Skip to content

Commit

Permalink
pull in saner code to set api (from config branch) and also *some* of…
Browse files Browse the repository at this point in the history
… the cleaner config code
  • Loading branch information
unscriptable committed Nov 29, 2012
1 parent f995889 commit ae737b7
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 96 deletions.
237 changes: 143 additions & 94 deletions src/curl.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
var var
version = '0.7.3', version = '0.7.3',
curlName = 'curl', curlName = 'curl',
defineName = 'define',
userCfg, userCfg,
prevCurl, prevCurl,
define, prevDefine,
doc = global.document, doc = global.document,
head = doc && (doc['head'] || doc.getElementsByTagName('head')[0]), head = doc && (doc['head'] || doc.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
Expand Down Expand Up @@ -424,84 +425,108 @@
return def.url || (def.url = core.checkToAddJsExt(def.require['toUrl'](def.id), def.config)); return def.url || (def.url = core.checkToAddJsExt(def.require['toUrl'](def.id), def.config));
}, },


config: function (cfg) { /**
var setDefaults, defineName, failMsg, okToOverwrite, * Sets the curl() and define() APIs.
apiName, apiContext, apiObj, * @param [cfg] {Object|Null} set of config params. If missing or null,
defName, defContext, defObj; * this function will set the default API!

*/
// no config was specified, yet setApi: function (cfg) {
setDefaults = !cfg; /*

scenarios:
// switch to re-runnable config 1. global config sets apiName: "require"
if (cfg) core.config = core.moreConfig; - first call to config sets api

- second and later calls are ignored
defineName = 'define'; - prevCurl cannot exist
2. no global config, first call to config() sets api
- first call to config has no api info
- second call to config sets api
- third and later calls must be ignored
3. global config that doesn't set api, first call does though
- same as #2
4. api info is never set
- how to know when to stop ignoring?
objectives:
1. fail before mistakenly overwriting global[curlName]
2. allow rename/relocate of curl() and define()
3. restore curl() if we overwrote it
*/

var apiName, defName, apiObj, defObj,
failMsg, okToOverwrite;

apiName = curlName;
defName = defineName;
apiObj = defObj = global;
failMsg = ' already exists'; failMsg = ' already exists';


if (!cfg) cfg = {}; // if we're not setting defaults

if (cfg) {
// allow dev to rename/relocate curl() to another object // is it ok to overwrite existing api functions?
apiName = cfg['apiName'] || curlName; okToOverwrite = cfg['overwriteApi'] || cfg.overwriteApi;
apiContext = cfg['apiContext']; // allow dev to rename/relocate curl() to another object
apiObj = apiContext || global; apiName = cfg['apiName'] || cfg.apiName || apiName;
defName = cfg['defineName'] || defineName; apiObj = cfg['apiContext'] || cfg.apiContext || apiObj;
defContext = cfg['defineContext']; // define() too
defObj = defContext || global; defName = cfg['defineName'] || cfg.defineName || defName;

defObj = cfg['defineContext'] || cfg.defineContext || defObj;
// is it ok to overwrite an existing api functions?
okToOverwrite = cfg['overwriteApi']; // curl() already existed, restore it if this is not a

// setDefaults pass. dev must be a good citizen and set
// restore previous (global) curl, if it was blown away // apiName/apiContext (see below).
// by us. this can happen when configuring curl's api if (prevCurl && isType(prevCurl, 'Function')) {
// after loading it. do this before any throws below. // restore previous curl()
if (!setDefaults && prevCurl) { global[curlName] = prevCurl;
global[curlName] = prevCurl;
prevCurl = false;
}

// only throw if we're overwriting curl accidentally and this
// isn't a setDefaults pass. (see else)
if (!setDefaults && !okToOverwrite && apiObj[apiName] && apiObj[apiName] != _curl) {
throw new Error(apiName + failMsg);
}
else {
// if setDefaults, we must overwrite curl so that dev can
// configure it. (in this case, the following is the same as
// global.curl = _curl;)
apiObj[apiName] = _curl;
}

// if setDefaults, only create define() if it doesn't already exist.
if (!(setDefaults && global[defineName])) {
if (!setDefaults && !okToOverwrite && defName in defObj && defObj[defName] != define) {
throw new Error(defName + failMsg);
} }
else { prevCurl = null; // don't check ever again
// create AMD public api: define() // ditto for define()
defObj[defName] = define = function () { if (prevDefine && isType(prevDefine, 'Function')) {
// wrap inner _define so it can be replaced without losing define.amd // restore previous curl()
var args = core.fixArgs(arguments); global[defineName] = prevDefine;
_define(args);
};
} }
// indicate our capabilities: prevDefine = null; // don't check ever again
define['amd'] = { 'plugins': true, 'jQuery': true, 'curl': version };
// check if we're mistakenly overwriting either api
// if we're configuring, and there's a curl(), and it's not
// ours -- and we're not explicitly overwriting -- throw!
// Note: if we're setting defaults, we *must* overwrite curl
// so that dev can configure it. This is no different than
// noConflict()-type methods.
if (!okToOverwrite) {
if (apiObj[apiName] && apiObj[apiName] != _curl) {
throw new Error(apiName + failMsg);
}
// check if we're overwriting amd api
if (defObj[defName] && defObj[defName] != define) {
throw new Error(defName + failMsg);
}
}

} }


return core.moreConfig(cfg); // set curl api
apiObj[apiName] = _curl;

// set AMD public api: define()
defObj[defName] = define;

}, },


