/[suikacvs]/markup/html/scripting-parser/parser.html
Suika

Diff of /markup/html/scripting-parser/parser.html

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by wakaba, Tue Apr 29 03:29:41 2008 UTC revision 1.19 by wakaba, Sun Aug 31 09:50:49 2008 UTC
# Line 83  Line 83 
83        doc = new JSDocument (this);        doc = new JSDocument (this);
84        doc.manakaiIsHTML = true;        doc.manakaiIsHTML = true;
85      }      }
86        this.nextToken = [];
87      this.doc = doc;      this.doc = doc;
88      this.openElements = [doc];      this.openElements = [doc];
89      this.input = i;      this.input = i;
# Line 92  Line 93 
93    } // Parser    } // Parser
94    
95    Parser.prototype.getNextToken = function () {    Parser.prototype.getNextToken = function () {
96        if (this.nextToken.length) {
97          return this.nextToken.shift ();
98        }
99    
100      var p = this;      var p = this;
101      var i = this.input;      var i = this.input;
102      if (this.parseMode == 'cdata') {      if (this.parseMode == 'cdata') {
# Line 146  Line 151 
151      i.s = i.s.replace (/^<\/([^>]+)(?:>|$)/, function (s, e) {      i.s = i.s.replace (/^<\/([^>]+)(?:>|$)/, function (s, e) {
152        if (p.insertionPoint < s.length ||        if (p.insertionPoint < s.length ||
153            (p.insertionPoint <= s.length &&            (p.insertionPoint <= s.length &&
154             s.substring (s.length - 1, 1) != '>')) {             s.substring (s.length - 1, s.length) != '>')) {
155          token = {type: 'abort'};          token = {type: 'abort'};
156          return s;          return s;
157        }        }
# Line 158  Line 163 
163      i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) {      i.s = i.s.replace (/^<([^>]+)(?:>|$)/, function (s, e) {
164        if (p.insertionPoint < s.length ||        if (p.insertionPoint < s.length ||
165            (p.insertionPoint <= s.length &&            (p.insertionPoint <= s.length &&
166             s.substring (s.length - 1, 1) != '>')) {             s.substring (s.length - 1, s.length) != '>')) {
167          token = {type: 'abort'};          token = {type: 'abort'};
168          return s;          return s;
169        }        }
# Line 221  Line 226 
226        var token = this.getNextToken ();        var token = this.getNextToken ();
227        log ('token: ' + token.type + ' "' + token.value + '"');        log ('token: ' + token.type + ' "' + token.value + '"');
228    
229          if (this.cdataEndTagRequired) {
230            // Generic CDATA parsing algorithm
231    
232            if (token.type != 'abort') {
233              // 7.
234              if (token.type == 'end-tag' && token.value == this.endTagName) {
235                // 7.1. Ignores it.
236                //
237              } else {
238                // 7.2. Parse error.
239                log ('Parse error: no </' + this.endTagName + '>');
240                this.nextToken.unshift (token);
241              }
242              this.cdataEndTagRequired = false;
243              continue;
244            }
245          }
246    
247        if (token.type == 'start-tag') {        if (token.type == 'start-tag') {
248          if (token.value == 'script') {          if (token.value == 'script') {
249            // 1. Create an element for the token in the HTML namespace.            // 1. Create an element for the token in the HTML namespace.
# Line 257  Line 280 
280                if (!(token.type == 'end-tag' && token.value == 'script')) {                if (!(token.type == 'end-tag' && token.value == 'script')) {
281                  // 7.2. This is a parse error.                  // 7.2. This is a parse error.
282                  log ('Parse error: no </' + 'script>');                  log ('Parse error: no </' + 'script>');
283                    this.nextToken.unshift (token);
284    
285                  // 7.3. Mark the script element as "already executed".                  // 7.3. Mark the script element as "already executed".
286                  el.manakaiAlreadyExecuted = true;                  el.manakaiAlreadyExecuted = true;
# Line 288  Line 312 
312            oldInsertionPoint += this.insertionPoint;            oldInsertionPoint += this.insertionPoint;
313            this.setInsertionPoint (oldInsertionPoint);            this.setInsertionPoint (oldInsertionPoint);
314    
315            // 12. If there is a script that will execute as soon as ...            // 12. If there is a pending external script
316            while (this.scriptExecutedWhenParserResumes) {            while (this.pendingExternalScript) {
317              // 12.1. If the tree construction stage is being called reentrantly              // 12.1. If the tree construction stage is being called reentrantly
318              if (this.reentrant) {              if (this.reentrant) {
319                log ('parse: abort (reentrance)');                log ('parse: abort (reentrance)');
# Line 299  Line 323 
323              // 12.2. Otherwise              // 12.2. Otherwise
324              } else {              } else {
325                // 1.                // 1.
326                var script = this.scriptExecutedWhenParserResumes;                var script = this.pendingExternalScript;
327                this.scriptExecutedWhenParserResumes = null;                this.pendingExternalScript = null;
328    
329                // 2. Pause until the script has completed loading.                // 2. Pause until the script has completed loading.
330                //                //
# Line 348  Line 372 
372                // 6. Switched back to the PCDATA state.                // 6. Switched back to the PCDATA state.
373                this.parseMode = 'pcdata';                this.parseMode = 'pcdata';
374    
375                  if (token.type == 'abort') {
376                    this.cdataEndTagRequired = true;
377                    break;
378                  }
379    
380                // 7.1. If the next token is not an end tag token with ...                // 7.1. If the next token is not an end tag token with ...
381                if (!(token.type == 'end-tag' &&                if (!(token.type == 'end-tag' &&
382                      token.value == this.endTagName)) {                      token.value == this.endTagName)) {
383                  // 7.2. This is a parse error.                  // 7.2. This is a parse error.
384                  log ('Parse error: no </' + this.endTagName + '>');                  log ('Parse error: no </' + this.endTagName + '>');
385                    this.nextToken.unshift (token);
386    
387                  // 7.3. Mark the script element as "already executed".                  // 7.3. Mark the script element as "already executed".
388                  el.manakaiAlreadyExecuted = true;                  el.manakaiAlreadyExecuted = true;
# Line 530  Line 560 
560          log ('Running a script: aborted (async)');          log ('Running a script: aborted (async)');
561          // ISSUE: What is the difference with the case above?          // ISSUE: What is the difference with the case above?
562        } else if (e.src != null && e.manakaiParserInserted) {        } else if (e.src != null && e.manakaiParserInserted) {
563          if (p.scriptExecutedWhenParserResumes) {          if (p.pendingExternalScript) {
564            log ('Error: There is a script that will execute as soon as the parser resumes.');            log ('Error: There is a pending external script.');
565          }          }
566          p.scriptExecutedWhenParserResumes = e;          p.pendingExternalScript = e;
567          log ('Running a script: aborted (src parser-inserted)');          log ('Running a script: aborted (src parser-inserted)');
568        } else if (e.src != null) {        } else if (e.src != null) {
569          p.scriptsExecutedSoon.push (e);          p.scriptsExecutedSoon.push (e);
# Line 568  Line 598 
598      }      }
599    
600      // If the load was successful      // If the load was successful
     log ('load event fired at the script element');  
601    
602      if (true) {      if (true) {
603      // Scripting is enabled, Document.designMode is disabled,      // Scripting is enabled, Document.designMode is disabled,
# Line 577  Line 606 
606        parseAndRunScript (doc, s);        parseAndRunScript (doc, s);
607      }      }
608    
609        log ('load event fired at the script element');
610    
611      log ('executing a script block: end');      log ('executing a script block: end');
612    } // executeScript    } // executeScript
613    
# Line 734  Line 765 
765          + p.input.s.substring (p.insertionPoint, p.input.s.length);          + p.input.s.substring (p.insertionPoint, p.input.s.length);
766      p.insertionPoint += s.length;      p.insertionPoint += s.length;
767    
768      // 3. If there is a script that will execute as soon as the parser resumes      // 3. If there is a pending external script
769      if (p.scriptExecutedAfterParserResumes) {      if (p.pendingExternalScript) {
770        log ('document.write: processed later (there is an unprocessed <script src>)');        log ('document.write: processed later (there is an unprocessed <script src>)');
771        logIndentLevel--;        logIndentLevel--;
772        log ('document.write: return');        log ('document.write: return');
# Line 866  algorithm.  Especially, this parser: Line 897  algorithm.  Especially, this parser:
897  algorithm, and so on.  algorithm, and so on.
898  <li>Does not raise parse errors for invalid attribute specifications in start  <li>Does not raise parse errors for invalid attribute specifications in start
899  or end tags.  or end tags.
900  <li>Does not support PCDATA elements (<code>title</code> and  <li>Does not support RCDATA elements (<code>title</code> and
901  <code>textarea</code>).  <code>textarea</code>).
902  <li>Does not strip the first newline in <code>pre</code> elements.  <li>Does not strip the first newline in <code>pre</code>,
903    <code>listing</code>, and <code>textarea</code> elements.
904  <li>Does not support <code>&lt;!--</code>..<code>--></code> parsing rule  <li>Does not support <code>&lt;!--</code>..<code>--></code> parsing rule
905  in <code>script</code> element.  in CDATA/RCDATA elements.
906  <li>Does not support foreign (SVG or MathML) elements.  <li>Does not support foreign (SVG or MathML) elements.
907  <li>Only supports <code>script</code> <code>type</code>  <li>Only supports <code>script</code> <code>type</code>
908  <code>text/javascript</code>.  <code>type</code> and <code>language</code>  <code>text/javascript</code>.  <code>type</code> and <code>language</code>
# Line 912  when it is inserted into the document, n Line 944  when it is inserted into the document, n
944  executed.  Currently it does not matter, since we don't allow dynamic  executed.  Currently it does not matter, since we don't allow dynamic
945  modification to the |src| content/DOM attribute value yet. -->  modification to the |src| content/DOM attribute value yet. -->
946    
947    <p>See also
948    <a href="http://suika.fam.cx/gate/2005/sw/Live%20Scripting%20HTML%20Parser">SuikaWiki:
949    Live Scripting HTML Parser</a>.
950    
951  </body>  </body>
952  </html>  </html>
953  <!-- $Date$ -->  <!-- $Date$ -->

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.19

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24