Commit 57e70d6d authored by Brian Cavalier's avatar Brian Cavalier

Update to latest cujoJS releases: wire 0.10.0, curl 0.7.4, when 2.1.1

parent db9cb67d
......@@ -174,13 +174,8 @@ define({
}
},
plugins: [
// { module: 'wire/debug', trace: true },
{ module: 'wire/dom' },
{ module: 'wire/dom/render' },
{ module: 'wire/on' },
{ module: 'wire/aop' },
{ module: 'wire/connect' },
{ module: 'cola' }
plugins: [ //'wire/debug',
'wire/dom', 'wire/dom/render', 'wire/on',
'wire/aop', 'wire/connect', 'cola'
]
});
/*global curl */
(function (curl) {
// Bootstrap the app. Notice that curl is not a global, only define.
/*global define*/
define(['curl'], function (curl) {
'use strict';
curl({
......@@ -12,10 +13,9 @@
{ name: 'cola', location: 'bower_components/cola', main: 'cola' },
{ name: 'poly', location: 'bower_components/poly', main: 'poly' }
],
preloads: ['poly/string', 'poly/array'],
preloads: ['poly/es5'],
// Turn off i18n locale sniffing. Change or remove this line if you want to
// test specific locales or try automatic locale-sniffing.
locale: false
});
})(curl);
});
......@@ -2,12 +2,12 @@
"name": "todomvc-cujoJS",
"version": "0.0.0",
"dependencies": {
"todomvc-common": "~0.1.4",
"curl": "~0.7.3",
"todomvc-common": "~0.1.7",
"curl": "~0.7.4",
"cola": "latest",
"poly": "~0.5.1",
"when": "~2.1.0",
"wire": "~0.9.4",
"when": "~2.1.1",
"wire": "~0.10.0",
"meld": "~1.3.0"
}
}
[submodule "test/curl"]
path = test/curl
url = https://unscriptable@github.com/cujojs/curl.git
[submodule "test/util"]
path = test/util
url = https://unscriptable@github.com/cujojs/util.git
[submodule "support/when"]
path = support/when
url = https://github.com/cujojs/when.git
{
"name": "cola",
"version": "0.0.0",
"commit": "27b8c7e8fe88feef62a746d29d30af945dcb244d",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/cola"
}
}
\ No newline at end of file
{
"name": "curl",
"version": "0.7.3",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/curl"
}
}
\ No newline at end of file
{
"name": "curl",
"version": "0.7.3",
"description": "A small, fast module and resource loader with dependency management. (AMD, CommonJS Modules/1.1, CSS, HTML, etc.)",
"keywords": ["curl", "cujo", "amd", "loader", "module"],
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"repositories": [
{
"type": "git",
"url": "https://github.com/cujojs/curl"
}
],
"bugs": "https://github.com/cujojs/curl/issues",
"maintainers": [
{
"name": "John Hann",
"web": "http://unscriptable.com"
}
],
"contributors": [
{
"name": "John Hann",
"web": "http://unscriptable.com"
},
{
"name": "Brian Cavalier",
"web": "http://hovercraftstudios.com"
}
],
"main": "./src/curl",
"directories": {
"test": "test"
}
}
/** @license MIT License (c) copyright B Cavalier & J Hann */
/** @license MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl (cujo resource loader)
......@@ -13,9 +13,10 @@
(function (global) {
//"use strict"; don't restore this until the config routine is refactored
var
version = '0.7.3',
version = '0.7.4',
curlName = 'curl',
defineName = 'define',
runModuleAttr = 'data-curl-run',
userCfg,
prevCurl,
prevDefine,
......@@ -49,8 +50,9 @@
dontAddExtRx = /\?|\.js\b/,
absUrlRx = /^\/|^[^:]+:\/\//,
findDotsRx = /(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,
removeCommentsRx = /\/\*[\s\S]*?\*\/|(?:[^\\])\/\/.*?[\n\r]/g,
findRValueRequiresRx = /require\s*\(\s*["']([^"']+)["']\s*\)|(?:[^\\]?)(["'])/g,
removeCommentsRx = /\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g,
findRValueRequiresRx = /require\s*\(\s*(["'])(.*?[^\\])\1\s*\)|[^\\]?(["'])/g,
splitMainDirectives = /\s*,\s*/,
cjsGetters,
core;
......@@ -202,7 +204,7 @@
}
function isPromise (o) {
return o instanceof Promise;
return o instanceof Promise || o instanceof CurlApi;
}
function when (promiseOrValue, callback, errback, progback) {
......@@ -637,18 +639,6 @@
},
checkPreloads: function (cfg) {
var preloads;
preloads = cfg && cfg['preloads'];
if (preloads && preloads.length > 0) {
// chain from previous preload, if any.
when(preload, function () {
preload = core.getDeps(core.createContext(userCfg, undef, preloads, true));
});
}
},
resolvePathInfo: function (absId, cfg) {
// searches through the configured path mappings and packages
var pathMap, pathInfo, path, pkgCfg;
......@@ -744,8 +734,8 @@
defFunc :
defFunc.toSource ? defFunc.toSource() : defFunc.toString();
// remove comments, then look for require() or quotes
source.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, id, qq) {
// if we encounter a quote
source.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, rq, id, qq) {
// if we encounter a string in the source, don't look for require()
if (qq) {
currQuote = currQuote == qq ? undef : currQuote;
}
......@@ -971,22 +961,30 @@
},
fetchDep: function (depName, parentDef) {
var toAbsId, isPreload, cfg, parts, mainId, loaderId, pluginId,
var toAbsId, isPreload, cfg, parts, absId, mainId, loaderId, pluginId,
resId, pathInfo, def, tempDef, resCfg;
toAbsId = parentDef.toAbsId;
isPreload = parentDef.isPreload;
cfg = parentDef.config || userCfg; // is this fallback necessary?
absId = toAbsId(depName);
if (absId in cache) {
// module already exists in cache
mainId = absId;
}
else {
// check for plugin loaderId
// TODO: this runs pluginParts() twice. how to run it just once?
parts = pluginParts(toAbsId(depName));
parts = pluginParts(absId);
resId = parts.resourceId;
// get id of first resource to load (which could be a plugin)
mainId = parts.pluginId || resId;
pathInfo = core.resolvePathInfo(mainId, cfg);
}
// get custom module loader from package config if not a plugin
if (parts) {
if (parts.pluginId) {
loaderId = mainId;
}
......@@ -1002,6 +1000,7 @@
pathInfo = core.resolvePathInfo(loaderId, cfg);
}
}
}
if (mainId in cache) {
def = cache[mainId];
......@@ -1070,8 +1069,8 @@
// but to be compatible with AMD spec, we have to
// piggy-back on the callback function parameter:
var loaded = function (res) {
normalizedDef.resolve(res);
if (!dynamic) cache[fullId] = res;
normalizedDef.resolve(res);
};
loaded['resolve'] = loaded;
loaded['reject'] = loaded['error'] = normalizedDef.reject;
......@@ -1110,6 +1109,34 @@
}
}
return def;
},
findScript: function (predicate) {
var i = 0, script;
while (doc && (script = doc.scripts[i++])) {
if (predicate(script)) return script;
}
},
extractDataAttrConfig: function (cfg) {
var script;
script = core.findScript(function (script) {
var main;
// find main module(s) in data-curl-run attr on script element
// TODO: extract baseUrl, too?
main = script.getAttribute(runModuleAttr);
if (main) cfg.main = main;
return main;
});
// removeAttribute is wonky (in IE6?) but this works
if (script) {
script.setAttribute(runModuleAttr, '');
}
return cfg;
},
nextTurn: function (task) {
setTimeout(task, 0);
}
};
......@@ -1118,42 +1145,57 @@
cjsGetters = {'require': core.getCjsRequire, 'exports': core.getCjsExports, 'module': core.getCjsModule};
function _curl (/* various */) {
var args, promise, cfg;
var args = [].slice.call(arguments), cfg;
args = [].slice.call(arguments);
// extract config, if it's specified
if (isType(args[0], 'Object')) {
cfg = args.shift();
_config(cfg);
promise = _config(cfg);
}
return new CurlApi(args[0], args[1], args[2]);
return new CurlApi(args[0], args[1], args[2], promise);
}
function _config (cfg) {
function _config (cfg, callback, errback) {
var pPromise, mPromise, main, devmain, fallback;
if (cfg) {
core.setApi(cfg);
userCfg = core.config(cfg);
// check for preloads
core.checkPreloads(cfg);
// check for main module(s)
if ('main' in cfg) {
// start in next turn to wait for other modules in current file
setTimeout(function () {
var ctx;
ctx = core.createContext(userCfg, undef, [].concat(cfg['main']));
core.getDeps(ctx);
}, 0);
if ('preloads' in cfg) {
pPromise = new CurlApi(cfg['preloads'], undef, errback, preload, true);
// yes, this is hacky and embarrassing. now that we've got that
// settled... until curl has deferred factory execution, this
// is the only way to stop preloads from dead-locking when
// they have dependencies inside a bundle.
core.nextTurn(function () { preload = pPromise; });
}
// check for main module(s). all modules wait for preloads implicitly.
main = cfg['main'];
main = main && String(main).split(splitMainDirectives);
if (main) {
mPromise = new Promise();
mPromise.then(callback, errback);
// figure out if we are using a dev-time fallback
fallback = main[1]
? function () { new CurlApi(main[1], mPromise.resolve, mPromise.reject); }
: mPromise.reject;
new CurlApi(main[0], mPromise.resolve, fallback);
return mPromise;
}
}
}
// thanks to Joop Ringelberg for helping troubleshoot the API
function CurlApi (ids, callback, errback, waitFor) {
function CurlApi (ids, callback, errback, waitFor, isPreload) {
var then, ctx;
ctx = core.createContext(userCfg, undef, [].concat(ids));
this['then'] = then = function (resolved, rejected) {
ctx = core.createContext(userCfg, undef, [].concat(ids), isPreload);
this['then'] = this.then = then = function (resolved, rejected) {
when(ctx,
// return the dependencies as arguments, not an array
function (deps) {
......@@ -1166,13 +1208,22 @@
);
return this;
};
this['next'] = function (ids, cb, eb) {
// chain api
return new CurlApi(ids, cb, eb, ctx);
};
this['config'] = _config;
if (callback || errback) then(callback, errback);
when(waitFor, function () { core.getDeps(ctx); });
// ensure next-turn so inline code can execute first
core.nextTurn(function () {
when(isPreload || preload, function () {
when(waitFor, function () { core.getDeps(ctx); }, errback);
});
});
}
_curl['version'] = version;
......@@ -1232,18 +1283,23 @@
pathRx: /$^/
};
// look for "data-curl-run" directive, and override config
userCfg = core.extractDataAttrConfig(userCfg);
// handle pre-existing global
prevCurl = global[curlName];
prevDefine = global[defineName];
if (!prevCurl || isType(prevCurl, 'Function')) {
// set default api
core.setApi();
}
else {
// only run config if there is something to config (perf saver?)
if (prevCurl && isType(prevCurl, 'Object') || userCfg.main) {
// remove global curl object
global[curlName] = undef; // can't use delete in IE 6-8
// configure curl
_config(prevCurl);
_config(prevCurl || userCfg);
}
else {
// set default api
core.setApi();
}
// allow curl to be a dependency
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl debug plugin
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl domReady
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl CommonJS Modules/1.1 loader
......@@ -16,52 +16,13 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
var head, insertBeforeEl /*, findRequiresRx, myId*/;
// findRequiresRx = /require\s*\(\s*['"](\w+)['"]\s*\)/,
// function nextId (index) {
// var varname = '', part;
// do {
// part = index % 26;
// varname += String.fromCharCode(part + 65);
// index -= part;
// }
// while (index > 0);
// return 'curl$' + varname;
// }
// /**
// * @description Finds the require() instances in the source text of a cjs
// * module and collects them. If removeRequires is true, it also replaces
// * them with a unique variable name. All unique require()'d module ids
// * are assigned a unique variable name to be used in the define(deps)
// * that will be constructed to wrap the cjs module.
// * @param source - source code of cjs module
// * @param moduleIds - hashMap (object) to receive pairs of moduleId /
// * unique variable name
// * @param removeRequires - if truthy, replaces all require() instances with
// * a unique variable
// * @return - source code of cjs module, possibly with require()s replaced
// */
// function parseDepModuleIds (source, moduleIds, removeRequires) {
// var index = 0;
// // fast parse
// source = source.replace(findRequiresRx, function (match, id) {
// if (!moduleIds[id]) {
// moduleIds[id] = nextId(index++);
// moduleIds.push(id);
// }
// return removeRequires ? moduleIds[id] : match;
// });
// return source;
// }
head = document && (document['head'] || document.getElementsByTagName('head')[0]);
// to keep IE from crying, we need to put scripts before any
// <base> elements, but after any <meta>. this should do it:
insertBeforeEl = head && head.getElementsByTagName('base')[0] || null;
function wrapSource (source, resourceId, fullUrl) {
var sourceUrl = fullUrl ? '////@ sourceURL=' + fullUrl.replace(/\s/g, '%20') + '.js' : '';
var sourceUrl = fullUrl ? '/*\n////@ sourceURL=' + fullUrl.replace(/\s/g, '%20') + '.js\n*/' : '';
return "define('" + resourceId + "'," +
"['require','exports','module'],function(require,exports,module){" +
source + "\n});\n" + sourceUrl + "\n";
......@@ -82,8 +43,7 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
head.insertBefore(el, insertBeforeEl);
}
return {
'load': function (resourceId, require, callback, config) {
wrapSource['load'] = function (resourceId, require, callback, config) {
// TODO: extract xhr from text! plugin and use that instead (after we upgrade to cram.js)
require(['text!' + resourceId + '.js', 'curl/_privileged'], function (source, priv) {
var moduleMap;
......@@ -112,9 +72,12 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
}, callback['error'] || function (ex) { throw ex; });
});
}
};
wrapSource['cramPlugin'] = '../cram/cjsm11';
return wrapSource;
});
}(this, this.document, function () { /* FB needs direct eval here */ eval(arguments[0]); }));
define([], function () {
var xhr, progIds;
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
xhr = function () {
if (typeof XMLHttpRequest !== "undefined") {
// rewrite the getXhr method to always return the native implementation
xhr = function () {
return new XMLHttpRequest();
};
}
else {
// keep trying progIds until we find the correct one, then rewrite the getXhr method
// to always return that one.
var noXhr = xhr = function () {
throw new Error("getXhr(): XMLHttpRequest not available");
};
while (progIds.length > 0 && xhr === noXhr) (function (id) {
try {
new ActiveXObject(id);
xhr = function () {
return new ActiveXObject(id);
};
}
catch (ex) {
}
}(progIds.shift()));
}
return xhr();
};
function fetchText (url, callback, errback) {
var x = xhr();
x.open('GET', url, true);
x.onreadystatechange = function (e) {
if (x.readyState === 4) {
if (x.status < 400) {
callback(x.responseText);
}
else {
errback(new Error('fetchText() failed. status: ' + x.statusText));
}
}
};
x.send(null);
}
return fetchText;
});
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl async! plugin
......
/** MIT License (c) copyright B Cavalier & J Hann */
/**
* curl css! plugin build-time module
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
define(function () {
"use strict";
// collection of modules that have been written to the built file
var built = {};
function nameWithExt (name, defaultExt) {
return name.lastIndexOf('.') <= name.lastIndexOf('/') ?
name + '.' + defaultExt : name;
}
function jsEncode (text) {
// TODO: hoist the map and regex to the enclosing scope for better performance
var map = { 34: '\\"', 13: '\\r', 12: '\\f', 10: '\\n', 9: '\\t', 8: '\\b' };
return text.replace(/(["\n\f\t\r\b])/g, function (c) {
return map[c.charCodeAt(0)];
});
}
function parseSuffixes (name) {
// creates a dual-structure: both an array and a hashmap
// suffixes[0] is the actual name
var parts = name.split('!'),
suf, i = 1, pair;
while ((suf = parts[i++])) { // double-parens to avoid jslint griping
pair = suf.split('=', 2);
parts[pair[0]] = pair.length == 2 ? pair[1] : true;
}
return parts;
}
var
// this actually tests for absolute urls and root-relative urls
// they're both non-relative
nonRelUrlRe = /^\/|^[^:]*:\/\//,
// Note: this will fail if there are parentheses in the url
findUrlRx = /url\s*\(['"]?([^'"\)]*)['"]?\)/g;
function translateUrls (cssText, baseUrl) {
return cssText.replace(findUrlRx, function (all, url) {
return 'url("' + translateUrl(url, baseUrl) + '")';
});
}
function translateUrl (url, parentPath) {
// if this is a relative url
if (!nonRelUrlRe.test(url)) {
// append path onto it
url = parentPath + url;
}
return url;
}
function createSheetProxy (sheet) {
return {
cssRules: function () {
return sheet.cssRules || sheet.rules;
},
insertRule: sheet.insertRule || function (text, index) {
var parts = text.split(/\{|\}/g);
sheet.addRule(parts[0], parts[1], index);
return index;
},
deleteRule: sheet.deleteRule || function (index) {
sheet.removeRule(index);
return index;
},
sheet: function () {
return sheet;
}
};
}
/***** style element functions *****/
var currentStyle;
function createStyle (cssText) {
clearTimeout(createStyle.debouncer);
if (createStyle.accum) {
createStyle.accum.push(cssText);
}
else {
createStyle.accum = [cssText];
currentStyle = doc.createStyleSheet ? doc.createStyleSheet() :
head.appendChild(doc.createElement('style'));
}
createStyle.debouncer = setTimeout(function () {
// Note: IE 6-8 won't accept the W3C method for inserting css text
var style, allCssText;
style = currentStyle;
currentStyle = undef;
allCssText = createStyle.accum.join('\n');
createStyle.accum = undef;
// for safari which chokes on @charset "UTF-8";
allCssText = allCssText.replace(/.+charset[^;]+;/g, '');
// TODO: hoist all @imports to the top of the file to follow w3c spec
'cssText' in style ? style.cssText = allCssText :
style.appendChild(doc.createTextNode(allCssText));
}, 0);
return currentStyle;
}
/*
// return the run-time API
callback({
'translateUrls': function (cssText, baseId) {
var baseUrl;
baseUrl = require['toUrl'](baseId);
baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf('/') + 1);
return translateUrls(cssText, baseUrl);
},
'injectStyle': function (cssText) {
return createStyle(cssText);
},
'proxySheet': function (sheet) {
// for W3C, `sheet` is a reference to a <style> node so we need to
// return the sheet property.
if (sheet.sheet) sheet = sheet.sheet;
return createSheetProxy(sheet);
}
});
*/
return {
'build': function (writer, fetcher, config) {
// writer is a function used to output to the built file
// fetcher is a function used to fetch a text file
// config is the global config
// returns a function that the build tool can use to tell this
// plugin to write-out a resource
return function write (pluginId, resource, resolver) {
var opts, name, url, absId, text, output;
opts = parseSuffixes(resource);
name = opts.shift();
absId = resolver['toAbsMid'](name);
if (!(absId in built)) {
built[absId] = true;
url = resolver['toUrl'](nameWithExt(absId, 'css'));
// fetch text
text = jsEncode(fetcher(url));
// write out a define
// TODO: wait until sheet's rules are active before returning (use an amd promise)
// TODO: fix parser so that it doesn't choke on the word define( in a string
// TODO: write out api calls from this plugin-builder
output = 'def' + 'ine("' + pluginId + '!' + absId + '", ["' + pluginId + '!"], function (api) {\n' +
// translate urls
'\tvar cssText = "' + text + '";\n' +
'\tcssText = api.translateUrls(cssText, "' + absId + '");\n' +
// call the injectStyle function
'\treturn api.proxySheet(api.injectStyle(cssText));\n' +
'});\n';
writer(output);
}
};
}
};
});
define(function () {
return {
normalize: function (id, toAbsId) {
},
compile: function (absId, req, io, config) {
}
};
});
/** MIT License (c) copyright B Cavalier & J Hann */
/**
* curl text! loader builder plugin
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
define(function () {
"use strict";
// collection of modules that have been written to the built file
var built = {};
function nameWithExt (name, defaultExt) {
return name.lastIndexOf('.') <= name.lastIndexOf('/') ?
name + '.' + defaultExt : name;
}
function jsEncode (text) {
// TODO: hoist the map and regex to the enclosing scope for better performance
var map = { 34: '\\"', 13: '\\r', 12: '\\f', 10: '\\n', 9: '\\t', 8: '\\b' };
return text.replace(/(["\n\f\t\r\b])/g, function (c) {
return map[c.charCodeAt(0)];
});
}
return {
build: function (writer, fetcher, config) {
// writer is a function used to output to the built file
// fetcher is a function used to fetch a text file
// config is the global config
// returns a function that the build tool can use to tell this
// plugin to write-out a resource
return function write (pluginId, resource, resolver) {
var url, absId, text, output;
url = resolver['toUrl'](nameWithExt(resource, 'html'));
absId = resolver['toAbsMid'](resource);
if (!(absId in built)) {
built[absId] = true;
// fetch text
text = jsEncode(fetcher(url));
// write out a define
output = 'define("' + pluginId + '!' + absId + '", function () {\n' +
'\treturn "' + text + '";\n' +
'});\n';
writer(output);
}
};
}
};
});
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl css! plugin
......@@ -573,8 +573,7 @@
},
'plugin-builder': './builder/css',
'pluginBuilder': './builder/css'
'cramPlugin': '../cram/css'
});
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl domReady loader plugin
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl i18n plugin
......@@ -85,7 +85,7 @@
*
*/
(function (global) {
(function (window) {
define(/*=='curl/plugin/i18n',==*/ function () {
......@@ -96,6 +96,7 @@ define(/*=='curl/plugin/i18n',==*/ function () {
appendLocaleRx = /(\.js)?$/;
return {
load: function (absId, require, loaded, config) {
var eb, toFile, locale, bundles, fetched, id, ids, specifiers, i;
......@@ -160,7 +161,10 @@ define(/*=='curl/plugin/i18n',==*/ function () {
}
}
}
},
'cramPlugin': '../cram/i18n'
};
function fetch (require, id, i, cb, eb) {
......@@ -177,7 +181,9 @@ define(/*=='curl/plugin/i18n',==*/ function () {
}
function getLocale () {
var ci = global['clientInformation'] || global.navigator;
var ci;
if (!window) return false;
ci = window['clientInformation'] || window.navigator;
return ci.language || ci['userLanguage'];
}
......@@ -187,4 +193,4 @@ define(/*=='curl/plugin/i18n',==*/ function () {
});
}(this));
}(typeof window != 'undefined' && window));
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl js! plugin
......@@ -191,7 +191,9 @@ define(/*=='curl/plugin/js',==*/ ['curl/_privileged'], function (priv) {
}
}
}
},
'cramPlugin': '../cram/js'
};
});
......
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl json! plugin
*
* Like the text! plugin, will only load same-domain resources.
*/
(function (globalEval) {
define(/*=='curl/plugin/json',==*/ ['./_fetchText'], function (fetchText) {
var hasJsonParse, missingJsonMsg;
hasJsonParse = typeof JSON != 'undefined' && JSON.parse;
missingJsonMsg = 'Cannot use strictJSONParse without JSON.parse';
return {
load: function (absId, require, loaded, config) {
var evaluator, errback;
errback = loaded['error'] || error;
// create a json evaluator function
if (config.strictJSONParse) {
if (!hasJsonParse) error(new Error(missingJsonMsg));
evaluator = guard(parseSource, loaded, errback);
}
else {
evaluator = guard(evalSource, loaded, errback);
}
// get the text, then eval it
fetchText(require['toUrl'](absId), evaluator, errback);
function evalSource (source) {
loaded(globalEval('(' + source + ')'));
}
function parseSource (source) {
return JSON.parse(source);
}
},
'cramPlugin': '../cram/json'
};
function error (ex) {
throw ex;
}
function guard (evaluator, success, fail) {
return function (source) {
try {
success(evaluator(source));
}
catch (ex) {
fail(ex);
}
}
}
});
}(
function () {/*jshint evil:true*/ return (1,eval)(arguments[0]); }
));
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl link! plugin
......
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl style! plugin
*/
define([], function () {
var nonRelUrlRe, findUrlRx, undef, doc, head;
if (typeof window != 'undefined') {
doc = window.document;
head = doc.head || doc.getElementsByTagName('head')[0];
}
// tests for absolute urls and root-relative urls
nonRelUrlRe = /^\/|^[^:]*:\/\//;
// Note: this will fail if there are parentheses in the url
findUrlRx = /url\s*\(['"]?([^'"\)]*)['"]?\)/g;
function translateUrls (cssText, baseUrl) {
return cssText.replace(findUrlRx, function (all, url) {
return 'url("' + translateUrl(url, baseUrl) + '")';
});
}
function translateUrl (url, parentPath) {
// if this is a relative url
if (!nonRelUrlRe.test(url)) {
// append path onto it
url = parentPath + url;
}
return url;
}
/***** style element functions *****/
var currentStyle, callbacks = [];
function createStyle (cssText, callback, errback) {
try {
clearTimeout(createStyle.debouncer);
if (createStyle.accum) {
createStyle.accum.push(cssText);
}
else {
createStyle.accum = [cssText];
currentStyle = doc.createStyleSheet ? doc.createStyleSheet() :
head.appendChild(doc.createElement('style'));
}
callbacks.push({
callback: callback,
errback: errback,
sheet: currentStyle
});
createStyle.debouncer = setTimeout(function () {
var style, allCssText;
try {
style = currentStyle;
currentStyle = undef;
allCssText = createStyle.accum.join('\n');
createStyle.accum = undef;
// for safari which chokes on @charset "UTF-8";
// TODO: see if Safari 5.x and up still complain
allCssText = allCssText.replace(/.+charset[^;]+;/g, '');
// IE 6-8 won't accept the W3C method for inserting css text
'cssText' in style ? style.cssText = allCssText :
style.appendChild(doc.createTextNode(allCssText));
waitForDocumentComplete(notify);
}
catch (ex) {
// just notify most recent errback. no need to spam
errback(ex);
}
}, 0);
}
catch (ex) {
errback(ex);
}
}
function notify () {
var list = callbacks;
callbacks = [];
for (var i = 0, len = list.length; i < len; i++) {
list[i].callback(list[i].sheet);
}
}
/**
* Keep checking for the document readyState to be "complete" since
* Chrome doesn't apply the styles to the document until that time.
* If we return before readyState == 'complete', Chrome may not have
* applied the styles, yet.
* Chrome only.
* @private
* @param cb
*/
function waitForDocumentComplete (cb) {
// this isn't exactly the same as domReady (when dom can be
// manipulated). it's later (when styles are applied).
// chrome needs this (and opera?)
function complete () {
if (isDocumentComplete()) {
cb();
}
else {
setTimeout(complete, 10);
}
}
complete();
}
/**
* Returns true if the documents' readyState == 'complete' or the
* document doesn't implement readyState.
* Chrome only.
* @private
* @return {Boolean}
*/
function isDocumentComplete () {
return !doc.readyState || doc.readyState == 'complete';
}
createStyle.load = function (absId, req, loaded, config) {
// get css text
req([absId], function (cssText) {
// TODO: translate urls?
createStyle(cssText, loaded, loaded.error);
});
};
createStyle.translateUrls = translateUrls;
return createStyle;
});
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl text! loader plugin
......@@ -8,62 +8,18 @@
*/
/**
* TODO: load xdomain text, too
* TODO: load xdomain text, too, somehow
*
*/
define(/*=='curl/plugin/text',==*/ function () {
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
function xhr () {
if (typeof XMLHttpRequest !== "undefined") {
// rewrite the getXhr method to always return the native implementation
xhr = function () { return new XMLHttpRequest(); };
}
else {
// keep trying progIds until we find the correct one, then rewrite the getXhr method
// to always return that one.
var noXhr = xhr = function () {
throw new Error("getXhr(): XMLHttpRequest not available");
};
while (progIds.length > 0 && xhr === noXhr) (function (id) {
try {
new ActiveXObject(id);
xhr = function () { return new ActiveXObject(id); };
}
catch (ex) {}
}(progIds.shift()));
}
return xhr();
}
function fetchText (url, callback, errback) {
var x = xhr();
x.open('GET', url, true);
x.onreadystatechange = function (e) {
if (x.readyState === 4) {
if (x.status < 400) {
callback(x.responseText);
}
else {
errback(new Error('fetchText() failed. status: ' + x.statusText));
}
}
};
x.send(null);
}
function error (ex) {
throw ex;
}
define(/*=='curl/plugin/text',==*/ ['./_fetchText'], function (fetchText) {
return {
// 'normalize': function (resourceId, toAbsId) {
// // remove options
// return resourceId ? toAbsId(resourceId.split("!")[0]) : resourceId;
// },
'normalize': function (resourceId, toAbsId) {
// remove options
return resourceId ? toAbsId(resourceId.split("!")[0]) : resourceId;
},
load: function (resourceName, req, callback, config) {
// remove suffixes (future)
......@@ -71,8 +27,12 @@ define(/*=='curl/plugin/text',==*/ function () {
fetchText(req['toUrl'](resourceName), callback, callback['error'] || error);
},
'plugin-builder': './builder/text'
'cramPlugin': '../cram/text'
};
function error (ex) {
throw ex;
}
});
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl dojo 1.6 shim
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl ssjs shim
......@@ -59,6 +59,10 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) {
localLoadFunc = remoteLoadFunc = failIfInvoked;
}
if (typeof process === 'object' && process.nextTick) {
priv.core.nextTurn = process.nextTick;
}
function stripExtension (url) {
return url.replace(/\.js$/, '');
}
......@@ -136,5 +140,9 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) {
: protocol;
}
function _nextTick (func) {
nextTick(func);
}
});
}(require, load));
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl createContext module
......@@ -266,6 +266,7 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin
function createTrackedRequire (require, modulesAllFetched) {
var callCount = 0;
function trackedRequire (idOrArray, callback) {
var cb;
......@@ -277,12 +278,14 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin
if (--callCount == 0) modulesAllFetched();
};
// preserve AMD API
trackedRequire.toUrl = require.toUrl;
return require(idOrArray, cb);
}
// preserve AMD API
trackedRequire.toUrl = require.toUrl;
// helpful
trackedRequire.notAsync = function () { return callCount == 0; };
return trackedRequire;
}
......
/** MIT License (c) copyright B Cavalier & J Hann */
/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/**
* curl createContext module
......
root = true
[*]
indent_style = tab
end_of_line = LF
\ No newline at end of file
.idea/
.npmignore
node_modules/
projectFilesBackup/
{
"browser": true,
"node": true,
"es5": true,
"predef": [
"define",
"module"
],
"boss": true,
"curly": true,
"eqnull": true,
"expr": true,
"globalstrict": false,
"laxbreak": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"quotmark": "single",
"strict": false,
"trailing": true,
"undef": true,
"unused": true,
"maxdepth": 4,
"maxcomplexity": 6
}
\ No newline at end of file
### 1.3.0
* [`meld()`](docs/api.md#adding-aspects) is now a function that adds aspects.
* **DEPRECATED:** `meld.add()`. Use `meld()` instead.
### 1.2.2
* Remove stray `console.log`.
### 1.2.1
* Fix for IE8-specific issue with meld's internal use of `Object.defineProperty`.
* Internally shim Object.create if not available to so that meld no longer requires an Object.create shim to advise constructors in pre-ES5 environments.
### 1.2.0
* `meld.joinpoint()` - [Access the current joinpoint](docs/api.md#meldjoinpoint) from any advice type.
* [Bundled aspects](docs/aspects.md):
* trace: trace method call entry/return/throw
* memoize: simple memoization for methods and functions
* cache: configurable caching aspect to do more than simple memoization
### 1.1.0
* Advice can be applied directly to methods on a function.
* Removed undocumented behavior that implicitly adds constructor prototype advice: to advise a prototype, pass the prototype as the advice target.
### 1.0.0
* **Removed browser global** - `window.meld` is no longer supported. See [this post on the cujo.js Google Group](https://groups.google.com/d/topic/cujojs/K0VGuvpYQ34/discussion) for an explanation.
* No functional change beyond browser global removal.
### 0.8.0
* 1.0.0 Release Candidate 1
* Documentation! Check out the new [reference](docs/reference.md) and [api](docs/api.md) docs.
* **Deprecated browser global** - meld.js will drop support for browser global for 1.0.0 and will support modular environments only.
### 0.7.2
* Fix for context when advising constructors: `this` is now the constructed instance in all advice functions.
### 0.7.1
* Fix for global name when using meld as a browser global. Thanks [@scothis](https://github.com/scothis)
* Update unit tests to run in browser using `buster server`, in addition to node. Thanks again, [@scothis](https://github.com/scothis) :)
### 0.7.0
* Advice can be applied directly to functions without a context.
* Advice can be applied to constructors.
* `joinpoint.proceed()` can be called multiple times. This makes it possible to implement "retry" types of advice.
### 0.6.0
* aop.js is now meld.js
* Use [Travis CI](http://travis-ci.org/cujojs/meld)
### 0.5.4
* Optimizations to run time advice invocation, especially around advice
* Fix for passing new args to `joinpoint.proceed()` in around advice
* Added `joinpoint.proceedApply(array)` for proceeding and supplying new arguments as an array
* Ported unit tests to [BusterJS](http://busterjs.org)
### 0.5.3
* First official release as part of [cujojs](http://github.com/cujojs)
* Minor doc and package.json tweaks
### 0.5.2
* Revert to larger, more builder-friendly module boilerplate. No functional change.
### 0.5.1
* Minor corrections and updates to `package.json`
### 0.5.0
* Rewritten Advisor that allows entire aspects to be unwoven (removed) easily.
\ No newline at end of file
[![Build Status](https://secure.travis-ci.org/cujojs/meld.png)](http://travis-ci.org/cujojs/meld)
[Aspect Oriented Programming](http://en.wikipedia.org/wiki/Aspect-oriented_programming "Aspect-oriented programming - Wikipedia, the free encyclopedia") for Javascript. It allows you to change the behavior of, or add behavior to methods and functions (including constructors) *non-invasively*.
As a simple example, instead of changing code, you can use meld to log the result of `myObject.doSomething`:
```js
var myObject = {
doSomething: function(a, b) {
return a + b;
}
};
// Call a function after myObject.doSomething returns
var remover = meld.after(myObject, 'doSomething', function(result) {
console.log('myObject.doSomething returned: ' + result);
});
myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3"
remover.remove();
myObject.doSomething(1, 2); // Nothing logged
```
# Docs
* [API](docs/api.md)
* [Reference](docs/reference.md)
* [Aspects](docs/aspects.md)
# Quick Start
### AMD
1. Get it using one of the following
1. `yeoman install meld`, or
1. `bower install meld`, or
1. `git clone https://github.com/cujojs/meld`, or
1. `git submodule add https://github.com/cujojs/meld`
1. Configure your loader with a package:
```js
packages: [
{ name: 'meld', location: 'path/to/meld', main: 'meld' },
// ... other packages ...
]
```
1. `define(['meld', ...], function(meld, ...) { ... });` or `require(['meld', ...], function(meld, ...) { ... });`
### Node
1. `npm install meld`
1. `var meld = require('meld');`
### RingoJS
1. `ringo-admin install cujojs/meld`
1. `var meld = require('meld');`
Running the Unit Tests
======================
Install [buster.js](http://busterjs.org/)
`npm install -g buster`
Run unit tests in Node:
`buster test`
# What's New
### 1.3.0
* [`meld()`](docs/api.md#adding-aspects) is now a function that adds aspects.
* **DEPRECATED:** `meld.add()`. Use `meld()` instead.
### 1.2.2
* Remove stray `console.log`.
### 1.2.1
* Fix for IE8-specific issue with meld's internal use of `Object.defineProperty`.
* Internally shim Object.create if not available to so that meld no longer requires an Object.create shim to advise constructors in pre-ES5 environments.
### 1.2.0
* `meld.joinpoint()` - [Access the current joinpoint](docs/api.md#meldjoinpoint) from any advice type.
* [Bundled aspects](docs/aspects.md):
* trace: trace method call entry/return/throw
* memoize: simple memoization for methods and functions
* cache: configurable caching aspect to do more than simple memoization
### 1.1.0
* Advice can be applied directly to methods on a function.
* Removed undocumented behavior that implicitly adds constructor prototype advice: to advise a prototype, pass the prototype as the advice target.
### 1.0.0
* **Removed browser global** - `window.meld` is no longer supported. See [this post on the cujo.js Google Group](https://groups.google.com/d/topic/cujojs/K0VGuvpYQ34/discussion) for an explanation.
* No functional change beyond browser global removal.
See the [full Changelog here](CHANGES.md)
# References
* [AspectJ](http://www.eclipse.org/aspectj/) and [Spring Framework AOP](http://static.springsource.org/spring/docs/3.0.x/reference/meld.html) for inspiration and great docs
* Implementation ideas from @phiggins42's [uber.js AOP](https://github.com/phiggins42/uber.js/blob/master/lib/meld.js)
* API ideas from [jquery-aop](http://code.google.com/p/jquery-aop/)
\ No newline at end of file
{
"name": "meld",
"version": "1.3.0",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/meld.git"
}
}
\ No newline at end of file
{
"name": "meld",
"version": "1.3.0",
"description": "AOP for JS with before, around, on, afterReturning, afterThrowing, after advice, and pointcut support",
"keywords": ["aop", "aspect", "cujo"],
"homepage": "http://cujojs.com",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"repositories": [
{
"type": "git",
"url": "https://github.com/cujojs/meld"
}
],
"bugs": "https://github.com/cujojs/meld/issues",
"maintainers": [
{
"name": "Brian Cavalier",
"web": "http://hovercraftstudios.com"
},
{
"name": "John Hann",
"web": "http://unscriptable.com"
}
],
"contributors": [
{
"name": "Brian Cavalier",
"web": "http://hovercraftstudios.com"
},
{
"name": "John Hann",
"web": "http://unscriptable.com"
},
{
"name": "Scott Andrews"
}
],
"devDependencies": {
"buster": "~0.6",
"jshint": "~1"
},
"main": "meld",
"directories": {
"test": "test"
},
"scripts": {
"test": "jshint . && buster test -e node"
}
}
\ No newline at end of file
/**
* polyfill / shim plugin for AMD loaders
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
......@@ -9,7 +9,7 @@
* http://www.opensource.org/licenses/mit-license.php
*/
define(['./object', './string', './date', './array', './function', './json', './xhr'], function (object, string, date) {
define(['./object', './string', './date', './array', './function', './json', './xhr', './setImmediate'], function (object, string, date) {
return {
failIfShimmed: object.failIfShimmed,
......
......@@ -2,7 +2,7 @@
Array -- a stand-alone module for using Javascript 1.6 array features
in lame-o browsers that don't support Javascript 1.6
(c) copyright 2011-2012 Brian Cavalier and John Hann
(c) copyright 2011-2013 Brian Cavalier and John Hann
This module is part of the cujo.js family of libraries (http://cujojs.com/).
......
{
"name": "poly",
"version": "0.5.1",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/poly"
}
}
\ No newline at end of file
......@@ -3,7 +3,7 @@
ES5-ish Date shims for older browsers.
(c) copyright 2011-2012 Brian Cavalier and John Hann
(c) copyright 2011-2013 Brian Cavalier and John Hann
This module is part of the cujo.js family of libraries (http://cujojs.com/).
......@@ -20,11 +20,14 @@ define(['./lib/_base'], function (base) {
invalidDate,
isoCompat,
isoParseRx,
ownProp,
undef;
origProto = origDate.prototype;
origParse = origDate.parse;
ownProp = Object.prototype.hasOwnProperty;
maxDate = 8.64e15;
invalidDate = NaN;
// borrowed this from https://github.com/kriskowal/es5-shim
......@@ -119,6 +122,7 @@ define(['./lib/_base'], function (base) {
}
if (!has('date-tojson')) {
origProto.toJSON = function toJSON (key) {
// key arg is ignored by Date objects, but since this function
// is generic, other Date-like objects could use the key arg.
......@@ -129,39 +133,42 @@ define(['./lib/_base'], function (base) {
}
function checkIsoCompat () {
if (!isoCompat()) {
// fix Date constructor
function Date_ (y, m, d, h, mn, s, ms) {
var newDate = (function () {
// Replacement Date constructor
return function Date (y, m, d, h, mn, s, ms) {
var len, result;
// Date_ called as function, not constructor
if (!(this instanceof Date_)) return origDate.apply(this, arguments);
// Date called as function, not constructor
if (!(this instanceof newDate)) return origDate.apply(this, arguments);
len = arguments.length;
if (len == 0) {
if (len === 0) {
result = new origDate();
}
else if (len == 1) {
result = new origDate(base.isString(y) ? Date.parse(y) : y);
else if (len === 1) {
result = new origDate(base.isString(y) ? newDate.parse(y) : y);
}
else {
result = new origDate(y, m, d == undef ? 1 : d, h || 0, mn || 0, s || 0, ms || 0);
}
result.constructor = Date_;
result.constructor = newDate;
return result;
}
};
}());
if (!isoCompat()) {
Date_.now = origDate.now;
Date_.UTC = origDate.UTC;
Date_.prototype = origProto;
Date_.prototype.constructor = Date_;
newDate.now = origDate.now;
newDate.UTC = origDate.UTC;
newDate.prototype = origProto;
newDate.prototype.constructor = newDate;
Date_.parse = function parse (str) {
newDate.parse = function parse (str) {
var result;
// check for iso date
......@@ -175,11 +182,25 @@ define(['./lib/_base'], function (base) {
return result;
};
Date = Date_;
// Unfortunate. See cujojs/poly#11
// Copy any owned props that may have been previously added to
// the Date constructor by 3rd party libs.
copyPropsSafely(newDate, origDate);
Date = newDate;
}
else if (Date != origDate) {
Date = origDate;
}
}
function copyPropsSafely(dst, src) {
for (var p in src) {
if (ownProp.call(src, p) && !ownProp.call(dst, p)) {
dst[p] = src[p];
}
}
}
checkIsoCompat();
......
/*
poly/strict
(c) copyright 2011-2013 Brian Cavalier and John Hann
This module is part of the cujo.js family of libraries (http://cujojs.com/).
Licensed under the MIT License at:
http://www.opensource.org/licenses/mit-license.php
*/
define(['./object', './string', './date', './array', './function', './json', './xhr'], function (object, string, date) {
var failTestRx;
failTestRx = /^define|^prevent|descriptor$/i;
function regexpShouldThrow (feature) {
return failTestRx.test(feature);
}
// set unshimmable Object methods to be somewhat strict:
object.failIfShimmed(regexpShouldThrow);
// set strict whitespace
string.setWhitespaceChars('\\s');
return {
failIfShimmed: object.failIfShimmed,
setWhitespaceChars: string.setWhitespaceChars,
setIsoCompatTest: date.setIsoCompatTest
};
});
/**
* polyfill / shim plugin for AMD loaders
*
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
define(['./object', './string', './date', './array', './function', './json', './xhr'], function (object, string, date) {
return {
failIfShimmed: object.failIfShimmed,
setWhitespaceChars: string.setWhitespaceChars,
setIsoCompatTest: date.setIsoCompatTest
};
});
/**
* Function polyfill / shims
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* This module is part of the cujo.js family of libraries (http://cujojs.com/).
*
......
/**
* JSON polyfill / shim
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* TODO: document that JSON module is always downloaded at run-time unless
* dev explicitly mentions it in build instructions
*/
define(['./lib/_async!./lib/_json'], function (JSON) {
define(['./support/json3'], function (JSON) {
return JSON;
});
/**
* async plugin for AMD loaders
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
*/
define(function () {
return {
load: function (def, require, onload, config) {
function success (module) {
// check for curl.js's promise
onload.resolve ? onload.resolve(module) : onload(module);
}
function fail (ex) {
// check for curl.js's promise
if (onload.reject) {
onload.reject(ex)
}
else {
throw ex;
}
}
// load module. wait for it if it returned a promise
require([def], function (module) {
if (module && typeof module.then == 'function') {
module.then(success, fail);
}
else {
success(module);
}
});
}
};
});
/**
* poly common functions
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* This module is part of the cujo.js family of libraries (http://cujojs.com/).
*
......
/**
* JSON polyfill / shim
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
(function (global) {
define(['require'], function (require) {
var cbs, ebs, promise;
function has (feature) {
return global.JSON;
}
if (!has('json')) {
cbs = [];
ebs = [];
promise = {
then: function (cb, eb) {
if (cb) cbs.push(cb);
if (eb) ebs.push(eb);
}
};
function callback (list, val) {
promise.then = list == cbs
? function (cb, eb) { cb(val); }
: function (cb, eb) { eb(val); }
for (var i = 0; i < list.length; i++) list[i](val);
}
function resolve (val) {
callback(cbs, val);
}
function reject (ex) {
callback(ebs, ex);
}
require(['../support/json2'], resolve, reject);
return promise;
}
});
}(this));
/**
* Object polyfill / shims
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* This module is part of the cujo.js family of libraries (http://cujojs.com/).
*
......@@ -52,24 +52,45 @@
* IE missing enum properties fixes copied from kangax:
* https://github.com/kangax/protolicious/blob/master/experimental/object.for_in.js
*
* TODO: fix Object#propertyIsEnumerable for IE's non-enumerable props to match Object.keys()
*/
define(['./lib/_base'], function (base) {
"use strict";
var refObj,
refProto,
has__proto__,
hasNonEnumerableProps,
getPrototypeOf,
keys,
featureMap,
shims,
secrets,
protoSecretProp,
hasOwnProp = 'hasOwnProperty',
undef;
refObj = Object;
refProto = refObj.prototype;
getPrototypeOf = typeof {}.__proto__ == 'object'
? function (object) { return object.__proto__; }
: function (object) { return object.constructor ? object.constructor.prototype : refProto; };
has__proto__ = typeof {}.__proto__ == 'object';
hasNonEnumerableProps = (function () {
for (var p in { valueOf: 1 }) return false;
return true;
}());
// TODO: this still doesn't work for IE6-8 since object.constructor && object.constructor.prototype are clobbered/replaced when using `new` on a constructor that has a prototype. srsly.
// devs will have to do the following if they want this to work in IE6-8:
// Ctor.prototype.constructor = Ctor
getPrototypeOf = has__proto__
? function (object) { assertIsObject(object); return object.__proto__; }
: function (object) {
assertIsObject(object);
return protoSecretProp && object[protoSecretProp](secrets)
? object[protoSecretProp](secrets.proto)
: object.constructor ? object.constructor.prototype : refProto;
};
keys = !hasNonEnumerableProps
? _keys
......@@ -81,7 +102,7 @@ define(['./lib/_base'], function (base) {
}
return result;
}
}([ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ]));
}([ 'constructor', hasOwnProp, 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ]));
featureMap = {
'object-create': 'create',
......@@ -101,10 +122,11 @@ define(['./lib/_base'], function (base) {
shims = {};
function hasNonEnumerableProps () {
for (var p in { toString: 1 }) return false;
return true;
}
secrets = {
proto: {}
};
protoSecretProp = !has('object-getprototypeof') && !has__proto__ && hasNonEnumerableProps && hasOwnProp;
function createFlameThrower (feature) {
return function () {
......@@ -134,6 +156,15 @@ define(['./lib/_base'], function (base) {
return result;
}
// we might create an owned property to hold the secrets, but make it look
// like it's not an owned property. (affects getOwnPropertyNames, too)
if (protoSecretProp) (function (_hop) {
refProto[hasOwnProp] = function (name) {
if (name == protoSecretProp) return false;
return _hop.call(this, name);
};
}(refProto[hasOwnProp]));
if (!has('object-create')) {
Object.create = shims.create = function create (proto, props) {
var obj;
......@@ -141,11 +172,21 @@ define(['./lib/_base'], function (base) {
if (typeof proto != 'object') throw new TypeError('prototype is not of type Object or Null.');
PolyBase.prototype = proto;
obj = new PolyBase(props);
obj = new PolyBase();
PolyBase.prototype = null;
// provide a mechanism for retrieving the prototype in IE 6-8
if (protoSecretProp) {
var orig = obj[protoSecretProp];
obj[protoSecretProp] = function (name) {
if (name == secrets) return true; // yes, we're using secrets
if (name == secrets.proto) return proto;
return orig.call(this, name);
};
}
if (arguments.length > 1) {
// defineProperties could throw depending on `shouldThrow`
// defineProperties could throw depending on `failIfShimmed`
Object.defineProperties(obj, props);
}
......@@ -264,8 +305,7 @@ define(['./lib/_base'], function (base) {
}
}
// this is effectively a no-op, so why execute it?
//failIfShimmed(false);
function assertIsObject (o) { if (typeof o != 'object') throw new TypeError('Object.getPrototypeOf called on non-object'); }
return {
failIfShimmed: failIfShimmed
......
/**
* polyfill / shim plugin for AMD loaders
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* @version 0.5.1
*/
define(['./all'], function (all) {
......@@ -18,7 +17,7 @@ define(['./all'], function (all) {
// copy all
for (var p in all) poly[p] = all[p];
poly.version = '0.5.1';
poly.version = '0.5.2';
return poly;
......
/**
* setImmediate polyfill / shim
*
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* poly is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Based on NobleJS's setImmediate. (https://github.com/NobleJS/setImmediate)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
*/
(function (global) {
define(['./lib/_base'], function (base) {
var testCache,
tasks;
testCache = {};
tasks = (function () {
var nextHandle,
tasksByHandle,
currentlyRunningATask;
nextHandle = 1; // Spec says greater than zero
tasksByHandle = {};
currentlyRunningATask = false;
function Task (handler, args) {
this.handler = handler;
this.args = Array.prototype.slice.call(args);
}
Task.prototype.run = function () {
// See steps in section 5 of the spec.
if (base.isFunction(this.handler)) {
// Choice of `thisArg` is not in the setImmediate spec; `undefined` is in the setTimeout spec though:
// http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html
this.handler.apply(undefined, this.args);
}
else {
var scriptSource = '' + this.handler;
eval(scriptSource);
}
};
return {
addFromSetImmediateArguments: function (args) {
var handler,
argsToHandle,
task,
thisHandle;
handler = args[0];
argsToHandle = Array.prototype.slice.call(args, 1);
task = new Task(handler, argsToHandle);
thisHandle = nextHandle++;
tasksByHandle[thisHandle] = task;
return thisHandle;
},
runIfPresent: function (handle) {
// From the spec: "Wait until any invocations of this algorithm started before this one have completed."
// So if we're currently running a task, we'll need to delay this invocation.
if (!currentlyRunningATask) {
var task = tasksByHandle[handle];
if (task) {
currentlyRunningATask = true;
try {
task.run();
} finally {
delete tasksByHandle[handle];
currentlyRunningATask = false;
}
}
} else {
// Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
// "too much recursion" error.
global.setTimeout(function () {
tasks.runIfPresent(handle);
}, 0);
}
},
remove: function (handle) {
delete tasksByHandle[handle];
}
};
}());
function has (name) {
if (base.isFunction(testCache[name])) {
testCache[name] = testCache[name](global);
}
return testCache[name];
}
function add (name, test, now) {
testCache[name] = now ? test(global, d, el) : test;
}
function aliasMicrosoftImplementation (attachTo) {
attachTo.setImmediate = global.msSetImmediate;
attachTo.clearImmediate = global.msClearImmediate;
}
function installPostMessageImplementation (attachTo) {
// Installs an event handler on `global` for the `message` event: see
// * https://developer.mozilla.org/en/DOM/window.postMessage
// * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
var MESSAGE_PREFIX = 'cujojs/poly.setImmediate' + Math.random();
function isStringAndStartsWith (string, putativeStart) {
return typeof string === 'string' && string.substring(0, putativeStart.length) === putativeStart;
}
function onGlobalMessage (event) {
// This will catch all incoming messages (even from other windows!), so we need to try reasonably hard to
// avoid letting anyone else trick us into firing off. We test the origin is still this window, and that a
// (randomly generated) unpredictable identifying prefix is present.
if (event.source === global && isStringAndStartsWith(event.data, MESSAGE_PREFIX)) {
var handle = event.data.substring(MESSAGE_PREFIX.length);
tasks.runIfPresent(handle);
}
}
global.addEventListener('message', onGlobalMessage, false);
attachTo.setImmediate = function () {
var handle = tasks.addFromSetImmediateArguments(arguments);
// Make `global` post a message to itself with the handle and identifying prefix, thus asynchronously
// invoking our onGlobalMessage listener above.
global.postMessage(MESSAGE_PREFIX + handle, '*');
return handle;
};
}
function installReadyStateChangeImplementation(attachTo) {
attachTo.setImmediate = function () {
var handle = tasks.addFromSetImmediateArguments(arguments);
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {
tasks.runIfPresent(handle);
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global.document.documentElement.appendChild(scriptEl);
return handle;
};
}
function installSetTimeoutImplementation(attachTo) {
attachTo.setImmediate = function () {
var handle = tasks.addFromSetImmediateArguments(arguments);
global.setTimeout(function () {
tasks.runIfPresent(handle);
}, 0);
return handle;
};
}
add('setimmediate', function (g) {
return base.isFunction(g.setImmediate);
});
add('ms-setimmediate', function (g) {
return base.isFunction(g.msSetImmediate);
});
add('post-message', function (g) {
// Note: this is only for the async postMessage, not the buggy sync
// version in IE8
var postMessageIsAsynchronous,
oldOnMessage;
postMessageIsAsynchronous = true;
oldOnMessage = g.onmessage;
if (!g.postMessage) {
return false;
}
g.onmessage = function () {
postMessageIsAsynchronous = false;
};
g.postMessage('', '*');
g.onmessage = oldOnMessage;
return postMessageIsAsynchronous;
});
add('script-onreadystatechange', function (g) {
return 'document' in g && 'onreadystatechange' in g.document.createElement('script');
});
if (!has('setimmediate')) {
if (has('ms-setimmediate')) {
aliasMicrosoftImplementation(global);
}
else {
if (has('post-message')) {
installPostMessageImplementation(global);
}
else if (has('script-onreadystatechange')) {
installReadyStateChangeImplementation(global);
}
else {
installSetTimeoutImplementation(global);
}
global.clearImmediate = tasks.remove;
}
}
});
}(this.global || this));
/*
poly/strict
(c) copyright 2011-2012 Brian Cavalier and John Hann
(c) copyright 2011-2013 Brian Cavalier and John Hann
This module is part of the cujo.js family of libraries (http://cujojs.com/).
Licensed under the MIT License at:
http://www.opensource.org/licenses/mit-license.php
*/
/**
* @deprecated Please use poly/es5-strict
*/
define(['./object', './string', './date', './array', './function', './json', './xhr'], function (object, string, date) {
var failTestRx;
......
/**
* String polyfill / shims
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* This module is part of the cujo.js family of libraries (http://cujojs.com/).
*
......
/**
* XHR polyfill / shims
*
* (c) copyright 2011-2012 Brian Cavalier and John Hann
* (c) copyright 2011-2013 Brian Cavalier and John Hann
*
* This module is part of the cujo.js family of libraries (http://cujojs.com/).
*
......@@ -9,34 +9,31 @@
* http://www.opensource.org/licenses/mit-license.php
*
*/
define(['./lib/_base'], function (base) {
define(function () {
var progIds, xhrCtor;
var progIds;
// find XHR implementation
if (typeof XMLHttpRequest == 'undefined') {
// create xhr impl that will fail if called.
assignCtor(function () { throw new Error("poly/xhr: XMLHttpRequest not available"); });
// keep trying progIds until we find the correct one,
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
while (progIds.length && tryProgId(progIds.shift())) {}
}
// find XHR implementation
if (typeof XMLHttpRequest != 'undefined') {
xhrCtor = XMLHttpRequest;
function assignCtor (ctor) {
// assign window.XMLHttpRequest function
window.XMLHttpRequest = ctor;
}
else {
var noXhr;
// keep trying progIds until we find the correct one, then rewrite the getXhr method
// to always return that one.
noXhr = xhrCtor = function () {
throw new Error("poly/xhr: XMLHttpRequest not available");
};
while (progIds.length > 0 && xhrCtor == noXhr) (function (progId) {
function tryProgId (progId) {
try {
new ActiveXObject(progId);
xhrCtor = function () { return new ActiveXObject(progId); };
assignCtor(function () { return new ActiveXObject(progId); });
return true;
}
catch (ex) {}
}(progIds.shift()));
}
if (!window.XMLHttpRequest) {
window.XMLHttpRequest = xhrCtor;
}
});
......@@ -136,10 +136,6 @@
}
function getFile(file, callback) {
if (!location.host) {
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
}
var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true);
......
.npmignore
.idea/
experiments/
node_modules/
.externs.js
{
"browser": true,
"node": true,
"es5": true,
"predef": [
"define",
"module",
"system"
],
"boss": true,
"curly": true,
"eqnull": true,
"expr": true,
"globalstrict": false,
"laxbreak": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"quotmark": "single",
"strict": false,
"trailing": true,
"undef": true,
"unused": true,
"maxdepth": 3,
"maxcomplexity": 5
}
\ No newline at end of file
language: node_js
node_js:
- 0.8
script: npm run-script ci
branches:
only:
- dev
- master
env:
global:
- SELENIUM_USERNAME="cujojs-when"
- secure: "Vja3i39gQE7KnDMbIvblwJAfQK5ydeA6NKsAULQ//nvuV9muNeKgIxIMMPDw\nttjS6CY75how9tt87WSJQur/8PaSx+dj6RPvok4sf8DWgMMz97oI8e2l72wI\nIiHK1+btvI4/KG3QHLGCOJ8IxJA3Oluzo6ZDvRKXAvJoIrjmJjY="
\ No newline at end of file
<a href="http://promises-aplus.github.com/promises-spec"><img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png" alt="Promises/A+ logo" align="right" /></a>
[![Build Status](https://secure.travis-ci.org/cujojs/when.png)](http://travis-ci.org/cujojs/when)
# when.js
When.js is cujoJS's lightweight [Promises/A+](http://promises-aplus.github.com/promises-spec) and `when()` implementation that powers the async core of [wire.js](https://github.com/cujojs/wire), cujoJS's IOC Container. It features:
* A rock solid, battle-tested Promise implementation
* Resolving, settling, mapping, and reducing arrays of promises
* Executing tasks in parallel and sequence
* Transforming Node-style and other callback-based APIs into promise-based APIs
It passes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promises-tests), is [very fast](https://github.com/cujojs/promise-perf-tests#test-results), is under 1.5k when compiled with Google Closure + gzip, and has no external dependencies.
# What's New?
### 2.1.0
* New [`when.settle`](docs/api.md#whensettle) that settles an array of promises
* New [`when/guard`](docs/api.md#whenguard) generalized concurrency guarding and limiting
* New [`promise.inspect`](docs/api.md#inspect) for synchronously getting a snapshot of a promise's state at a particular instant.
* Significant performance improvements when resolving promises with non-primitives (e.g. with Arrays, Objects, etc.)
* Experimental [vert.x](http://vertx.io) support
* **DEPRECATED**: `onFulfilled`, `onRejected`, `onProgress` handler arguments to `when.all`, `when.any`, `when.some`. Use the returned promise's `then()` (or `otherwise()`, `ensure()`, etc) to register handlers instead.
* For example, do this: `when.all(array).then(onFulfilled, onRejected)` instead of this: `when.all(array, onFulfilled, onRejected)`. The functionality is equivalent.
### 2.0.1
* Account for the fact that Mocha creates a global named `process`. Thanks [Narsul](https://github.com/cujojs/when/pull/136)
### 2.0.0
* Fully asynchronous resolutions.
* [Promises/A+](http://promises-aplus.github.com/promises-spec) compliance.
* New [`when/keys`](docs/api.md#object-keys) module with `all()` and `map()` for object keys/values.
* New [`promise.ensure`](docs/api.md#ensure) as a better, and safer, replacement for `promise.always`. [See discussion](https://github.com/cujojs/when/issues/103) as to why `promise.always` is mistake-prone.
* **DEPRECATED:** `promise.always`
* `lift()` is now the preferred name for what was `bind()` in [when/function](docs/api.md#synchronous-functions), [when/node/function](docs/api.md#node-style-asynchronous-functions), and [when/callbacks](docs/api.md#asynchronous-functions).
* **DEPRECATED:** `bind()` in `when/function`, `when/node/function`, and `when/callbacks`. Use `lift()` instead.
[Full Changelog](CHANGES.md)
# Docs & Examples
[API docs](docs/api.md#api)
[More info on the wiki](https://github.com/cujojs/when/wiki)
[Examples](https://github.com/cujojs/when/wiki/Examples)
Quick Start
===========
### AMD
1. Get it
- `bower install when` or `yeoman install when`, *or*
- `git clone https://github.com/cujojs/when` or `git submodule add https://github.com/cujojs/when`
1. Configure your loader with a package:
```js
packages: [
{ name: 'when', location: 'path/to/when/', main: 'when' },
// ... other packages ...
]
```
1. `define(['when', ...], function(when, ...) { ... });` or `require(['when', ...], function(when, ...) { ... });`
### Node
1. `npm install when`
1. `var when = require('when');`
### RingoJS
1. `ringo-admin install cujojs/when`
1. `var when = require('when');`
### Legacy environments
1. `git clone https://github.com/cujojs/when` or `git submodule add https://github.com/cujojs/when`
1. Add a transient `define` shim, and a `<script>` element for when.js
```html
<script>
window.define = function(factory) {
try{ delete window.define; } catch(e){ window.define = void 0; } // IE
window.when = factory();
};
window.define.amd = {};
</script>
<script src="path/to/when/when.js"></script>
```
1. `when` will be available as `window.when`
# Running the Unit Tests
## Node
Note that when.js includes the [Promises/A+ Test Suite](https://github.com/promises-aplus/promise-tests). Running unit tests in Node will run both when.js's own test suite, and the Promises/A+ Test Suite.
1. `npm install`
1. `npm test`
## Browsers
1. `npm install`
1. `npm start` - starts buster server & prints a url
1. Point browsers at <buster server url>/capture, e.g. `localhost:1111/capture`
1. `npm run-script test-browser`
References
----------
Much of this code was inspired by the async innards of [wire.js](https://github.com/cujojs/wire), and has been influenced by the great work in [Q](https://github.com/kriskowal/q), [Dojo's Deferred](https://github.com/dojo/dojo), and [uber.js](https://github.com/phiggins42/uber.js).
{
"name": "when",
"version": "2.1.0",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/when.git"
}
}
\ No newline at end of file
{
"name": "when",
"version": "2.1.0",
"description": "A lightweight Promises/A+ and when() implementation, plus other async goodies.",
"keywords": ["Promises/A+", "promises-aplus", "promise", "promises", "deferred", "deferreds", "when", "async", "asynchronous", "cujo"],
"homepage": "http://cujojs.com",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"repositories": [
{
"type": "git",
"url": "https://github.com/cujojs/when"
}
],
"bugs": "https://github.com/cujojs/when/issues",
"maintainers": [
{
"name": "Brian Cavalier",
"web": "http://hovercraftstudios.com"
},
{
"name": "John Hann",
"web": "http://unscriptable.com"
}
],
"contributors": [
{
"name": "Brian Cavalier",
"web": "http://hovercraftstudios.com"
},
{
"name": "John Hann",
"web": "http://unscriptable.com"
},
{
"name": "Scott Andrews"
}
],
"devDependencies": {
"curl": "https://github.com/cujojs/curl/tarball/0.7.3",
"test-support": "~0.2",
"promises-aplus-tests": "~1"
},
"main": "when",
"directories": {
"test": "test"
},
"scripts": {
"test": "jshint . && buster test -e node && promises-aplus-tests test/promises-aplus-adapter.js",
"ci": "npm test && sauceme",
"start": "buster static -e browser"
}
}
\ No newline at end of file
......@@ -25,7 +25,7 @@ define(function(require) {
return function list(generator, condition, seed) {
var result = [];
return unfold(generator, condition, append, seed).yield(result);
return unfold(generator, condition, append, seed)['yield'](result);
function append(value, newSeed) {
result.push(value);
......
......@@ -9,7 +9,7 @@
*
* @author Brian Cavalier
* @author John Hann
* @version 2.1.0
* @version 2.1.1
*/
(function(define, global) { 'use strict';
define(function () {
......@@ -88,7 +88,7 @@ define(function () {
* @returns {Promise}
*/
ensure: function(onFulfilledOrRejected) {
return this.then(injectHandler, injectHandler).yield(this);
return this.then(injectHandler, injectHandler)['yield'](this);
function injectHandler() {
return resolve(onFulfilledOrRejected());
......
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = LF
\ No newline at end of file
node_modules/
experiments/
.npmignore
experiments/
*~
.idea/
tools/
curl/
test/lib
!test/dojo
!wire/dojo
dijit/
dojo.js
bin/
jquery.js
\ No newline at end of file
[submodule "test/util"]
path = test/util
url = https://github.com/dojo/util.git
[submodule "test/curl"]
path = test/curl
url = git://github.com/cujojs/curl.git
[submodule "support/sizzle"]
path = support/sizzle
url = https://github.com/cujojs/sizzle.git
[submodule "support/meld"]
path = support/meld
url = https://github.com/cujojs/meld.git
[submodule "support/when"]
path = support/when
url = git://github.com/cujojs/when.git
[submodule "test/requirejs"]
path = test/requirejs
url = https://github.com/jrburke/requirejs.git
[submodule "test/requirejs-domReady"]
path = test/requirejs-domReady
url = https://github.com/requirejs/domReady.git
[submodule "support/poly"]
path = support/poly
url = git://github.com/cujojs/poly.git
{
// Settings
"passfail" : false, // Stop on first error.
"maxerr" : 20, // Maximum error before stopping.
// Predefined globals whom JSHint will ignore.
"browser" : true, // Standard browser globals e.g. `window`, `document`.
"node" : true,
"rhino" : false,
"couch" : false,
"wsh" : false, // Windows Scripting Host.
"jquery" : false,
"prototypejs" : false,
"mootools" : false,
"dojo" : false,
"predef" : [ // Custom globals.
"define",
"module"
],
// Development.
"debug" : false, // Allow debugger statements e.g. browser breakpoints.
"devel" : false, // Allow developments statements e.g. `console.log();`.
// ECMAScript 5.
"es5" : false, // Allow ECMAScript 5 syntax.
"strict" : false, // Require `use strict` pragma in every file.
"globalstrict" : false, // Allow global "use strict" (also enables 'strict').
// The Good Parts.
"asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
"laxbreak" : true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
"bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.).
"boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
"curly" : true, // Require {} for every new block or scope.
"eqeqeq" : false, // Require triple equals i.e. `===`.
"eqnull" : true, // Tolerate use of `== null`.
"evil" : false, // Tolerate use of `eval`.
"expr" : true, // Tolerate `ExpressionStatement` as Programs.
"forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`.
"immed" : false, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
"latedef" : false, // Prohibit variable use before definition.
"loopfunc" : false, // Allow functions to be defined within loops.
"noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"nonstandard" : false, // Defines non-standard but widely adopted globals such as escape and unescape.
"regexp" : false, // Prohibit `.` and `[^...]` in regular expressions.
"regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
"scripturl" : true, // Tolerate script-targeted URLs.
"shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
"supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
"undef" : true, // Require all non-global variables be declared before they are used.
// Personal styling preferences.
"newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
"noempty" : false, // Prohibit use of empty blocks.
"nonew" : true, // Prohibit use of constructors for side-effects.
"nomen" : false, // Prohibit use of initial or trailing underbars in names.
"onevar" : false, // Allow only one `var` statement per function.
"plusplus" : false, // Prohibit use of `++` & `--`.
"sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
"trailing" : true, // Prohibit trailing whitespaces.
"white" : false, // Check against strict whitespace and indentation rules.
"indent" : 4, // Specify indentation spacing
"smarttabs" : true // Suppresses warnings about mixed tabs and spaces when the latter are used for alignmnent only
}
\ No newline at end of file
# wire.js
Wire is an [Inversion of Control Container](http://martinfowler.com/articles/injection.html "Inversion of Control Containers and the Dependency Injection pattern") for Javascript apps, and acts as the Application Composition layer for [cujo.js](http://cujojs.com).
Wire provides architectural plumbing that allows you to create and manage application components, and to connect those components together in loosely coupled and non-invasive ways. Consequently, your components will be more modular, easier to unit test and refactor, and your application will be easier to evolve and maintain.
To find out more, read the [full introduction](docs/introduction.md), more about the [concepts behind wire](docs/concepts.md), and check out a few [example applications](docs/introduction.md#example-apps).
# Documentation
1. [Getting Started](docs/get.md)
1. [Reference Documentation](docs/TOC.md)
1. [Example Code and Apps](docs/introduction.md#example-apps)
# What's new
### 0.9.4
* Fix for [render factory](docs/dom.md#rendering-dom-elements) in IE8.
### 0.9.3
* Compatibility with when.js 1.5.0 - 2.0.x. If you use when >= 2.0.0, you *MUST* update to wire 0.9.3. There are no other changes in 0.9.3.
### 0.9.2
* IE-specific fix for `wire/debug`'s `trace` option. See [#78](https://github.com/cujojs/wire/issues/78)
### 0.9.1
* Fix for compose factory. See [#69](https://github.com/cujojs/wire/issues/69)
### 0.9.0
* [Get it!](docs/get.md)
* [All new documentation](docs/TOC.md)
* [Even more DOM support](docs/dom.md), including DOM event connections via wire/on and cloning DOM elements.
* [Functions are first-class citizens](docs/functions.md) that can be used in very powerful ways.
* [Transform connections](docs/connections.md#transform-connections) use functions to transform data as it flows through connections (including DOM event connections).
* Built on latest [cujo.js](http://cujojs.com) platform:
* [curl](https://github.com/cujojs/curl) >= 0.7.1, or 0.6.8
* [when](https://github.com/cujojs/when) >= 1.5.0 (including 2.0.x)
* [meld](https://github.com/cujojs/meld) >= 1.0.0
* [poly](https://github.com/cujojs/poly) >= 0.5.0
[Full Changelog](https://github.com/cujojs/wire/wiki/Changelog)
# License
wire.js is licensed under [The MIT License](http://www.opensource.org/licenses/mit-license.php).
......@@ -10,10 +10,15 @@
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
(function(define) {
define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when, async, connection) {
(function(define) { 'use strict';
define(function(require) {
var adviceTypes, adviceStep, undef;
var meld, when, sequence, connection, adviceTypes, adviceStep, undef;
meld = require('meld');
when = require('when');
sequence = require('when/sequence');
connection = require('./lib/connection');
// "after" is not included in these standard advice types because
// it is created as promise-aware advice.
......@@ -55,7 +60,7 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
tasks.push(makeDecorator(decoratorRefName, options[decoratorRefName], wire));
}
resolver.resolve(async.sequence(tasks, target));
resolver.resolve(sequence(tasks, target));
}
//
......@@ -65,12 +70,19 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
function addSingleAdvice(addAdviceFunc, advices, proxy, advice, options, wire) {
function handleAopConnection(srcObject, srcMethod, adviceHandler) {
checkAdvisable(srcObject, srcMethod);
advices.push(addAdviceFunc(srcObject, srcMethod, adviceHandler));
}
return connection.parse(proxy, advice, options, wire, handleAopConnection);
}
function checkAdvisable(source, method) {
if (!(typeof method == 'function' || typeof source[method] == 'function')) {
throw new TypeError('Cannot add advice to non-method: ' + method);
}
}
function makeSingleAdviceAdd(adviceType) {
return function (source, sourceMethod, advice) {
return meld[adviceType](source, sourceMethod, advice);
......@@ -180,32 +192,18 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
}, target));
}
return {
/**
* Creates wire/aop plugin instances.
*
* @param ready {Promise} promise that will be resolved when the context has been wired,
* rejected if there is an error during the wiring process, and will receive progress
* events for object creation, property setting, and initialization.
* @param destroyed {Promise} promise that will be resolved when the context has been destroyed,
* rejected if there is an error while destroying the context, and will receive progress
* events for objects being destroyed.
* @param options {Object}
* @param options {Object} options passed to the plugin
*/
wire$plugin: function(ready, destroyed, options) {
return function(options) {
// Track aspects so they can be removed when the context is destroyed
var woven, plugin, i, len, adviceType;
woven = [];
// Remove all aspects that we added in this context
when(destroyed, function() {
for(var i = woven.length - 1; i >= 0; --i) {
woven[i].remove();
}
});
/**
* Function to add an aspect and remember it in the current context
* so that it can be removed when the context is destroyed.
......@@ -229,6 +227,14 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
// Plugin
plugin = {
context: {
destroy: function(resolver) {
woven.forEach(function(aspect) {
aspect.remove();
});
resolver.resolve();
}
},
facets: {
decorate: makeFacet('configure:after', decorateFacet),
afterFulfilling: makeFacet(adviceStep, makeAdviceFacet(addAfterFulfillingAdvice, woven)),
......@@ -250,13 +256,10 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
}
return plugin;
}
};
};
});
})(typeof define == 'function'
// use define for AMD if available
? define
: function(deps, factory) {
module.exports = factory.apply(this, deps.map(require));
}
: function(factory) { module.exports = factory(require); }
);
{
"name": "wire",
"version": "0.9.4",
"repository": {
"type": "git",
"url": "git://github.com/cujojs/wire.git"
}
}
\ No newline at end of file
/** @license MIT License (c) copyright B Cavalier & J Hann */
/**
* wire/cram/builder plugin
* Builder plugin for cram
* https://github.com/cujojs/cram
*
* wire is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
(function(define) {
define(function(require) {
var when, unfold, defaultModuleRegex, defaultSpecRegex, replaceIdsRegex,
removeCommentsRx, splitSpecsRegex;
when = require('when');
unfold = require('when/unfold');
// default dependency regex
defaultModuleRegex = /\.(module|create)$/;
defaultSpecRegex = /\.(wire\.spec|wire)$/;
// adapted from cram's scan function:
//replaceIdsRegex = /(define)\s*\(\s*(?:\s*["']([^"']*)["']\s*,)?(?:\s*\[([^\]]+)\]\s*,)?\s*(function)?\s*(?:\(([^)]*)\))?/g;
replaceIdsRegex = /(define)\s*\(\s*(?:\s*["']([^"']*)["']\s*,)?(?:\s*\[([^\]]*)\]\s*,)?/;
removeCommentsRx = /\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g;
splitSpecsRegex = /\s*,\s*/;
return {
normalize: normalize,
compile: compile
};
function normalize(resourceId, toAbsId) {
return resourceId ? toAbsId(resourceId.split("!")[0]) : resourceId;
}
function compile(wireId, resourceId, require, io, config) {
// Track all modules seen in wire spec, so we only include them once
var specIds, defines, seenModules, childSpecRegex,
moduleRegex;
defines = [];
seenModules = {};
moduleRegex = defaultModuleRegex;
childSpecRegex = defaultSpecRegex;
// Get config values
if(config) {
if(config.moduleRegex) moduleRegex = new RegExp(config.moduleRegex);
if(config.childSpecRegex) childSpecRegex = new RegExp(config.childSpecRegex);
}
// Grab the spec module id, *or comma separated list of spec module ids*
// Split in case it's a comma separated list of spec ids
specIds = resourceId.split(splitSpecsRegex);
return when.map(specIds, function(specId) {
return processSpec(specId);
}).then(write, io.error);
// For each spec id, add the spec itself as a dependency, and then
// scan the spec contents to find all modules that it needs (e.g.
// "module" and "create")
function processSpec(specId) {
var dependencies, ids;
dependencies = [];
ids = [specId];
addDep(wireId);
return unfold(fetchNextSpec, endOfList, scanSpec, ids)
.then(function() {
return generateDefine(specId, dependencies);
}
);
function fetchNextSpec() {
var id, dfd;
id = ids.shift();
dfd = when.defer();
require(
[id],
function(spec) { dfd.resolve([spec, ids]); },
dfd.reject
);
return dfd.promise;
}
function scanSpec(spec) {
scanPlugins(spec);
scanObj(spec);
}
function scanObj(obj, path) {
// Scan all keys. This might be the spec itself, or any sub-object-literal
// in the spec.
for (var name in obj) {
scanItem(obj[name], createPath(path, name));
}
}
function scanItem(it, path) {
// Determine the kind of thing we're looking at
// 1. If it's a string, and the key is module or create, then assume it
// is a moduleId, and add it as a dependency.
// 2. If it's an object or an array, scan it recursively
// 3. If it's a wire spec, add it to the list of spec ids
if (isSpec(path) && typeof it === 'string') {
addSpec(it);
} else if (isDep(path) && typeof it === 'string') {
// Get module def
addDep(it);
} else if (isStrictlyObject(it)) {
// Descend into subscope
scanObj(it, path);
} else if (Array.isArray(it)) {
// Descend into array
var arrayPath = path + '[]';
it.forEach(function(arrayItem) {
scanItem(arrayItem, arrayPath);
});
}
}
function scanPlugins(spec) {
var plugins = spec.$plugins || spec.plugins;
if(Array.isArray(plugins)) {
plugins.forEach(addPlugin);
} else if(typeof plugins === 'object') {
Object.keys(plugins).forEach(function(key) {
addPlugin(plugins[key]);
});
}
}
function addPlugin(plugin) {
if(typeof plugin === 'string') {
addDep(plugin);
} else if(typeof plugin === 'object' && plugin.module) {
addDep(plugin.module);
}
}
function addDep(moduleId) {
if(!(moduleId in seenModules)) {
dependencies.push(moduleId);
seenModules[moduleId] = moduleId;
}
}
function addSpec(specId) {
if(!(specId in seenModules)) {
ids.push(specId);
}
addDep(specId);
}
}
function generateDefine(specId, dependencies) {
var dfd, buffer;
dfd = when.defer();
io.read(ensureExtension(specId, 'js'), function(specText) {
buffer = injectIds(specText, specId, dependencies);
defines.push(buffer);
dfd.resolve();
}, dfd.reject);
return dfd.promise;
}
function write() {
// protect against prior code that may have omitted a semi-colon
io.write('\n;' + defines.join('\n'));
}
function isDep(path) {
return moduleRegex.test(path);
}
function isSpec(path) {
return childSpecRegex.test(path);
}
}
function createPath(path, name) {
return path ? (path + '.' + name) : name
}
function isStrictlyObject(it) {
return (it && Object.prototype.toString.call(it) == '[object Object]');
}
function ensureExtension(id, ext) {
return id.lastIndexOf('.') <= id.lastIndexOf('/')
? id + '.' + ext
: id;
}
function injectIds (moduleText, absId, moduleIds) {
// note: replaceIdsRegex removes commas, parens, and brackets
return moduleText.replace(removeCommentsRx, '').replace(replaceIdsRegex, function (m, def, mid, depIds) {
// merge deps, but not args since they're not referenced in module
if (depIds) moduleIds = moduleIds.concat(depIds);
moduleIds = moduleIds.map(quoted).join(', ');
if (moduleIds) moduleIds = '[' + moduleIds + '], ';
return def + '(' + quoted(absId) + ', ' + moduleIds;
});
}
function quoted (id) {
return '"' + id + '"';
}
function endOfList(ids) {
return !ids.length;
}
});
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
......@@ -44,26 +44,12 @@
define(['when', 'meld', './lib/functional', './lib/connection'],
function(when, meld, functional, connection) {
return {
wire$plugin: function eventsPlugin(ready, destroyed /*, options */) {
return function eventsPlugin(/* options */) {
var connectHandles = [];
/**
* Create a single connection from source[event] to target[method] so that
* when source[event] is invoked, target[method] will be invoked afterward
* with the same params.
*
* @param source source object
* @param event source method
* @param handler {Function} function to invoke
*/
function doConnectOne(source, event, handler) {
return meld.on(source, event, handler);
}
function handleConnection(source, eventName, handler) {
connectHandles.push(doConnectOne(source, eventName, handler));
function handleConnection(instance, methodName, handler) {
connectHandles.push(meld.on(instance, methodName, handler));
}
function doConnect(proxy, connect, options, wire) {
......@@ -71,27 +57,28 @@ function(when, meld, functional, connection) {
}
function connectFacet(wire, facet) {
var connect, promises, connects;
var promises, connects;
connects = facet.options;
promises = [];
for(connect in connects) {
promises.push(doConnect(facet, connect, connects[connect], wire));
}
promises = Object.keys(connects).map(function(key) {
return doConnect(facet, key, connects[key], wire);
});
return when.all(promises);
}
destroyed.then(function onContextDestroy() {
for (var i = connectHandles.length - 1; i >= 0; i--){
connectHandles[i].remove();
}
});
return {
context: {
destroy: function(resolver) {
connectHandles.forEach(function(handle) {
handle.remove();
});
resolver.resolve();
}
},
facets: {
// A facet named "connect" that runs during the connect
// lifecycle phase
connect: {
connect: function(resolver, facet, wire) {
resolver.resolve(connectFacet(wire, facet));
......@@ -99,7 +86,6 @@ function(when, meld, functional, connection) {
}
}
};
}
};
});
})(typeof define == 'function'
......
/** @license MIT License (c) copyright B Cavalier & J Hann */
/**
* wire/cram/builder plugin
* Builder plugin for cram
* https://github.com/cujojs/cram
*
* wire is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*/
define([], function() {
var defaultModuleRegex;
// default dependency regex
defaultModuleRegex = /\.(module|create)$/;
function cramAnalyze(myId, api, addDep, config) {
// Track all modules seen in wire spec, so we only include them once
var seenModules, specs, spec, i, childSpecRegex, moduleRegex;
seenModules = {};
moduleRegex = defaultModuleRegex;
// Get config values
if(config) {
if(config.moduleRegex) moduleRegex = new RegExp(config.moduleRegex);
if(config.childSpecRegex) childSpecRegex = new RegExp(config.childSpecRegex);
}
function addAbsoluteDep(absoluteId) {
// Only add the moduleId if we haven't already
if (absoluteId in seenModules) return;
seenModules[absoluteId] = 1;
addDep(absoluteId);
}
function addDependency(moduleId) {
addAbsoluteDep(api.toAbsMid(moduleId));
}
function addChildSpec(specId) {
addAbsoluteDep('wire' + '!' + api.toAbsMid(specId));
}
function scanObj(obj, path) {
// Scan all keys. This might be the spec itself, or any sub-object-literal
// in the spec.
for (var name in obj) {
scanItem(obj[name], path ? ([path, name].join('.')) : name);
}
}
function scanItem(it, path) {
// Determine the kind of thing we're looking at
// 1. If it's a string, and the key is module or create, then assume it
// is a moduleId, and add it as a dependency.
// 2. If it's an object or an array, scan it recursively
if (typeof it === 'string') {
// If it's a regular module, add it as a dependency
// If it's child spec, add it as a wire! dependency
if (isDep(path)) {
addDependency(it);
} else if (isWireDep(path)) {
addChildSpec(it);
}
}
if (isDep(path) && typeof it === 'string') {
// Get module def
addDependency(it);
} else if (isStrictlyObject(it)) {
// Descend into subscope
scanObj(it, path);
} else if (isArray(it)) {
// Descend into array
var arrayPath = path + '[]';
for (var i = 0, len = it.length; i < len; i++) {
scanItem(it[i], arrayPath);
}
}
}
function isWireDep(path) {
return childSpecRegex && childSpecRegex.test(path);
}
function isDep(path) {
return moduleRegex.test(path);
}
// Grab the spec module id, *or comma separated list of spec module ids*
// Split in case it's a comma separated list of spec ids
specs = myId.split(',');
// For each spec id, add the spec itself as a dependency, and then
// scan the spec contents to find all modules that it needs (e.g.
// "module" and "create")
for (i = 0; (spec = specs[i++]);) {
scanObj(api.load(spec));
addDependency(spec);
}
}
function isStrictlyObject(it) {
return (it && Object.prototype.toString.call(it) == '[object Object]');
}
return {
analyze: cramAnalyze
};
});
\ No newline at end of file
......@@ -79,10 +79,12 @@
*/
(function(global, define) {
define(['meld'], function(meld) {
var timer, defaultTimeout, logger, createTracer;
var timer, defaultTimeout, logger, createTracer, ownProp;
function noop() {}
ownProp = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
// Setup console for node, sane browsers, or IE
logger = typeof console != 'undefined'
? console
......@@ -355,11 +357,11 @@ define(['meld'], function(meld) {
logger.log('---------------------------------------------------');
}
return {
wire$plugin:function debugPlugin(ready, destroyed, options) {
return function wireDebug(options) {
var contextTimer, timeout, paths, count, tag, logCreated, logDestroyed, checkPathsTimeout,
verbose, filter, plugin, tracer;
var contextTimer, timeout, paths, count, tag,
logCreated, logDestroyed, checkPathsTimeout,
verbose, filter, plugin, context, tracer;
verbose = options.verbose;
contextTimer = createTimer();
......@@ -375,31 +377,30 @@ define(['meld'], function(meld) {
return time(msg, contextTimer);
}
logger.log(contextTime("Context init"));
logger.log(contextTime("Context debug"));
ready.then(
function onContextReady(context) {
cancelPathsTimeout();
logger.log(contextTime("Context ready"), context);
context = {
initialize: function(resolver) {
logger.log(contextTime("Context init"));
resolver.resolve();
},
function onContextError(err) {
ready: function(resolver) {
cancelPathsTimeout();
console.error(contextTime("Context ERROR: ") + err, err);
logStack(err);
}
);
destroyed.then(
function onContextDestroyed() {
logger.log(contextTime("Context ready"));
resolver.resolve();
},
destroy: function(resolver) {
tracer.untrace();
logger.log(contextTime("Context destroyed"));
resolver.resolve();
},
function onContextDestroyError(err) {
tracer.untrace();
logger.error(contextTime("Context destroy ERROR") + err, err);
error: function(resolver, api, err) {
cancelPathsTimeout();
console.error(contextTime("Context ERROR: ") + err, err);
logStack(err);
resolver.reject(err);
}
);
};
function makeListener(step, verbose) {
return function (promise, proxy /*, wire */) {
......@@ -414,7 +415,7 @@ define(['meld'], function(meld) {
if (verbose && filter(path)) {
var message = time(step + ' ' + (path || proxy.id || ''), contextTimer);
if (proxy.target) {
logger.log(message, proxy.target, proxy.spec);
logger.log(message, proxy.target, proxy.metadata);
} else {
logger.log(message, proxy);
}
......@@ -456,7 +457,7 @@ define(['meld'], function(meld) {
msg = p + ': ' + component.status;
(component.status == 'ready' ? ready : notReady).push(
{ msg: msg, spec: component.spec }
{ msg: msg, metadata: component.metadata }
);
}
......@@ -465,7 +466,7 @@ define(['meld'], function(meld) {
logger.log('Components that DID NOT finish wiring');
for(p = notReady.length-1; p >= 0; --p) {
component = notReady[p];
logger.error(component.msg, component.spec);
logger.error(component.msg, component.metadata);
}
}
......@@ -474,7 +475,7 @@ define(['meld'], function(meld) {
logger.log('Components that finished wiring');
for(p = ready.length-1; p >= 0; --p) {
component = ready[p];
logger.log(component.msg, component.spec);
logger.log(component.msg, component.metadata);
}
}
} else {
......@@ -484,15 +485,49 @@ define(['meld'], function(meld) {
logSeparator();
}
/**
* Adds a named constructor function property to the supplied component
* so that the name shows up in debug inspectors. Squelches all errors.
*/
function makeConstructor(name, component) {
/*jshint evil:true*/
var ctor;
try {
// Generate a named function to use as the constructor
name = name.replace(/^[^a-zA-Z$_]|[^a-zA-Z0-9$_]+/g, '_');
eval('ctor = function ' + name + ' () {}');
// Be friendly and make configurable and writable just in case
// some other library or application code tries to set constructor.
Object.defineProperty(component, 'constructor', {
configurable: true,
writable: true,
value: ctor
});
} catch(e) {
// Oh well, ignore.
}
}
plugin = {
context: context,
create:function (promise, proxy) {
var path = proxy.path;
var path, component;
path = proxy.path;
component = proxy.target;
count++;
paths[path || ('(unnamed-' + count + ')')] = {
spec:proxy.spec
metadata: proxy.metadata
};
if(component && typeof component == 'object'
&& !ownProp(component, 'constructor')) {
makeConstructor(proxy.id, component);
}
logCreated(promise, proxy);
},
configure: makeListener('configured', verbose),
......@@ -516,7 +551,6 @@ define(['meld'], function(meld) {
checkPathsTimeout = setTimeout(checkPaths, timeout);
return plugin;
}
};
});
......
......@@ -42,7 +42,7 @@ define(['../lib/plugin-base/on', 'dojo/on', 'dojo/query'], function(createOnPlug
on.wire$plugin = createOnPlugin({
on: on
}).wire$plugin;
});
return on;
......
......@@ -14,7 +14,7 @@
* http://www.opensource.org/licenses/mit-license.php
*/
define(['./lib/plugin-base/dom', './lib/dom/base', './domReady'], function(createDomPlugin, base, domReady) {
define(['./lib/plugin-base/dom', './lib/dom/base'], function(createDomPlugin, base) {
return createDomPlugin({
addClass: base.addClass,
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment