--- markup/html/scripting-parser/parser.html 2008/04/27 11:27:04 1.13
+++ markup/html/scripting-parser/parser.html 2008/04/29 03:29:41 1.15
@@ -65,9 +65,11 @@
var logIndentLevel = 0;
function log (s) {
+ var indent = '';
for (var i = 0; i < logIndentLevel; i++) {
- s = ' ' + s;
+ indent += ' ';
}
+ s = indent + s.replace (/\n/g, "\n" + indent);
document.logElement.appendChild (document.createTextNode (s + "\n"));
} // log
@@ -92,7 +94,8 @@
Parser.prototype.getNextToken = function () {
var p = this;
var i = this.input;
- if (this.parseMode == 'script') {
+ if (this.parseMode == 'cdata') {
+ var tagName = this.endTagName;
var token;
if (p.insertionPoint <= 0) {
return {type: 'abort'};
@@ -110,21 +113,22 @@
return '';
});
if (token) return token;
- i.s = i.s.replace (/^<\/[Ss][Cc][Rr][Ii][Pp][Tt]>/, function (s) {
+ var pattern = new RegExp ('^' + tagName + '>', 'i');
+ i.s = i.s.replace (pattern, function (s) {
if (p.insertionPoint < s.length) {
token = {type: 'abort'};
return s;
}
- token = {type: 'end-tag', value: 'script'};
+ token = {type: 'end-tag', value: tagName};
p.insertionPoint -= s.length;
return '';
});
if (token) return token;
var m;
- if ((p.insertionPoint < '');
@@ -313,6 +318,51 @@
//
}
}
+ } else if (token.value == 'style' ||
+ token.value == 'noscript' ||
+ token.value == 'xmp') {
+ // 1. Create an element for the token in the HTML namespace.
+ var el = new JSElement (this.doc, token.value);
+
+ // 2. Append the new element to the current node.
+ this.openElements[this.openElements.length - 1].appendChild (el);
+
+ // 3. Switch the tokeniser's content model flag to the CDATA state.
+ this.parseMode = 'cdata';
+ this.endTagName = token.value;
+
+ // 4.1. Collect all the character tokens.
+ while (true) {
+ var token = this.getNextToken ();
+ log ('token: ' + token.type + ' "' + token.value + '"');
+
+ if (token.type == 'char') {
+ // 5. Append a single Text node to the script element node.
+ el.manakaiAppendText (token.value);
+
+ // 4.2. Until it returns a token that is not a character token, or
+ // until it stops tokenising.
+ } else if (token.type == 'eof' ||
+ token.type == 'end-tag' ||
+ token.type == 'abort') {
+ // 6. Switched back to the PCDATA state.
+ this.parseMode = 'pcdata';
+
+ // 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 + '>');
+
+ // 7.3. Mark the script element as "already executed".
+ el.manakaiAlreadyExecuted = true;
+ } else {
+ // 7.4. Ignore it.
+ //
+ }
+ break;
+ }
+ }
} else {
var el = new JSElement (this.doc, token.value);
this.openElements[this.openElements.length - 1].appendChild (el);
@@ -397,7 +447,7 @@
log ('DOMContentLoaded event fired');
- // "delays tha load event" things has completed:
+ // "delays the load event" things has completed:
// readyState = 'complete'
log ('load event fired');
@@ -453,7 +503,7 @@
// 2.4. If the script element has its "already executed" flag set
if (e.manakaiAlreadyExecuted) {
// 2.5. Abort these steps at this point.
- log ('Running a script: aborted');
+ log ('Running a script: aborted (already executed)');
logIndentLevel--;
return e;
}
@@ -564,11 +614,22 @@
doc.write.apply (doc, args);
return '';
});
- s = s.replace (/^\s*var\s+s\s*=\s*document\.createElement\s*\(\s*['"]script['"]\s*\)\s*;\s*s\.src\s*=\s*(?:'(javascript:[^']*)'|"(javascript:[^"]*)")\s*;\s*document\.documentElement\.appendChild\s*\(\s*s\s*\)\s*;\s*/,
+ var noDocumentElement = false;
+ s = s.replace (/^\s*var\s+s\s*=\s*document\.createElement\s*\(\s*['"]script['"]\s*\)\s*;\s*s\.src\s*=\s*(?:'([^']*)'|"([^"]*)")\s*;\s*document\.documentElement\.appendChild\s*\(\s*s\s*\)\s*;\s*/,
function (s, t, u) {
matched = true;
var args = [unescapeJSLiteral (t ? t : u)];
- doc._insertExternalScript.apply (doc, args);
+ noDocumentElement = !doc._insertExternalScript.apply (doc, args);
+ return '';
+ });
+ if (noDocumentElement) {
+ log ('Script error: documentElement is null');
+ break;
+ }
+ s = s.replace (/^\s*w\s*\(\s*document\.documentElement\.innerHTML\s*\)\s*;\s*/,
+ function (s, t) {
+ matched = true;
+ log (dumpTree (doc, ''));
return '';
});
if (s == '') break;
@@ -653,6 +714,7 @@
}; // document.open
JSDocument.prototype.write = function () {
+ log ('document.write: start');
logIndentLevel++;
var p = this._parser;
@@ -676,6 +738,7 @@
if (p.scriptExecutedAfterParserResumes) {
log ('document.write: processed later (there is an unprocessed