Skip to content

Commit

Permalink
Merge branch 'dev' of git@github.com:unscriptable/curl into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
unscriptable committed Jul 20, 2011
2 parents b646b1b + 8577e18 commit b123d2a
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 131 deletions.
121 changes: 72 additions & 49 deletions src/curl.js
Expand Up @@ -61,7 +61,7 @@
aslice = [].slice,
// RegExp's used later, "cached" here
absUrlRx = /^\/|^[^:]*:\/\//,
normalizeRx = /^\.(\/|$)/,
normalizeRx = /^(\.)(\.)?(\/|$)/,
findSlashRx = /\//,
hasExtRx = /\.\w+$/,
pathSearchRx,
Expand All @@ -72,7 +72,8 @@
defaultDescriptor = {
main: './lib/main',
lib: './lib'
};
},
debug;

function isType (obj, type) {
return toString.call(obj).indexOf('[object ' + type) == 0;
Expand Down Expand Up @@ -104,6 +105,14 @@

baseUrl = cfg['baseUrl'] || '';

if (cfg['debug']) {
debug = true;
// add debugging aides
_curl['cache'] = cache;
_curl['cfg'] = cfg;
_curl['undefine'] = function (moduleId) { delete cache[moduleId]; };
}

// fix all paths
var cfgPaths = cfg['paths'];
for (p in cfgPaths) {
Expand Down Expand Up @@ -145,25 +154,25 @@
ctx = {
baseName: baseName
},
exports = {};
exports = {},
require = function (deps, callback) {
return _require(deps, callback || noop, ctx);
};
// CommonJS Modules 1.1.1 compliance
ctx.vars = {
exports: exports,
module: {
'id': normalizeName(name, baseName),
'uri': toUrl(name),
exports: exports
},
require: function (deps, callback) {
return _require(deps, callback || noop, ctx);
}
};
ctx.require = ctx.vars.require;
if (userCfg['debug']) {
ctx.require['curl'] = _curl;
if (debug) {
require['curl'] = _curl;
}
ctx.require = ctx.vars.require = require;
// using bracket property notation so closure won't clobber name
ctx.require['toUrl'] = toUrl;
require['toUrl'] = toUrl;

return ctx;
}
Expand Down Expand Up @@ -198,27 +207,24 @@
}
}

return {
then: function (resolved, rejected) {
then(resolved, rejected);
return self;
},
resolve: function (val) {
self.resolved = val;
resolve(val);
},
reject: function (ex) {
self.rejected = ex;
reject(ex);
}
}
this.then = function (resolved, rejected) {
then(resolved, rejected);
return self;
};
this.resolve = function (val) {
self.resolved = val;
resolve(val);
};
this.reject = function (ex) {
self.rejected = ex;
reject(ex);
};

}

function ResourceDef (name) {
var promise = Promise();
promise.name = name;
return promise;
Promise.apply(this);
this.name = name;
}

