Commit c488f564 authored by Stephen Sawchuk's avatar Stephen Sawchuk

Merge pull request #609 from cujojs/cujojs-update

Update to latest cujoJS releases
parents 575d1e61 57e70d6d
...@@ -174,13 +174,8 @@ define({ ...@@ -174,13 +174,8 @@ define({
} }
}, },
plugins: [ plugins: [ //'wire/debug',
// { module: 'wire/debug', trace: true }, 'wire/dom', 'wire/dom/render', 'wire/on',
{ module: 'wire/dom' }, 'wire/aop', 'wire/connect', 'cola'
{ module: 'wire/dom/render' },
{ module: 'wire/on' },
{ module: 'wire/aop' },
{ module: 'wire/connect' },
{ module: 'cola' }
] ]
}); });
/*global curl */ // Bootstrap the app. Notice that curl is not a global, only define.
(function (curl) { /*global define*/
define(['curl'], function (curl) {
'use strict'; 'use strict';
curl({ curl({
...@@ -12,10 +13,9 @@ ...@@ -12,10 +13,9 @@
{ name: 'cola', location: 'bower_components/cola', main: 'cola' }, { name: 'cola', location: 'bower_components/cola', main: 'cola' },
{ name: 'poly', location: 'bower_components/poly', main: 'poly' } { 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 // Turn off i18n locale sniffing. Change or remove this line if you want to
// test specific locales or try automatic locale-sniffing. // test specific locales or try automatic locale-sniffing.
locale: false locale: false
}); });
});
})(curl);
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
"name": "todomvc-cujoJS", "name": "todomvc-cujoJS",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"todomvc-common": "~0.1.4", "todomvc-common": "~0.1.7",
"curl": "~0.7.3", "curl": "~0.7.4",
"cola": "latest", "cola": "latest",
"poly": "~0.5.1", "poly": "~0.5.1",
"when": "~2.1.0", "when": "~2.1.1",
"wire": "~0.9.4", "wire": "~0.10.0",
"meld": "~1.3.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) * curl (cujo resource loader)
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
(function (global) { (function (global) {
//"use strict"; don't restore this until the config routine is refactored //"use strict"; don't restore this until the config routine is refactored
var var
version = '0.7.3', version = '0.7.4',
curlName = 'curl', curlName = 'curl',
defineName = 'define', defineName = 'define',
runModuleAttr = 'data-curl-run',
userCfg, userCfg,
prevCurl, prevCurl,
prevDefine, prevDefine,
...@@ -49,8 +50,9 @@ ...@@ -49,8 +50,9 @@
dontAddExtRx = /\?|\.js\b/, dontAddExtRx = /\?|\.js\b/,
absUrlRx = /^\/|^[^:]+:\/\//, absUrlRx = /^\/|^[^:]+:\/\//,
findDotsRx = /(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g, findDotsRx = /(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,
removeCommentsRx = /\/\*[\s\S]*?\*\/|(?:[^\\])\/\/.*?[\n\r]/g, removeCommentsRx = /\/\*[\s\S]*?\*\/|\/\/.*?[\n\r]/g,
findRValueRequiresRx = /require\s*\(\s*["']([^"']+)["']\s*\)|(?:[^\\]?)(["'])/g, findRValueRequiresRx = /require\s*\(\s*(["'])(.*?[^\\])\1\s*\)|[^\\]?(["'])/g,
splitMainDirectives = /\s*,\s*/,
cjsGetters, cjsGetters,
core; core;
...@@ -202,7 +204,7 @@ ...@@ -202,7 +204,7 @@
} }
function isPromise (o) { function isPromise (o) {
return o instanceof Promise; return o instanceof Promise || o instanceof CurlApi;
} }
function when (promiseOrValue, callback, errback, progback) { function when (promiseOrValue, callback, errback, progback) {
...@@ -637,18 +639,6 @@ ...@@ -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) { resolvePathInfo: function (absId, cfg) {
// searches through the configured path mappings and packages // searches through the configured path mappings and packages
var pathMap, pathInfo, path, pkgCfg; var pathMap, pathInfo, path, pkgCfg;
...@@ -744,8 +734,8 @@ ...@@ -744,8 +734,8 @@
defFunc : defFunc :
defFunc.toSource ? defFunc.toSource() : defFunc.toString(); defFunc.toSource ? defFunc.toSource() : defFunc.toString();
// remove comments, then look for require() or quotes // remove comments, then look for require() or quotes
source.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, id, qq) { source.replace(removeCommentsRx, '').replace(findRValueRequiresRx, function (m, rq, id, qq) {
// if we encounter a quote // if we encounter a string in the source, don't look for require()
if (qq) { if (qq) {
currQuote = currQuote == qq ? undef : currQuote; currQuote = currQuote == qq ? undef : currQuote;
} }
...@@ -971,22 +961,30 @@ ...@@ -971,22 +961,30 @@
}, },
fetchDep: function (depName, parentDef) { 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; resId, pathInfo, def, tempDef, resCfg;
toAbsId = parentDef.toAbsId; toAbsId = parentDef.toAbsId;
isPreload = parentDef.isPreload; isPreload = parentDef.isPreload;
cfg = parentDef.config || userCfg; // is this fallback necessary? 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 // check for plugin loaderId
// TODO: this runs pluginParts() twice. how to run it just once? parts = pluginParts(absId);
parts = pluginParts(toAbsId(depName));
resId = parts.resourceId; resId = parts.resourceId;
// get id of first resource to load (which could be a plugin) // get id of first resource to load (which could be a plugin)
mainId = parts.pluginId || resId; mainId = parts.pluginId || resId;
pathInfo = core.resolvePathInfo(mainId, cfg); pathInfo = core.resolvePathInfo(mainId, cfg);
}
// get custom module loader from package config if not a plugin // get custom module loader from package config if not a plugin
if (parts) {
if (parts.pluginId) { if (parts.pluginId) {
loaderId = mainId; loaderId = mainId;
} }
...@@ -1002,6 +1000,7 @@ ...@@ -1002,6 +1000,7 @@
pathInfo = core.resolvePathInfo(loaderId, cfg); pathInfo = core.resolvePathInfo(loaderId, cfg);
} }
} }
}
if (mainId in cache) { if (mainId in cache) {
def = cache[mainId]; def = cache[mainId];
...@@ -1070,8 +1069,8 @@ ...@@ -1070,8 +1069,8 @@
// but to be compatible with AMD spec, we have to // but to be compatible with AMD spec, we have to
// piggy-back on the callback function parameter: // piggy-back on the callback function parameter:
var loaded = function (res) { var loaded = function (res) {
normalizedDef.resolve(res);
if (!dynamic) cache[fullId] = res; if (!dynamic) cache[fullId] = res;
normalizedDef.resolve(res);
}; };
loaded['resolve'] = loaded; loaded['resolve'] = loaded;
loaded['reject'] = loaded['error'] = normalizedDef.reject; loaded['reject'] = loaded['error'] = normalizedDef.reject;
...@@ -1110,6 +1109,34 @@ ...@@ -1110,6 +1109,34 @@
} }
} }
return def; 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 @@ ...@@ -1118,42 +1145,57 @@
cjsGetters = {'require': core.getCjsRequire, 'exports': core.getCjsExports, 'module': core.getCjsModule}; cjsGetters = {'require': core.getCjsRequire, 'exports': core.getCjsExports, 'module': core.getCjsModule};
function _curl (/* various */) { function _curl (/* various */) {
var args, promise, cfg;
var args = [].slice.call(arguments), cfg; args = [].slice.call(arguments);
// extract config, if it's specified // extract config, if it's specified
if (isType(args[0], 'Object')) { if (isType(args[0], 'Object')) {
cfg = args.shift(); 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) { if (cfg) {
core.setApi(cfg); core.setApi(cfg);
userCfg = core.config(cfg); userCfg = core.config(cfg);
// check for preloads // check for preloads
core.checkPreloads(cfg); if ('preloads' in cfg) {
// check for main module(s) pPromise = new CurlApi(cfg['preloads'], undef, errback, preload, true);
if ('main' in cfg) { // yes, this is hacky and embarrassing. now that we've got that
// start in next turn to wait for other modules in current file // settled... until curl has deferred factory execution, this
setTimeout(function () { // is the only way to stop preloads from dead-locking when
var ctx; // they have dependencies inside a bundle.
ctx = core.createContext(userCfg, undef, [].concat(cfg['main'])); core.nextTurn(function () { preload = pPromise; });
core.getDeps(ctx); }
}, 0); // 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 // 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; 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, when(ctx,
// return the dependencies as arguments, not an array // return the dependencies as arguments, not an array
function (deps) { function (deps) {
...@@ -1166,13 +1208,22 @@ ...@@ -1166,13 +1208,22 @@
); );
return this; return this;
}; };
this['next'] = function (ids, cb, eb) { this['next'] = function (ids, cb, eb) {
// chain api // chain api
return new CurlApi(ids, cb, eb, ctx); return new CurlApi(ids, cb, eb, ctx);
}; };
this['config'] = _config; this['config'] = _config;
if (callback || errback) then(callback, errback); 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; _curl['version'] = version;
...@@ -1232,18 +1283,23 @@ ...@@ -1232,18 +1283,23 @@
pathRx: /$^/ pathRx: /$^/
}; };
// look for "data-curl-run" directive, and override config
userCfg = core.extractDataAttrConfig(userCfg);
// handle pre-existing global // handle pre-existing global
prevCurl = global[curlName]; prevCurl = global[curlName];
prevDefine = global[defineName]; prevDefine = global[defineName];
if (!prevCurl || isType(prevCurl, 'Function')) {
// set default api // only run config if there is something to config (perf saver?)
core.setApi(); if (prevCurl && isType(prevCurl, 'Object') || userCfg.main) {
}
else {
// remove global curl object // remove global curl object
global[curlName] = undef; // can't use delete in IE 6-8 global[curlName] = undef; // can't use delete in IE 6-8
// configure curl // configure curl
_config(prevCurl); _config(prevCurl || userCfg);
}
else {
// set default api
core.setApi();
} }
// allow curl to be a dependency // 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 * curl debug plugin
......
/** MIT License (c) copyright B Cavalier & J Hann */ /** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/** /**
* curl domReady * 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 * curl CommonJS Modules/1.1 loader
...@@ -16,52 +16,13 @@ define(/*=='curl/loader/cjsm11',==*/ function () { ...@@ -16,52 +16,13 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
var head, insertBeforeEl /*, findRequiresRx, myId*/; 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]); head = document && (document['head'] || document.getElementsByTagName('head')[0]);
// to keep IE from crying, we need to put scripts before any // to keep IE from crying, we need to put scripts before any
// <base> elements, but after any <meta>. this should do it: // <base> elements, but after any <meta>. this should do it:
insertBeforeEl = head && head.getElementsByTagName('base')[0] || null; insertBeforeEl = head && head.getElementsByTagName('base')[0] || null;
function wrapSource (source, resourceId, fullUrl) { 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 + "'," + return "define('" + resourceId + "'," +
"['require','exports','module'],function(require,exports,module){" + "['require','exports','module'],function(require,exports,module){" +
source + "\n});\n" + sourceUrl + "\n"; source + "\n});\n" + sourceUrl + "\n";
...@@ -82,8 +43,7 @@ define(/*=='curl/loader/cjsm11',==*/ function () { ...@@ -82,8 +43,7 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
head.insertBefore(el, insertBeforeEl); head.insertBefore(el, insertBeforeEl);
} }
return { wrapSource['load'] = function (resourceId, require, callback, config) {
'load': function (resourceId, require, callback, config) {
// TODO: extract xhr from text! plugin and use that instead (after we upgrade to cram.js) // 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) { require(['text!' + resourceId + '.js', 'curl/_privileged'], function (source, priv) {
var moduleMap; var moduleMap;
...@@ -112,9 +72,12 @@ define(/*=='curl/loader/cjsm11',==*/ function () { ...@@ -112,9 +72,12 @@ define(/*=='curl/loader/cjsm11',==*/ function () {
}, callback['error'] || function (ex) { throw ex; }); }, callback['error'] || function (ex) { throw ex; });
}); });
}
}; };
wrapSource['cramPlugin'] = '../cram/cjsm11';
return wrapSource;
}); });
}(this, this.document, function () { /* FB needs direct eval here */ eval(arguments[0]); })); }(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 * 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 * curl css! plugin
...@@ -573,8 +573,7 @@ ...@@ -573,8 +573,7 @@
}, },
'plugin-builder': './builder/css', 'cramPlugin': '../cram/css'
'pluginBuilder': './builder/css'
}); });
......
/** MIT License (c) copyright B Cavalier & J Hann */ /** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/** /**
* curl domReady loader plugin * 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 * curl i18n plugin
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
* *
*/ */
(function (global) { (function (window) {
define(/*=='curl/plugin/i18n',==*/ function () { define(/*=='curl/plugin/i18n',==*/ function () {
...@@ -96,6 +96,7 @@ define(/*=='curl/plugin/i18n',==*/ function () { ...@@ -96,6 +96,7 @@ define(/*=='curl/plugin/i18n',==*/ function () {
appendLocaleRx = /(\.js)?$/; appendLocaleRx = /(\.js)?$/;
return { return {
load: function (absId, require, loaded, config) { load: function (absId, require, loaded, config) {
var eb, toFile, locale, bundles, fetched, id, ids, specifiers, i; var eb, toFile, locale, bundles, fetched, id, ids, specifiers, i;
...@@ -160,7 +161,10 @@ define(/*=='curl/plugin/i18n',==*/ function () { ...@@ -160,7 +161,10 @@ define(/*=='curl/plugin/i18n',==*/ function () {
} }
} }
} },
'cramPlugin': '../cram/i18n'
}; };
function fetch (require, id, i, cb, eb) { function fetch (require, id, i, cb, eb) {
...@@ -177,7 +181,9 @@ define(/*=='curl/plugin/i18n',==*/ function () { ...@@ -177,7 +181,9 @@ define(/*=='curl/plugin/i18n',==*/ function () {
} }
function getLocale () { function getLocale () {
var ci = global['clientInformation'] || global.navigator; var ci;
if (!window) return false;
ci = window['clientInformation'] || window.navigator;
return ci.language || ci['userLanguage']; return ci.language || ci['userLanguage'];
} }
...@@ -187,4 +193,4 @@ define(/*=='curl/plugin/i18n',==*/ function () { ...@@ -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 * curl js! plugin
...@@ -191,7 +191,9 @@ define(/*=='curl/plugin/js',==*/ ['curl/_privileged'], function (priv) { ...@@ -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 * 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 * curl text! loader plugin
...@@ -8,62 +8,18 @@ ...@@ -8,62 +8,18 @@
*/ */
/** /**
* TODO: load xdomain text, too * TODO: load xdomain text, too, somehow
* *
*/ */
define(/*=='curl/plugin/text',==*/ function () { define(/*=='curl/plugin/text',==*/ ['./_fetchText'], function (fetchText) {
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;
}
return { return {
// 'normalize': function (resourceId, toAbsId) { 'normalize': function (resourceId, toAbsId) {
// // remove options // remove options
// return resourceId ? toAbsId(resourceId.split("!")[0]) : resourceId; return resourceId ? toAbsId(resourceId.split("!")[0]) : resourceId;
// }, },
load: function (resourceName, req, callback, config) { load: function (resourceName, req, callback, config) {
// remove suffixes (future) // remove suffixes (future)
...@@ -71,8 +27,12 @@ define(/*=='curl/plugin/text',==*/ function () { ...@@ -71,8 +27,12 @@ define(/*=='curl/plugin/text',==*/ function () {
fetchText(req['toUrl'](resourceName), callback, callback['error'] || error); 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 * 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 * curl ssjs shim
...@@ -59,6 +59,10 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) { ...@@ -59,6 +59,10 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) {
localLoadFunc = remoteLoadFunc = failIfInvoked; localLoadFunc = remoteLoadFunc = failIfInvoked;
} }
if (typeof process === 'object' && process.nextTick) {
priv.core.nextTurn = process.nextTick;
}
function stripExtension (url) { function stripExtension (url) {
return url.replace(/\.js$/, ''); return url.replace(/\.js$/, '');
} }
...@@ -136,5 +140,9 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) { ...@@ -136,5 +140,9 @@ define(/*=='curl/shim/ssjs',==*/ function (require, exports) {
: protocol; : protocol;
} }
function _nextTick (func) {
nextTick(func);
}
}); });
}(require, load)); }(require, load));
/** MIT License (c) copyright B Cavalier & J Hann */ /** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/** /**
* curl createContext module * curl createContext module
...@@ -266,6 +266,7 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin ...@@ -266,6 +266,7 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin
function createTrackedRequire (require, modulesAllFetched) { function createTrackedRequire (require, modulesAllFetched) {
var callCount = 0; var callCount = 0;
function trackedRequire (idOrArray, callback) { function trackedRequire (idOrArray, callback) {
var cb; var cb;
...@@ -277,12 +278,14 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin ...@@ -277,12 +278,14 @@ define(['curl', 'curl/_privileged', './undefine'], function (curl, priv, undefin
if (--callCount == 0) modulesAllFetched(); if (--callCount == 0) modulesAllFetched();
}; };
// preserve AMD API
trackedRequire.toUrl = require.toUrl;
return require(idOrArray, cb); return require(idOrArray, cb);
} }
// preserve AMD API
trackedRequire.toUrl = require.toUrl;
// helpful
trackedRequire.notAsync = function () { return callCount == 0; }; trackedRequire.notAsync = function () { return callCount == 0; };
return trackedRequire; return trackedRequire;
} }
......
/** MIT License (c) copyright B Cavalier & J Hann */ /** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */
/** /**
* curl createContext module * 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 * 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/) * poly is part of the cujo.js family of libraries (http://cujojs.com/)
* *
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* http://www.opensource.org/licenses/mit-license.php * 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 { return {
failIfShimmed: object.failIfShimmed, failIfShimmed: object.failIfShimmed,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Array -- a stand-alone module for using Javascript 1.6 array features Array -- a stand-alone module for using Javascript 1.6 array features
in lame-o browsers that don't support Javascript 1.6 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/). 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 @@ ...@@ -3,7 +3,7 @@
ES5-ish Date shims for older browsers. 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/). This module is part of the cujo.js family of libraries (http://cujojs.com/).
...@@ -20,11 +20,14 @@ define(['./lib/_base'], function (base) { ...@@ -20,11 +20,14 @@ define(['./lib/_base'], function (base) {
invalidDate, invalidDate,
isoCompat, isoCompat,
isoParseRx, isoParseRx,
ownProp,
undef; undef;
origProto = origDate.prototype; origProto = origDate.prototype;
origParse = origDate.parse; origParse = origDate.parse;
ownProp = Object.prototype.hasOwnProperty;
maxDate = 8.64e15; maxDate = 8.64e15;
invalidDate = NaN; invalidDate = NaN;
// borrowed this from https://github.com/kriskowal/es5-shim // borrowed this from https://github.com/kriskowal/es5-shim
...@@ -119,6 +122,7 @@ define(['./lib/_base'], function (base) { ...@@ -119,6 +122,7 @@ define(['./lib/_base'], function (base) {
} }
if (!has('date-tojson')) { if (!has('date-tojson')) {
origProto.toJSON = function toJSON (key) { origProto.toJSON = function toJSON (key) {
// key arg is ignored by Date objects, but since this function // key arg is ignored by Date objects, but since this function
// is generic, other Date-like objects could use the key arg. // is generic, other Date-like objects could use the key arg.
...@@ -129,39 +133,42 @@ define(['./lib/_base'], function (base) { ...@@ -129,39 +133,42 @@ define(['./lib/_base'], function (base) {
} }
function checkIsoCompat () { function checkIsoCompat () {
if (!isoCompat()) {
// fix Date constructor // 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; var len, result;
// Date_ called as function, not constructor // Date called as function, not constructor
if (!(this instanceof Date_)) return origDate.apply(this, arguments); if (!(this instanceof newDate)) return origDate.apply(this, arguments);
len = arguments.length; len = arguments.length;
if (len == 0) { if (len === 0) {
result = new origDate(); result = new origDate();
} }
else if (len == 1) { else if (len === 1) {
result = new origDate(base.isString(y) ? Date.parse(y) : y); result = new origDate(base.isString(y) ? newDate.parse(y) : y);
} }
else { else {
result = new origDate(y, m, d == undef ? 1 : d, h || 0, mn || 0, s || 0, ms || 0); 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; return result;
} };
}());
if (!isoCompat()) {
Date_.now = origDate.now; newDate.now = origDate.now;
Date_.UTC = origDate.UTC; newDate.UTC = origDate.UTC;
Date_.prototype = origProto; newDate.prototype = origProto;
Date_.prototype.constructor = Date_; newDate.prototype.constructor = newDate;
Date_.parse = function parse (str) { newDate.parse = function parse (str) {
var result; var result;
// check for iso date // check for iso date
...@@ -175,11 +182,25 @@ define(['./lib/_base'], function (base) { ...@@ -175,11 +182,25 @@ define(['./lib/_base'], function (base) {
return result; 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) { else if (Date != origDate) {
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(); 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 * 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/). * This module is part of the cujo.js family of libraries (http://cujojs.com/).
* *
......
/** /**
* JSON polyfill / shim * 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/) * poly is part of the cujo.js family of libraries (http://cujojs.com/)
* *
* Licensed under the MIT License at: * Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php * 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; 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 * 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/). * 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 * 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/). * This module is part of the cujo.js family of libraries (http://cujojs.com/).
* *
...@@ -52,24 +52,45 @@ ...@@ -52,24 +52,45 @@
* IE missing enum properties fixes copied from kangax: * IE missing enum properties fixes copied from kangax:
* https://github.com/kangax/protolicious/blob/master/experimental/object.for_in.js * 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) { define(['./lib/_base'], function (base) {
"use strict"; "use strict";
var refObj, var refObj,
refProto, refProto,
has__proto__,
hasNonEnumerableProps,
getPrototypeOf, getPrototypeOf,
keys, keys,
featureMap, featureMap,
shims, shims,
secrets,
protoSecretProp,
hasOwnProp = 'hasOwnProperty',
undef; undef;
refObj = Object; refObj = Object;
refProto = refObj.prototype; refProto = refObj.prototype;
getPrototypeOf = typeof {}.__proto__ == 'object' has__proto__ = typeof {}.__proto__ == 'object';
? function (object) { return object.__proto__; }
: function (object) { return object.constructor ? object.constructor.prototype : refProto; }; 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 = !hasNonEnumerableProps
? _keys ? _keys
...@@ -81,7 +102,7 @@ define(['./lib/_base'], function (base) { ...@@ -81,7 +102,7 @@ define(['./lib/_base'], function (base) {
} }
return result; return result;
} }
}([ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ])); }([ 'constructor', hasOwnProp, 'isPrototypeOf', 'propertyIsEnumerable', 'toString', 'toLocaleString', 'valueOf' ]));
featureMap = { featureMap = {
'object-create': 'create', 'object-create': 'create',
...@@ -101,10 +122,11 @@ define(['./lib/_base'], function (base) { ...@@ -101,10 +122,11 @@ define(['./lib/_base'], function (base) {
shims = {}; shims = {};
function hasNonEnumerableProps () { secrets = {
for (var p in { toString: 1 }) return false; proto: {}
return true; };
}
protoSecretProp = !has('object-getprototypeof') && !has__proto__ && hasNonEnumerableProps && hasOwnProp;
function createFlameThrower (feature) { function createFlameThrower (feature) {
return function () { return function () {
...@@ -134,6 +156,15 @@ define(['./lib/_base'], function (base) { ...@@ -134,6 +156,15 @@ define(['./lib/_base'], function (base) {
return result; 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')) { if (!has('object-create')) {
Object.create = shims.create = function create (proto, props) { Object.create = shims.create = function create (proto, props) {
var obj; var obj;
...@@ -141,11 +172,21 @@ define(['./lib/_base'], function (base) { ...@@ -141,11 +172,21 @@ define(['./lib/_base'], function (base) {
if (typeof proto != 'object') throw new TypeError('prototype is not of type Object or Null.'); if (typeof proto != 'object') throw new TypeError('prototype is not of type Object or Null.');
PolyBase.prototype = proto; PolyBase.prototype = proto;
obj = new PolyBase(props); obj = new PolyBase();
PolyBase.prototype = null; 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) { if (arguments.length > 1) {
// defineProperties could throw depending on `shouldThrow` // defineProperties could throw depending on `failIfShimmed`
Object.defineProperties(obj, props); Object.defineProperties(obj, props);
} }
...@@ -264,8 +305,7 @@ define(['./lib/_base'], function (base) { ...@@ -264,8 +305,7 @@ define(['./lib/_base'], function (base) {
} }
} }
// this is effectively a no-op, so why execute it? function assertIsObject (o) { if (typeof o != 'object') throw new TypeError('Object.getPrototypeOf called on non-object'); }
//failIfShimmed(false);
return { return {
failIfShimmed: failIfShimmed failIfShimmed: failIfShimmed
......
/** /**
* polyfill / shim plugin for AMD loaders * 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/) * poly is part of the cujo.js family of libraries (http://cujojs.com/)
* *
* Licensed under the MIT License at: * Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php * http://www.opensource.org/licenses/mit-license.php
* *
* @version 0.5.1
*/ */
define(['./all'], function (all) { define(['./all'], function (all) {
...@@ -18,7 +17,7 @@ define(['./all'], function (all) { ...@@ -18,7 +17,7 @@ define(['./all'], function (all) {
// copy all // copy all
for (var p in all) poly[p] = all[p]; for (var p in all) poly[p] = all[p];
poly.version = '0.5.1'; poly.version = '0.5.2';
return poly; 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 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/). This module is part of the cujo.js family of libraries (http://cujojs.com/).
Licensed under the MIT License at: Licensed under the MIT License at:
http://www.opensource.org/licenses/mit-license.php 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) { define(['./object', './string', './date', './array', './function', './json', './xhr'], function (object, string, date) {
var failTestRx; var failTestRx;
......
/** /**
* String polyfill / shims * 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/). * This module is part of the cujo.js family of libraries (http://cujojs.com/).
* *
......
/** /**
* XHR polyfill / shims * 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/). * This module is part of the cujo.js family of libraries (http://cujojs.com/).
* *
...@@ -9,34 +9,31 @@ ...@@ -9,34 +9,31 @@
* http://www.opensource.org/licenses/mit-license.php * 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']; progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
while (progIds.length && tryProgId(progIds.shift())) {}
}
// find XHR implementation function assignCtor (ctor) {
if (typeof XMLHttpRequest != 'undefined') { // assign window.XMLHttpRequest function
xhrCtor = XMLHttpRequest; window.XMLHttpRequest = ctor;
} }
else {
var noXhr; function tryProgId (progId) {
// 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) {
try { try {
new ActiveXObject(progId); new ActiveXObject(progId);
xhrCtor = function () { return new ActiveXObject(progId); }; assignCtor(function () { return new ActiveXObject(progId); });
return true;
} }
catch (ex) {} catch (ex) {}
}(progIds.shift()));
}
if (!window.XMLHttpRequest) {
window.XMLHttpRequest = xhrCtor;
} }
}); });
...@@ -136,10 +136,6 @@ ...@@ -136,10 +136,6 @@
} }
function getFile(file, callback) { 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(); var xhr = new XMLHttpRequest();
xhr.open('GET', findRoot() + file, true); 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) { ...@@ -25,7 +25,7 @@ define(function(require) {
return function list(generator, condition, seed) { return function list(generator, condition, seed) {
var result = []; var result = [];
return unfold(generator, condition, append, seed).yield(result); return unfold(generator, condition, append, seed)['yield'](result);
function append(value, newSeed) { function append(value, newSeed) {
result.push(value); result.push(value);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* @author Brian Cavalier * @author Brian Cavalier
* @author John Hann * @author John Hann
* @version 2.1.0 * @version 2.1.1
*/ */
(function(define, global) { 'use strict'; (function(define, global) { 'use strict';
define(function () { define(function () {
...@@ -88,7 +88,7 @@ define(function () { ...@@ -88,7 +88,7 @@ define(function () {
* @returns {Promise} * @returns {Promise}
*/ */
ensure: function(onFulfilledOrRejected) { ensure: function(onFulfilledOrRejected) {
return this.then(injectHandler, injectHandler).yield(this); return this.then(injectHandler, injectHandler)['yield'](this);
function injectHandler() { function injectHandler() {
return resolve(onFulfilledOrRejected()); 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 @@ ...@@ -10,10 +10,15 @@
* Licensed under the MIT License at: * Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php * http://www.opensource.org/licenses/mit-license.php
*/ */
(function(define) { (function(define) { 'use strict';
define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when, async, connection) { 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 // "after" is not included in these standard advice types because
// it is created as promise-aware advice. // it is created as promise-aware advice.
...@@ -55,7 +60,7 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when, ...@@ -55,7 +60,7 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
tasks.push(makeDecorator(decoratorRefName, options[decoratorRefName], wire)); 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, ...@@ -65,12 +70,19 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
function addSingleAdvice(addAdviceFunc, advices, proxy, advice, options, wire) { function addSingleAdvice(addAdviceFunc, advices, proxy, advice, options, wire) {
function handleAopConnection(srcObject, srcMethod, adviceHandler) { function handleAopConnection(srcObject, srcMethod, adviceHandler) {
checkAdvisable(srcObject, srcMethod);
advices.push(addAdviceFunc(srcObject, srcMethod, adviceHandler)); advices.push(addAdviceFunc(srcObject, srcMethod, adviceHandler));
} }
return connection.parse(proxy, advice, options, wire, handleAopConnection); 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) { function makeSingleAdviceAdd(adviceType) {
return function (source, sourceMethod, advice) { return function (source, sourceMethod, advice) {
return meld[adviceType](source, sourceMethod, advice); return meld[adviceType](source, sourceMethod, advice);
...@@ -180,32 +192,18 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when, ...@@ -180,32 +192,18 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
}, target)); }, target));
} }
return {
/** /**
* Creates wire/aop plugin instances. * Creates wire/aop plugin instances.
* *
* @param ready {Promise} promise that will be resolved when the context has been wired, * @param options {Object} options passed to the plugin
* 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}
*/ */
wire$plugin: function(ready, destroyed, options) { return function(options) {
// Track aspects so they can be removed when the context is destroyed // Track aspects so they can be removed when the context is destroyed
var woven, plugin, i, len, adviceType; var woven, plugin, i, len, adviceType;
woven = []; 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 * Function to add an aspect and remember it in the current context
* so that it can be removed when the context is destroyed. * 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, ...@@ -229,6 +227,14 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
// Plugin // Plugin
plugin = { plugin = {
context: {
destroy: function(resolver) {
woven.forEach(function(aspect) {
aspect.remove();
});
resolver.resolve();
}
},
facets: { facets: {
decorate: makeFacet('configure:after', decorateFacet), decorate: makeFacet('configure:after', decorateFacet),
afterFulfilling: makeFacet(adviceStep, makeAdviceFacet(addAfterFulfillingAdvice, woven)), afterFulfilling: makeFacet(adviceStep, makeAdviceFacet(addAfterFulfillingAdvice, woven)),
...@@ -250,13 +256,10 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when, ...@@ -250,13 +256,10 @@ define(['meld', 'when', './lib/async', './lib/connection'], function(meld, when,
} }
return plugin; return plugin;
} };
};
}); });
})(typeof define == 'function' })(typeof define == 'function'
// use define for AMD if available // use define for AMD if available
? define ? define
: function(deps, factory) { : function(factory) { module.exports = factory(require); }
module.exports = factory.apply(this, deps.map(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 @@ ...@@ -44,26 +44,12 @@
define(['when', 'meld', './lib/functional', './lib/connection'], define(['when', 'meld', './lib/functional', './lib/connection'],
function(when, meld, functional, connection) { function(when, meld, functional, connection) {
return { return function eventsPlugin(/* options */) {
wire$plugin: function eventsPlugin(ready, destroyed /*, options */) {
var connectHandles = []; var connectHandles = [];
/** function handleConnection(instance, methodName, handler) {
* Create a single connection from source[event] to target[method] so that connectHandles.push(meld.on(instance, methodName, handler));
* 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 doConnect(proxy, connect, options, wire) { function doConnect(proxy, connect, options, wire) {
...@@ -71,27 +57,28 @@ function(when, meld, functional, connection) { ...@@ -71,27 +57,28 @@ function(when, meld, functional, connection) {
} }
function connectFacet(wire, facet) { function connectFacet(wire, facet) {
var connect, promises, connects; var promises, connects;
connects = facet.options; connects = facet.options;
promises = Object.keys(connects).map(function(key) {
promises = []; return doConnect(facet, key, connects[key], wire);
});
for(connect in connects) {
promises.push(doConnect(facet, connect, connects[connect], wire));
}
return when.all(promises); return when.all(promises);
} }
destroyed.then(function onContextDestroy() {
for (var i = connectHandles.length - 1; i >= 0; i--){
connectHandles[i].remove();
}
});
return { return {
context: {
destroy: function(resolver) {
connectHandles.forEach(function(handle) {
handle.remove();
});
resolver.resolve();
}
},
facets: { facets: {
// A facet named "connect" that runs during the connect
// lifecycle phase
connect: { connect: {
connect: function(resolver, facet, wire) { connect: function(resolver, facet, wire) {
resolver.resolve(connectFacet(wire, facet)); resolver.resolve(connectFacet(wire, facet));
...@@ -99,7 +86,6 @@ function(when, meld, functional, connection) { ...@@ -99,7 +86,6 @@ function(when, meld, functional, connection) {
} }
} }
}; };
}
}; };
}); });
})(typeof define == 'function' })(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 @@ ...@@ -79,10 +79,12 @@
*/ */
(function(global, define) { (function(global, define) {
define(['meld'], function(meld) { define(['meld'], function(meld) {
var timer, defaultTimeout, logger, createTracer; var timer, defaultTimeout, logger, createTracer, ownProp;
function noop() {} function noop() {}
ownProp = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
// Setup console for node, sane browsers, or IE // Setup console for node, sane browsers, or IE
logger = typeof console != 'undefined' logger = typeof console != 'undefined'
? console ? console
...@@ -355,11 +357,11 @@ define(['meld'], function(meld) { ...@@ -355,11 +357,11 @@ define(['meld'], function(meld) {
logger.log('---------------------------------------------------'); logger.log('---------------------------------------------------');
} }
return { return function wireDebug(options) {
wire$plugin:function debugPlugin(ready, destroyed, options) {
var contextTimer, timeout, paths, count, tag, logCreated, logDestroyed, checkPathsTimeout, var contextTimer, timeout, paths, count, tag,
verbose, filter, plugin, tracer; logCreated, logDestroyed, checkPathsTimeout,
verbose, filter, plugin, context, tracer;
verbose = options.verbose; verbose = options.verbose;
contextTimer = createTimer(); contextTimer = createTimer();
...@@ -375,31 +377,30 @@ define(['meld'], function(meld) { ...@@ -375,31 +377,30 @@ define(['meld'], function(meld) {
return time(msg, contextTimer); return time(msg, contextTimer);
} }
logger.log(contextTime("Context init")); logger.log(contextTime("Context debug"));
ready.then( context = {
function onContextReady(context) { initialize: function(resolver) {
cancelPathsTimeout(); logger.log(contextTime("Context init"));
logger.log(contextTime("Context ready"), context); resolver.resolve();
}, },
function onContextError(err) { ready: function(resolver) {
cancelPathsTimeout(); cancelPathsTimeout();
console.error(contextTime("Context ERROR: ") + err, err); logger.log(contextTime("Context ready"));
logStack(err); resolver.resolve();
} },
); destroy: function(resolver) {
destroyed.then(
function onContextDestroyed() {
tracer.untrace(); tracer.untrace();
logger.log(contextTime("Context destroyed")); logger.log(contextTime("Context destroyed"));
resolver.resolve();
}, },
function onContextDestroyError(err) { error: function(resolver, api, err) {
tracer.untrace(); cancelPathsTimeout();
logger.error(contextTime("Context destroy ERROR") + err, err); console.error(contextTime("Context ERROR: ") + err, err);
logStack(err); logStack(err);
resolver.reject(err);
} }
); };
function makeListener(step, verbose) { function makeListener(step, verbose) {
return function (promise, proxy /*, wire */) { return function (promise, proxy /*, wire */) {
...@@ -414,7 +415,7 @@ define(['meld'], function(meld) { ...@@ -414,7 +415,7 @@ define(['meld'], function(meld) {
if (verbose && filter(path)) { if (verbose && filter(path)) {
var message = time(step + ' ' + (path || proxy.id || ''), contextTimer); var message = time(step + ' ' + (path || proxy.id || ''), contextTimer);
if (proxy.target) { if (proxy.target) {
logger.log(message, proxy.target, proxy.spec); logger.log(message, proxy.target, proxy.metadata);
} else { } else {
logger.log(message, proxy); logger.log(message, proxy);
} }
...@@ -456,7 +457,7 @@ define(['meld'], function(meld) { ...@@ -456,7 +457,7 @@ define(['meld'], function(meld) {
msg = p + ': ' + component.status; msg = p + ': ' + component.status;
(component.status == 'ready' ? ready : notReady).push( (component.status == 'ready' ? ready : notReady).push(
{ msg: msg, spec: component.spec } { msg: msg, metadata: component.metadata }
); );
} }
...@@ -465,7 +466,7 @@ define(['meld'], function(meld) { ...@@ -465,7 +466,7 @@ define(['meld'], function(meld) {
logger.log('Components that DID NOT finish wiring'); logger.log('Components that DID NOT finish wiring');
for(p = notReady.length-1; p >= 0; --p) { for(p = notReady.length-1; p >= 0; --p) {
component = notReady[p]; component = notReady[p];
logger.error(component.msg, component.spec); logger.error(component.msg, component.metadata);
} }
} }
...@@ -474,7 +475,7 @@ define(['meld'], function(meld) { ...@@ -474,7 +475,7 @@ define(['meld'], function(meld) {
logger.log('Components that finished wiring'); logger.log('Components that finished wiring');
for(p = ready.length-1; p >= 0; --p) { for(p = ready.length-1; p >= 0; --p) {
component = ready[p]; component = ready[p];
logger.log(component.msg, component.spec); logger.log(component.msg, component.metadata);
} }
} }
} else { } else {
...@@ -484,15 +485,49 @@ define(['meld'], function(meld) { ...@@ -484,15 +485,49 @@ define(['meld'], function(meld) {
logSeparator(); 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 = { plugin = {
context: context,
create:function (promise, proxy) { create:function (promise, proxy) {
var path = proxy.path; var path, component;
path = proxy.path;
component = proxy.target;
count++; count++;
paths[path || ('(unnamed-' + 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); logCreated(promise, proxy);
}, },
configure: makeListener('configured', verbose), configure: makeListener('configured', verbose),
...@@ -516,7 +551,6 @@ define(['meld'], function(meld) { ...@@ -516,7 +551,6 @@ define(['meld'], function(meld) {
checkPathsTimeout = setTimeout(checkPaths, timeout); checkPathsTimeout = setTimeout(checkPaths, timeout);
return plugin; return plugin;
}
}; };
}); });
......
...@@ -42,7 +42,7 @@ define(['../lib/plugin-base/on', 'dojo/on', 'dojo/query'], function(createOnPlug ...@@ -42,7 +42,7 @@ define(['../lib/plugin-base/on', 'dojo/on', 'dojo/query'], function(createOnPlug
on.wire$plugin = createOnPlugin({ on.wire$plugin = createOnPlugin({
on: on on: on
}).wire$plugin; });
return on; return on;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* http://www.opensource.org/licenses/mit-license.php * 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({ return createDomPlugin({
addClass: base.addClass, 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