moreConfig: function (cfg, prevCfg) { config: function (cfg) {
var newCfg, pluginCfgs, p; var prevCfg, newCfg, pluginCfgs, p;

// convert from closure-safe names
if ('baseUrl' in cfg) cfg.baseUrl = cfg['baseUrl'];
if ('main' in cfg) cfg.main = cfg['main'];
if ('preloads' in cfg) cfg.preloads = cfg['preloads'];
if ('pluginPath' in cfg) cfg.pluginPath = cfg['pluginPath'];
if ('dontAddFileExt' in cfg || cfg.dontAddFileExt) {
cfg.dontAddFileExt = new RegExp(cfg['dontAddFileExt'] || cfg.dontAddFileExt);
}


if (!prevCfg) prevCfg = {}; prevCfg = userCfg;
newCfg = beget(prevCfg, cfg); newCfg = beget(prevCfg, cfg);


// set defaults and convert from closure-safe names
newCfg.baseUrl = newCfg['baseUrl'] || '';
newCfg.pluginPath = newCfg['pluginPath'] || 'curl/plugin';
newCfg.dontAddFileExt = new RegExp(newCfg['dontAddFileExt'] || dontAddExtRx);

// create object to hold path map. // create object to hold path map.
// each plugin and package will have its own pathMap, too. // each plugin and package will have its own pathMap, too.
newCfg.pathMap = beget(prevCfg.pathMap); newCfg.pathMap = beget(prevCfg.pathMap);
Expand All @@ -526,7 +551,7 @@
}; };
// grab the package id, if specified. default to // grab the package id, if specified. default to
// property name, if missing. // property name, if missing.
data.name = data['name'] || name; data.name = data.name || name;
currCfg = newCfg; currCfg = newCfg;
// check if this is a plugin-specific path // check if this is a plugin-specific path
parts = pluginParts(removeEndSlash(data.name)); parts = pluginParts(removeEndSlash(data.name));
Expand Down Expand Up @@ -715,9 +740,9 @@
// Note: ignores require() inside strings and comments // Note: ignores require() inside strings and comments
var source, ids = [], currQuote; var source, ids = [], currQuote;
// prefer toSource (FF) since it strips comments // prefer toSource (FF) since it strips comments
source = typeof defFunc == 'string' source = typeof defFunc == 'string' ?
? 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, id, qq) {
// if we encounter a quote // if we encounter a quote
Expand Down Expand Up @@ -967,7 +992,7 @@
} }
else { else {
// TODO: move config.moduleLoader to config.transform // TODO: move config.moduleLoader to config.transform
loaderId = pathInfo.config['moduleLoader']; loaderId = pathInfo.config['moduleLoader'] || pathInfo.config.moduleLoader;
if (loaderId) { if (loaderId) {
// TODO: allow transforms to have relative module ids? // TODO: allow transforms to have relative module ids?
// (we could do this by returning package location from // (we could do this by returning package location from
Expand Down Expand Up @@ -1107,17 +1132,20 @@
} }


function _config (cfg) { function _config (cfg) {
userCfg = core.config(cfg, userCfg); if (cfg) {
// check for preloads core.setApi(cfg);
core.checkPreloads(cfg); userCfg = core.config(cfg);
// check for main module(s) // check for preloads
if (cfg && 'main' in cfg) { core.checkPreloads(cfg);
// start in next turn to wait for other modules in current file // check for main module(s)
setTimeout(function () { if ('main' in cfg) {
var ctx; // start in next turn to wait for other modules in current file
ctx = core.createContext(userCfg, undef, [].concat(cfg['main'])); setTimeout(function () {
core.getDeps(ctx); var ctx;
}, 0); ctx = core.createContext(userCfg, undef, [].concat(cfg['main']));
core.getDeps(ctx);
}, 0);
}
} }
} }


Expand Down Expand Up @@ -1183,20 +1211,41 @@


} }


// look for pre-existing globals function define () {
userCfg = global[curlName]; // wrap inner _define so it can be replaced without losing define.amd
if (typeof userCfg == 'function') { var args = core.fixArgs(arguments);
prevCurl = userCfg; _define(args);
userCfg = false; }

// indicate our capabilities:
define['amd'] = { 'plugins': true, 'jQuery': true, 'curl': version };

// default configs
userCfg = {
baseUrl: '',
pluginPath: 'curl/plugin',
dontAddFileExt: dontAddExtRx,
paths: {},
packages: {},
plugins: {},
pathMap: {},
pathRx: /$^/
};

// handle pre-existing global
prevCurl = global[curlName];
prevDefine = global[defineName];
if (!prevCurl || isType(prevCurl, 'Function')) {
// set default api
core.setApi();
} }
else { else {
// don't use delete here since IE6-8 fail // remove global curl object
global[curlName] = undef; global[curlName] = undef; // can't use delete in IE 6-8
// configure curl
_config(prevCurl);
} }


// configure first time
_config(userCfg);

// allow curl to be a dependency // allow curl to be a dependency
cache[curlName] = _curl; cache[curlName] = _curl;


Expand Down
4 changes: 2 additions & 2 deletions test/then.html
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
} }
}, },
function (ex) { function (ex) {
write('FAILED: ', + ex.message); write('FAILED: ' + ex.message);
} }
).then( ).then(
function (three, one) { function (three, one) {
Expand Down Expand Up @@ -81,7 +81,7 @@
write('SUCCESS: js! plugin.'); write('SUCCESS: js! plugin.');
}, },
function (ex) { function (ex) {
write('FAILED: js! plugin. ' + ex && ex.message); write('FAILED: js! plugin. ' + ex.message);
} }
); );


Expand Down

0 comments on commit ae737b7

Please sign in to comment.