function endsWithSlash (str) {
Expand Down Expand Up @@ -350,14 +356,27 @@

function resolveResDef (def, args, ctx) {

var childCtx = begetCtx(def.name);
if (debug && console) {
console.log('curl: resolving', def.name);
}

// if a module id has been remapped, it will have a baseName
var childCtx = begetCtx(def.baseName || def.name);

// get the dependencies and then resolve/reject
getDeps(def, args.deps, childCtx,
function (deps) {
// node.js assumes `this` === exports
// anything returned overrides exports
var res = args.res.apply(childCtx.vars.exports, deps) || childCtx.vars.exports;
try {
// node.js assumes `this` === exports
// anything returned overrides exports
var res = args.res.apply(childCtx.vars.exports, deps) || childCtx.vars.exports;
if (debug && console) {
console.log('curl: defined', def.name, res.toString().substr(0, 50).replace(/\n/, ' '));
}
}
catch (ex) {
def.reject(ex);
}
def.resolve(res);
},
def.reject
Expand Down Expand Up @@ -403,7 +422,10 @@

function normalizeName (name, baseName) {
// if name starts with . then use parent's name as a base
return name.replace(normalizeRx, baseName + '/');
// if name starts with .. then use parent's parent
return name.replace(normalizeRx, function (match, dot1, dot2) {
return (dot2 ? baseName.substr(0, baseName.lastIndexOf('/')) : baseName) + '/';
});
}

function fetchDep (depName, ctx) {
Expand All @@ -427,14 +449,14 @@
// the spec is unclear, so we're using the full name (prefix + name) to id resources
def = cache[name];
if (!def) {
//var pathInfo = resolvePath(resName, baseUrl);
var pluginDef = cache[prefix];
if (!pluginDef) {
pluginDef = cache[prefix] = new ResourceDef(prefix);
pluginDef.url = resolveUrl(prefixPath, baseUrl);
fetchResDef(pluginDef, ctx)
pluginDef.baseName = prefixPath;
fetchResDef(pluginDef, ctx);
}
def = new ResourceDef(resName);
def = new ResourceDef(name);
// resName could be blank if the plugin doesn't specify a name (e.g. "domReady!")
if (resName) {
cache[name] = def;
Expand All @@ -449,7 +471,7 @@
loaded['resolve'] = loaded;
loaded['reject'] = def.reject;
// load the resource!
plugin.load(def.name, ctx.require, loaded, userCfg);
plugin.load(resName, ctx.require, loaded, userCfg);
},
def.reject
);
Expand Down Expand Up @@ -562,7 +584,8 @@

// extract config, if it's specified
if (isType(args[0], 'Object')) {
extractCfg(args.shift());
userCfg = args.shift();
extractCfg(userCfg);
}

// extract dependencies
Expand All @@ -589,9 +612,12 @@
api['next'] = function (names, cb) {
var origPromise = promise;
promise = new Promise();
// wait for the previous promise
origPromise.then(
// get dependencies and then resolve the previous promise
function () { ctx.require(names, promise, ctx); }
// get dependencies and then resolve the current promise
function () { ctx.require(names, promise, ctx); },
// fail the current promise
function (ex) { promise.reject(ex); }
);
// execute this callback after dependencies
if (cb) {
Expand Down Expand Up @@ -633,14 +659,19 @@
def = cache[name] = new ResourceDef(name);
}
def.useNet = false;
resolveResDef(def, args, begetCtx(name));
// check if this resource has already been resolved (can happen if
// a module was defined inside a built file and outside of it and
// dev didn't coordinate it explicitly)
if (!('resolved' in def)) {
resolveResDef(def, args, begetCtx(name));
}
}

}

/***** grab any global configuration info *****/

// if userCfg is a function, assume require() exists already
// if userCfg is a function, assume curl() exists already
var conflict = isType(userCfg, 'Function');
if (!conflict) {
extractCfg(userCfg);
Expand All @@ -656,14 +687,6 @@
global['curl'] = _curl;
}

if (userCfg['debug']) {
_curl['cache'] = _require['cache'] = cache;
_curl['cfg'] = _require['cfg'] = userCfg;
_curl['listen'] = function (which, callback) {
eval('var orig=which;which=function(){callback.apply(null,arguments);return orig.apply(null,arguments);};');
};
}

// using bracket property notation so closure won't clobber name
global['define'] = _curl['define'] = _define;
_curl['version'] = version;
Expand Down
37 changes: 11 additions & 26 deletions src/curl/debug.js
Expand Up @@ -15,50 +15,35 @@
*/
(function (global) {

define(function (require) {
define(['require'], function (require) {

var curl = require['curl'],
cache = curl['cache'],
listen = curl['listen'],
apiName = curl['cfg']['apiName'] || 'curl',
totalWaiting = 0,
prevTotal;
var curl, cache, totalWaiting, prevTotal;

if (!curl || !listen) {
curl = require['curl'];

if (!curl) {
throw new Error('You must also enable debugging via the debug:true config param.');
}
else if (typeof console == 'undefined') {
throw new Error('No console to output debug info.');
throw new Error('`console` object must be defined to use debug module.');
}
else {

cache = curl['cache'];
totalWaiting = 0;

function count () {
totalWaiting = 0;
for (var p in cache) {
if (cache[p].resolved) totalWaiting++;
if ('resolved' in cache[p]) totalWaiting++;
}
}
count();

listen('_define', function () {
var args = [].slice.apply(arguments).join(', ');
console.log('curl: define(' + args + ');');
});

listen('_require', function () {
var args = [].slice.apply(arguments).join(', ');
console.log('curl: require(' + args + ');');
});

listen('_curl', function () {
var args = [].slice.apply(arguments).join(', ');
console.log('curl: ' + apiName + '(' + args + ');');
});

function periodicLogger () {
count();
if (prevTotal != totalWaiting) {
console.log('curl: modules waiting: ' + totalWaiting);
console.log('curl: ********** modules waiting: ' + totalWaiting);
}
prevTotal = totalWaiting;
setTimeout(periodicLogger, 500);
Expand Down
16 changes: 11 additions & 5 deletions src/curl/dojo16Compat.js
Expand Up @@ -19,7 +19,7 @@
(function (global) {

// satisfy loader:
define(/*=='curl/dojo16Compat',==*/ function () {
define(/*=='curl/dojo16Compat',==*/ ['./domReady'], function (domReady) {

// TODO: figure out a better way to grab global curl
// we should probably just add "curl" as a dependency (???)
Expand All @@ -29,23 +29,24 @@
function duckPunchRequire (req) {
if (!req['ready']){
req['ready'] = function (cb) {
curl(['domReady!'], cb);
domReady(cb);
};
}
if (!req['nameToUrl']) {
req['nameToUrl'] = function (name, ext) {
// map non-standard nameToUrl to toUrl
return req['toUrl'](name) + (ext || '');
return req['toUrl'](name + (ext || ''));
};
}
return req;
}

// modify global curl
// modify global curl cuz dojo doesn't always use standard `require`
// as a dependency
duckPunchRequire(curl);

global['define'] = function () {
var args, len, names, reqPos = [], defFunc, i;
var args, len, names, reqPos = [], defFunc, i, needsDomReady;
// find dependency array
args = [].slice.call(arguments);
len = args.length;
Expand All @@ -58,6 +59,7 @@
if (names[i] == 'require') {
reqPos.push(i);
}
// needsDomReady = needsDomReady || names[i] == 'dojo/_base/html';
}
// if there are any
if (reqPos.length > 0) {
Expand All @@ -71,6 +73,10 @@
return defFunc.apply(this, deps);
};
}
// if we need to fix dojo's domReady bugs
// if (needsDomReady) {
// names.push('domReady!');
// }
}
return define.apply(null, args);
};
Expand Down
1 change: 1 addition & 0 deletions src/curl/plugin/async.js
@@ -1,4 +1,5 @@
/*
(c) copyright 2011, unscriptable.com / John M. Hann
async plugin takes another module as it's resource and defers callback
until that module is complete. the module must return a promise-like
Expand Down

0 comments on commit b123d2a

Please sign in to comment.