--- markup/html/scripting-parser/parser.html 2008/04/29 03:29:41 1.15
+++ markup/html/scripting-parser/parser.html 2008/08/31 09:50:49 1.19
@@ -83,6 +83,7 @@
doc = new JSDocument (this);
doc.manakaiIsHTML = true;
}
+ this.nextToken = [];
this.doc = doc;
this.openElements = [doc];
this.input = i;
@@ -92,6 +93,10 @@
} // Parser
Parser.prototype.getNextToken = function () {
+ if (this.nextToken.length) {
+ return this.nextToken.shift ();
+ }
+
var p = this;
var i = this.input;
if (this.parseMode == 'cdata') {
@@ -146,7 +151,7 @@
i.s = i.s.replace (/^<\/([^>]+)(?:>|$)/, function (s, e) {
if (p.insertionPoint < s.length ||
(p.insertionPoint <= s.length &&
- s.substring (s.length - 1, 1) != '>')) {
+ s.substring (s.length - 1, s.length) != '>')) {
token = {type: 'abort'};
return s;
}
@@ -158,7 +163,7 @@
i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) {
if (p.insertionPoint < s.length ||
(p.insertionPoint <= s.length &&
- s.substring (s.length - 1, 1) != '>')) {
+ s.substring (s.length - 1, s.length) != '>')) {
token = {type: 'abort'};
return s;
}
@@ -221,6 +226,24 @@
var token = this.getNextToken ();
log ('token: ' + token.type + ' "' + token.value + '"');
+ if (this.cdataEndTagRequired) {
+ // Generic CDATA parsing algorithm
+
+ if (token.type != 'abort') {
+ // 7.
+ if (token.type == 'end-tag' && token.value == this.endTagName) {
+ // 7.1. Ignores it.
+ //
+ } else {
+ // 7.2. Parse error.
+ log ('Parse error: no ' + this.endTagName + '>');
+ this.nextToken.unshift (token);
+ }
+ this.cdataEndTagRequired = false;
+ continue;
+ }
+ }
+
if (token.type == 'start-tag') {
if (token.value == 'script') {
// 1. Create an element for the token in the HTML namespace.
@@ -257,6 +280,7 @@
if (!(token.type == 'end-tag' && token.value == 'script')) {
// 7.2. This is a parse error.
log ('Parse error: no ' + 'script>');
+ this.nextToken.unshift (token);
// 7.3. Mark the script element as "already executed".
el.manakaiAlreadyExecuted = true;
@@ -288,8 +312,8 @@
oldInsertionPoint += this.insertionPoint;
this.setInsertionPoint (oldInsertionPoint);
- // 12. If there is a script that will execute as soon as ...
- while (this.scriptExecutedWhenParserResumes) {
+ // 12. If there is a pending external script
+ while (this.pendingExternalScript) {
// 12.1. If the tree construction stage is being called reentrantly
if (this.reentrant) {
log ('parse: abort (reentrance)');
@@ -299,8 +323,8 @@
// 12.2. Otherwise
} else {
// 1.
- var script = this.scriptExecutedWhenParserResumes;
- this.scriptExecutedWhenParserResumes = null;
+ var script = this.pendingExternalScript;
+ this.pendingExternalScript = null;
// 2. Pause until the script has completed loading.
//
@@ -348,11 +372,17 @@
// 6. Switched back to the PCDATA state.
this.parseMode = 'pcdata';
+ if (token.type == 'abort') {
+ this.cdataEndTagRequired = true;
+ break;
+ }
+
// 7.1. If the next token is not an end tag token with ...
if (!(token.type == 'end-tag' &&
token.value == this.endTagName)) {
// 7.2. This is a parse error.
log ('Parse error: no ' + this.endTagName + '>');
+ this.nextToken.unshift (token);
// 7.3. Mark the script element as "already executed".
el.manakaiAlreadyExecuted = true;
@@ -530,10 +560,10 @@
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.');
+ if (p.pendingExternalScript) {
+ log ('Error: There is a pending external script.');
}
- p.scriptExecutedWhenParserResumes = e;
+ p.pendingExternalScript = e;
log ('Running a script: aborted (src parser-inserted)');
} else if (e.src != null) {
p.scriptsExecutedSoon.push (e);
@@ -568,7 +598,6 @@
}
// If the load was successful
- log ('load event fired at the script element');
if (true) {
// Scripting is enabled, Document.designMode is disabled,
@@ -577,6 +606,8 @@
parseAndRunScript (doc, s);
}
+ log ('load event fired at the script element');
+
log ('executing a script block: end');
} // executeScript
@@ -734,8 +765,8 @@
+ p.input.s.substring (p.insertionPoint, p.input.s.length);
p.insertionPoint += s.length;
- // 3. If there is a script that will execute as soon as the parser resumes
- if (p.scriptExecutedAfterParserResumes) {
+ // 3. If there is a pending external script
+ if (p.pendingExternalScript) {
log ('document.write: processed later (there is an unprocessed