--- markup/html/scripting-parser/parser.html 2008/04/27 10:44:36 1.11 +++ markup/html/scripting-parser/parser.html 2008/04/27 11:21:09 1.12 @@ -79,6 +79,7 @@ this.input = i; this.scriptsExecutedAfterParsing = []; this.scriptsExecutedSoon = []; + this.scriptsExecutedAsynchronously = []; } // Parser Parser.prototype.getNextToken = function () { @@ -335,22 +336,42 @@ // "When a script completes loading" rules start applying. - // List of scripts that will execute as soon as possible - for (var i = 0; i < this.scriptsExecutedSoon.length; i++) { - var e = this.scriptsExecutedSoon[i]; + while (this.scriptsExecutedSoon.length > 0 || + this.scriptsExecutedAsynchronously.length > 0) { + // Handle "list of scripts that will execute as soon as possible". + while (this.scriptsExecutedSoon.length > 0) { + var e = this.scriptsExecutedSoon.shift (); + + // If it has completed loading + log ('Execute an external script not inserted by parser...'); + executeScript (this.doc, e); + + // NOTE: It MAY be executed before the end of the parsing, according + // to the spec. + this.hasAsyncScript = true; + } + + // Handle "list of scripts that will execute asynchronously". + while (this.scriptsExecutedAsynchronously.length > 0) { + var e = this.scriptsExecutedAsynchronously.shift (); + + // Step 1. + // We assume that all scripts have been loaded at this time. + + // Step 2. + log ('Execute an asynchronous script...'); + executeScript (this.doc, e); + + // Step 3. + // + + // Step 4. + // - // If it has completed loading - log ('Execute an external script not inserted by parser...'); - executeScript (this.doc, e); - - // NOTE: It MAY be executed before the end of the parsing, according - // to the spec. - this.hasAsyncScript = true; + this.hasAsyncScript = true; + } } - // TODO: Handles - // "list of scripts that will execute asynchronously" - // Handle "list of scripts that will execute when the document has finished // parsing". var list = this.scriptsExecutedAfterParsing; @@ -444,10 +465,13 @@ p.scriptsExecutedAfterParsing.push (e); log ('Running a script: aborted (defer)'); } else if (e.async && e.src != null) { - // TODO - } else if (e.async && e.src == null - /* && list of scripts that will execute asynchronously is not empty */) { - // TODO + p.scriptsExecutedAsynchronously.push (e); + log ('Running a script: aborted (async src)'); + } else if (e.async && e.src == null && + p.scriptsExecutedAsynchronously.length > 0) { + p.scriptsExecutedAsynchronously.push (e); + log ('Running a script: aborted (async)'); + // ISSUE: What is the difference with the case above? } else if (e.src != null && e.manakaiParserInserted) { if (p.scriptExecutedWhenParserResumes) { log ('Error: There is a script that will execute as soon as the parser resumes.'); @@ -792,11 +816,21 @@ the regular expression ^javascript:\s*(?:"[^"]*"|'[^']*')\s*$.
  • Only supports \uHHHH escapes in JavaScript string literals. +
  • Does not handle stop parsing phase correctly if the document is +replaced by document.open () call. In other word, delayed +(deferred or asynchronous) script executions and event firings might be +treated in a wrong way if a document.open () invocation +is implicitly done by document.write () in a delayed script.

    For some reason, this parser does not work in browsers that do not support JavaScript 1.5. + +