diff --git a/src/curl.js b/src/curl.js
index 96fc708b..a2c5b6ea 100644
--- a/src/curl.js
+++ b/src/curl.js
@@ -9,29 +9,30 @@
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
- * @version 0.6.2
*/
(function (global) {
var
- version = '0.6.2',
+ version = '0.6.2a',
userCfg = global['curl'],
doc = global.document,
head = doc && (doc['head'] || doc.getElementsByTagName('head')[0]),
-// // constants / flags
+ // to keep IE from crying, we need to put scripts before any
+ // elements, but after any . this should do it:
+ insertBeforeEl = head && head.getElementsByTagName('base')[0] || null,
+ // constants / flags
msgUsingExports = {},
msgFactoryExecuted = {},
- interactive = {},
// this is the list of scripts that IE is loading. one of these will
// be the "interactive" script. too bad IE doesn't send a readystatechange
// event to tell us exactly which one.
activeScripts = {},
+ // readyStates for IE6-9
+ readyStates = 'addEventListener' in global ? {} : { 'loaded': 1, 'complete': 1 },
// these are always handy :)
cleanPrototype = {},
toString = cleanPrototype.toString,
undef,
- // script ready states that signify it's loaded
- readyStates = { 'loaded': 1, 'interactive': interactive, 'complete': 1 },
// local cache of resource definitions (lightweight promises)
cache = {},
// preload are files that must be loaded before any others
@@ -230,7 +231,7 @@
function toUrl (n) {
// even though internally, we don't seem to need to do
// toAbsId, the AMD spec says we need to do this for plugins.
- // also, thesec states that we should not append an extension
+ // also, the spec states that we should not append an extension
// in this function.
return core.resolvePathInfo(toAbsId(n), cfg).url;
}
@@ -517,6 +518,9 @@
function process (ev) {
ev = ev || global.event;
// detect when it's done loading
+ // ev.type == 'load' is for all browsers except IE6-9
+ // IE6-9 need to use onreadystatechange and look for
+ // el.readyState in {loaded, complete} (yes, we need both)
if (ev.type == 'load' || readyStates[el.readyState]) {
delete activeScripts[def.id];
// release event listeners
@@ -547,9 +551,8 @@
// IE will load the script sync if it's in the cache, so
// indicate the current resource definition if this happens.
activeScripts[def.id] = el;
- // use insertBefore to keep IE from throwing Operation Aborted (thx Bryan Forbes!)
- head.insertBefore(el, head.firstChild);
+ head.insertBefore(el, insertBeforeEl);
},
extractCjsDeps: function (defFunc) {
@@ -569,7 +572,7 @@
else if (!currQuote) {
ids.push(id);
}
- return m; // uses least RAM/CPU
+ return ''; // uses least RAM/CPU
});
return ids;
},
@@ -683,7 +686,7 @@
// signal any waiters/parents that we can export
// early (see progress callback in getDep below).
// note: this may fire for `require` as well, if it
- // is listed after `module` or `exports` in teh deps list,
+ // is listed after `module` or `exports` in the deps list,
// but that is okay since all waiters will only record
// it once.
if (parentDef.exports) {
@@ -906,7 +909,7 @@
},
getCurrentDefName: function () {
- // IE marks the currently executing thread as "interactive"
+ // IE6-9 mark the currently executing thread as "interactive"
// Note: Opera lies about which scripts are "interactive", so we
// just have to test for it. Opera provides a true browser test, not
// a UA sniff, thankfully.
@@ -914,7 +917,7 @@
var def;
if (!isType(global.opera, 'Opera')) {
for (var d in activeScripts) {
- if (readyStates[activeScripts[d].readyState] == interactive) {
+ if (activeScripts[d].readyState == 'interactive') {
def = d;
break;
}
diff --git a/src/curl/plugin/js.js b/src/curl/plugin/js.js
index 2846c99d..21ef63d8 100644
--- a/src/curl/plugin/js.js
+++ b/src/curl/plugin/js.js
@@ -28,14 +28,12 @@
* http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
*
*/
-(function (global, doc) {
+(function (global, doc, testGlobalVar) {
+define(/*=='js',==*/ ['curl/_privileged'], function (priv) {
"use strict";
var cache = {},
queue = [],
supportsAsyncFalse = doc && doc.createElement('script').async == true,
- readyStates = { 'loaded': 1, 'interactive': 1, 'complete': 1 },
- orsc = 'onreadystatechange',
- head = doc && (doc['head'] || doc.getElementsByTagName('head')[0]),
waitForOrderedScript,
undef;
@@ -44,43 +42,31 @@
name + '.' + defaultExt : name;
}
- // TODO: find a way to reuse the loadScript from curl.js
function loadScript (def, success, failure) {
// script processing rules learned from RequireJS
- var deadline, el;
+ var deadline, completed, el;
// default deadline is very far in the future (5 min)
// devs should set something reasonable if they want to use it
- deadline = new Date().valueOf() + (def.timeoutMsec || 300) * 1000;
-
- // insert script
- el = doc.createElement('script');
+ deadline = new Date().valueOf() + (def.timeoutMsec || 300000);
// initial script processing
- function process (ev) {
- ev = ev || global.event;
- // detect when it's done loading
- if (ev.type == 'load' || readyStates[el.readyState]) {
- // release event listeners
- el.onload = el[orsc] = el.onerror = "";
- if (def.exports) def.resolved = testGlobalVar(def.exports);
- if (!def.exports || def.resolved) {
- success(el);
- }
- else {
- fail();
- }
+ function process () {
+ completed = true;
+ if (def.exports) def.resolved = testGlobalVar(def.exports);
+ if (!def.exports || def.resolved) {
+ success(el); // pass el so it can be removed (text/cache)
+ }
+ else {
+ failure();
}
}
- function fail () {
- // some browsers send an event, others send a string,
- // but none of them send anything useful, so just say we failed:
- el.onload = el[orsc] = el.onerror = "";
- if (failure) {
- failure(new Error('Script error or http error: ' + def.url));
- }
+ function fail (ex) {
+ // Exception is squashed by curl.js unfortunately
+ completed = true;
+ failure(ex);
}
// some browsers (Opera and IE6-8) don't support onerror and don't fire
@@ -89,31 +75,19 @@
// is defined (see below)
function poller () {
// if the script loaded
- if (el.onload && readyStates[el.readyState]) {
- process({});
- }
- // if neither process or fail as run and our deadline is in the past
- else if (el.onload && deadline < new Date()) {
- fail();
- }
- else {
- setTimeout(poller, 10);
+ if (!completed) {
+ // if neither process or fail as run and our deadline is in the past
+ if (deadline < new Date()) {
+ failure();
+ }
+ else {
+ setTimeout(poller, 10);
+ }
}
}
if (failure && def.exports) setTimeout(poller, 10);
- // set type first since setting other properties could
- // prevent us from setting this later
- el.type = def.mimetype || 'text/javascript';
- // using dom0 event handlers instead of wordy w3c/ms
- el.onload = el[orsc] = process;
- el.onerror = fail;
- el.charset = def.charset || 'utf-8';
- el.async = !def.order;
- el.src = def.url;
-
- // use insertBefore to keep IE from throwing Operation Aborted (thx Bryan Forbes!)
- head.insertBefore(el, head.firstChild);
+ el = priv['core'].loadScript(def, process, fail);
}
@@ -137,16 +111,7 @@
}
- function testGlobalVar (varName) {
- try {
- return eval('global.' + varName);
- }
- catch (ex) {
- return undef;
- }
- }
-
- define(/*=='js',==*/ {
+ return {
// the !options force us to cache ids in the plugin
'dynamic': true,
@@ -194,8 +159,8 @@
def.mimetype = 'text/cache';
loadScript(def,
// remove the fake script when loaded
- function (el) { el.parentNode.removeChild(el); },
- false
+ function (el) { el && el.parentNode.removeChild(el); },
+ function () {}
);
def.mimetype = '';
}
@@ -209,6 +174,10 @@
}
- });
-
-}(this, this.document));
+ };
+});
+}(
+ this,
+ this.document,
+ function () { try { return eval(arguments[0]); } catch (ex) { return; } }
+));