Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: lib/parser.dart

Issue 11260039: Advance html5lib to newest breaking changes in core: getKeys -> keys, etc (Closed) Base URL: git@github.com:dart-lang/html5lib.git@master
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/dom.dart ('k') | lib/src/inputstream.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * This library has a parser for HTML5 documents, that lets you parse HTML 2 * This library has a parser for HTML5 documents, that lets you parse HTML
3 * easily from a script or server side application: 3 * easily from a script or server side application:
4 * 4 *
5 * import 'package:html5lib/parser.dart' show parse; 5 * import 'package:html5lib/parser.dart' show parse;
6 * import 'package:html5lib/dom.dart'; 6 * import 'package:html5lib/dom.dart';
7 * main() { 7 * main() {
8 * var document = parse( 8 * var document = parse(
9 * '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); 9 * '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!');
10 * print(document.outerHTML); 10 * print(document.outerHTML);
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 } 265 }
266 266
267 bool isMathMLTextIntegrationPoint(Node element) { 267 bool isMathMLTextIntegrationPoint(Node element) {
268 return mathmlTextIntegrationPointElements.contains( 268 return mathmlTextIntegrationPointElements.contains(
269 new Pair(element.namespace, element.tagName)); 269 new Pair(element.namespace, element.tagName));
270 } 270 }
271 271
272 bool inForeignContent(Token token, int type) { 272 bool inForeignContent(Token token, int type) {
273 if (tree.openElements.length == 0) return false; 273 if (tree.openElements.length == 0) return false;
274 274
275 var node = tree.openElements.last(); 275 var node = tree.openElements.last;
276 if (node.namespace == tree.defaultNamespace) return false; 276 if (node.namespace == tree.defaultNamespace) return false;
277 277
278 if (isMathMLTextIntegrationPoint(node)) { 278 if (isMathMLTextIntegrationPoint(node)) {
279 if (type == TokenKind.startTag && 279 if (type == TokenKind.startTag &&
280 (token as StartTagToken).name != "mglyph" && 280 (token as StartTagToken).name != "mglyph" &&
281 (token as StartTagToken).name != "malignmark") { 281 (token as StartTagToken).name != "malignmark") {
282 return false; 282 return false;
283 } 283 }
284 if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { 284 if (type == TokenKind.characters || type == TokenKind.spaceCharacters) {
285 return false; 285 return false;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 "tablevalues":"tableValues", 458 "tablevalues":"tableValues",
459 "targetx":"targetX", 459 "targetx":"targetX",
460 "targety":"targetY", 460 "targety":"targetY",
461 "textlength":"textLength", 461 "textlength":"textLength",
462 "viewbox":"viewBox", 462 "viewbox":"viewBox",
463 "viewtarget":"viewTarget", 463 "viewtarget":"viewTarget",
464 "xchannelselector":"xChannelSelector", 464 "xchannelselector":"xChannelSelector",
465 "ychannelselector":"yChannelSelector", 465 "ychannelselector":"yChannelSelector",
466 "zoomandpan":"zoomAndPan" 466 "zoomandpan":"zoomAndPan"
467 }; 467 };
468 for (var originalName in token.data.getKeys()) { 468 for (var originalName in token.data.keys) {
469 var svgName = replacements[originalName]; 469 var svgName = replacements[originalName];
470 if (svgName != null) { 470 if (svgName != null) {
471 token.data[svgName] = token.data.remove(originalName); 471 token.data[svgName] = token.data.remove(originalName);
472 } 472 }
473 } 473 }
474 } 474 }
475 475
476 void adjustForeignAttributes(Token token) { 476 void adjustForeignAttributes(Token token) {
477 // TODO(jmesserly): I don't like mixing non-string objects with strings in 477 // TODO(jmesserly): I don't like mixing non-string objects with strings in
478 // the Node.attributes Map. Is there another solution? 478 // the Node.attributes Map. Is there another solution?
479 final replacements = const { 479 final replacements = const {
480 "xlink:actuate": const AttributeName("xlink", "actuate", 480 "xlink:actuate": const AttributeName("xlink", "actuate",
481 Namespaces.xlink), 481 Namespaces.xlink),
482 "xlink:arcrole": const AttributeName("xlink", "arcrole", 482 "xlink:arcrole": const AttributeName("xlink", "arcrole",
483 Namespaces.xlink), 483 Namespaces.xlink),
484 "xlink:href": const AttributeName("xlink", "href", Namespaces.xlink), 484 "xlink:href": const AttributeName("xlink", "href", Namespaces.xlink),
485 "xlink:role": const AttributeName("xlink", "role", Namespaces.xlink), 485 "xlink:role": const AttributeName("xlink", "role", Namespaces.xlink),
486 "xlink:show": const AttributeName("xlink", "show", Namespaces.xlink), 486 "xlink:show": const AttributeName("xlink", "show", Namespaces.xlink),
487 "xlink:title": const AttributeName("xlink", "title", Namespaces.xlink), 487 "xlink:title": const AttributeName("xlink", "title", Namespaces.xlink),
488 "xlink:type": const AttributeName("xlink", "type", Namespaces.xlink), 488 "xlink:type": const AttributeName("xlink", "type", Namespaces.xlink),
489 "xml:base": const AttributeName("xml", "base", Namespaces.xml), 489 "xml:base": const AttributeName("xml", "base", Namespaces.xml),
490 "xml:lang": const AttributeName("xml", "lang", Namespaces.xml), 490 "xml:lang": const AttributeName("xml", "lang", Namespaces.xml),
491 "xml:space": const AttributeName("xml", "space", Namespaces.xml), 491 "xml:space": const AttributeName("xml", "space", Namespaces.xml),
492 "xmlns": const AttributeName(null, "xmlns", Namespaces.xmlns), 492 "xmlns": const AttributeName(null, "xmlns", Namespaces.xmlns),
493 "xmlns:xlink": const AttributeName("xmlns", "xlink", Namespaces.xmlns) 493 "xmlns:xlink": const AttributeName("xmlns", "xlink", Namespaces.xmlns)
494 }; 494 };
495 495
496 for (var originalName in token.data.getKeys()) { 496 for (var originalName in token.data.keys) {
497 var foreignName = replacements[originalName]; 497 var foreignName = replacements[originalName];
498 if (foreignName != null) { 498 if (foreignName != null) {
499 token.data[foreignName] = token.data.remove(originalName); 499 token.data[foreignName] = token.data.remove(originalName);
500 } 500 }
501 } 501 }
502 } 502 }
503 503
504 void resetInsertionMode() { 504 void resetInsertionMode() {
505 // The name of this method is mostly historical. (It's also used in the 505 // The name of this method is mostly historical. (It's also used in the
506 // specification.) 506 // specification.)
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 581
582 Phase(HtmlParser parser) : parser = parser, tree = parser.tree; 582 Phase(HtmlParser parser) : parser = parser, tree = parser.tree;
583 583
584 bool processEOF() { 584 bool processEOF() {
585 throw const NotImplementedException(); 585 throw const NotImplementedException();
586 } 586 }
587 587
588 Token processComment(CommentToken token) { 588 Token processComment(CommentToken token) {
589 // For most phases the following is correct. Where it's not it will be 589 // For most phases the following is correct. Where it's not it will be
590 // overridden. 590 // overridden.
591 tree.insertComment(token, tree.openElements.last()); 591 tree.insertComment(token, tree.openElements.last);
592 } 592 }
593 593
594 Token processDoctype(DoctypeToken token) { 594 Token processDoctype(DoctypeToken token) {
595 parser.parseError(token.span, "unexpected-doctype"); 595 parser.parseError(token.span, "unexpected-doctype");
596 } 596 }
597 597
598 Token processCharacters(CharactersToken token) { 598 Token processCharacters(CharactersToken token) {
599 tree.insertText(token.data, token.span); 599 tree.insertText(token.data, token.span);
600 } 600 }
601 601
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 startTagHead(new StartTagToken("head", data: {})); 855 startTagHead(new StartTagToken("head", data: {}));
856 return token; 856 return token;
857 } 857 }
858 858
859 Token startTagHtml(StartTagToken token) { 859 Token startTagHtml(StartTagToken token) {
860 return parser._inBodyPhase.processStartTag(token); 860 return parser._inBodyPhase.processStartTag(token);
861 } 861 }
862 862
863 void startTagHead(StartTagToken token) { 863 void startTagHead(StartTagToken token) {
864 tree.insertElement(token); 864 tree.insertElement(token);
865 tree.headPointer = tree.openElements.last(); 865 tree.headPointer = tree.openElements.last;
866 parser.phase = parser._inHeadPhase; 866 parser.phase = parser._inHeadPhase;
867 } 867 }
868 868
869 Token startTagOther(StartTagToken token) { 869 Token startTagOther(StartTagToken token) {
870 startTagHead(new StartTagToken("head", data: {})); 870 startTagHead(new StartTagToken("head", data: {}));
871 return token; 871 return token;
872 } 872 }
873 873
874 Token endTagImplyHead(EndTagToken token) { 874 Token endTagImplyHead(EndTagToken token) {
875 startTagHead(new StartTagToken("head", data: {})); 875 startTagHead(new StartTagToken("head", data: {}));
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 default: return endTagOther(token); 1199 default: return endTagOther(token);
1200 } 1200 }
1201 } 1201 }
1202 1202
1203 bool isMatchingFormattingElement(Node node1, Node node2) { 1203 bool isMatchingFormattingElement(Node node1, Node node2) {
1204 if (node1.tagName != node2.tagName || node1.namespace != node2.namespace) { 1204 if (node1.tagName != node2.tagName || node1.namespace != node2.namespace) {
1205 return false; 1205 return false;
1206 } else if (node1.attributes.length != node2.attributes.length) { 1206 } else if (node1.attributes.length != node2.attributes.length) {
1207 return false; 1207 return false;
1208 } else { 1208 } else {
1209 for (var key in node1.attributes.getKeys()) { 1209 for (var key in node1.attributes.keys) {
1210 if (node1.attributes[key] != node2.attributes[key]) { 1210 if (node1.attributes[key] != node2.attributes[key]) {
1211 return false; 1211 return false;
1212 } 1212 }
1213 } 1213 }
1214 } 1214 }
1215 return true; 1215 return true;
1216 } 1216 }
1217 1217
1218 // helper 1218 // helper
1219 void addFormattingElement(token) { 1219 void addFormattingElement(token) {
1220 tree.insertElement(token); 1220 tree.insertElement(token);
1221 var element = tree.openElements.last(); 1221 var element = tree.openElements.last;
1222 1222
1223 var matchingElements = []; 1223 var matchingElements = [];
1224 for (Node node in reversed(tree.activeFormattingElements)) { 1224 for (Node node in reversed(tree.activeFormattingElements)) {
1225 if (node === Marker) { 1225 if (node === Marker) {
1226 break; 1226 break;
1227 } else if (isMatchingFormattingElement(node, element)) { 1227 } else if (isMatchingFormattingElement(node, element)) {
1228 matchingElements.add(node); 1228 matchingElements.add(node);
1229 } 1229 }
1230 } 1230 }
1231 1231
1232 assert(matchingElements.length <= 3); 1232 assert(matchingElements.length <= 3);
1233 if (matchingElements.length == 3) { 1233 if (matchingElements.length == 3) {
1234 tree.activeFormattingElements.remove(matchingElements.last()); 1234 tree.activeFormattingElements.remove(matchingElements.last);
1235 } 1235 }
1236 tree.activeFormattingElements.add(element); 1236 tree.activeFormattingElements.add(element);
1237 } 1237 }
1238 1238
1239 // the real deal 1239 // the real deal
1240 bool processEOF() { 1240 bool processEOF() {
1241 for (Node node in reversed(tree.openElements)) { 1241 for (Node node in reversed(tree.openElements)) {
1242 switch (node.tagName) { 1242 switch (node.tagName) {
1243 case "dd": case "dt": case "li": case "p": case "tbody": case "td": 1243 case "dd": case "dt": case "li": case "p": case "tbody": case "td":
1244 case "tfoot": case "th": case "thead": case "tr": case "body": 1244 case "tfoot": case "th": case "thead": case "tr": case "body":
1245 case "html": 1245 case "html":
1246 continue; 1246 continue;
1247 } 1247 }
1248 parser.parseError(node.span, "expected-closing-tag-but-got-eof"); 1248 parser.parseError(node.span, "expected-closing-tag-but-got-eof");
1249 break; 1249 break;
1250 } 1250 }
1251 //Stop parsing 1251 //Stop parsing
1252 return false; 1252 return false;
1253 } 1253 }
1254 1254
1255 void processSpaceCharactersDropNewline(Token token) { 1255 void processSpaceCharactersDropNewline(Token token) {
1256 // Sometimes (start of <pre>, <listing>, and <textarea> blocks) we 1256 // Sometimes (start of <pre>, <listing>, and <textarea> blocks) we
1257 // want to drop leading newlines 1257 // want to drop leading newlines
1258 var data = token.data; 1258 var data = token.data;
1259 dropNewline = false; 1259 dropNewline = false;
1260 if (data.startsWith("\n")) { 1260 if (data.startsWith("\n")) {
1261 var lastOpen = tree.openElements.last(); 1261 var lastOpen = tree.openElements.last;
1262 if (const ["pre", "listing", "textarea"].contains(lastOpen.tagName) 1262 if (const ["pre", "listing", "textarea"].contains(lastOpen.tagName)
1263 && !lastOpen.hasContent()) { 1263 && !lastOpen.hasContent()) {
1264 data = data.substring(1); 1264 data = data.substring(1);
1265 } 1265 }
1266 } 1266 }
1267 if (data.length > 0) { 1267 if (data.length > 0) {
1268 tree.reconstructActiveFormattingElements(); 1268 tree.reconstructActiveFormattingElements();
1269 tree.insertText(data, token.span); 1269 tree.insertText(data, token.span);
1270 } 1270 }
1271 } 1271 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 1312
1313 void startTagFrameset(StartTagToken token) { 1313 void startTagFrameset(StartTagToken token) {
1314 parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"}); 1314 parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"});
1315 if ((tree.openElements.length == 1 || 1315 if ((tree.openElements.length == 1 ||
1316 tree.openElements[1].tagName != "body")) { 1316 tree.openElements[1].tagName != "body")) {
1317 assert(parser.innerHTMLMode); 1317 assert(parser.innerHTMLMode);
1318 } else if (parser.framesetOK) { 1318 } else if (parser.framesetOK) {
1319 if (tree.openElements[1].parent != null) { 1319 if (tree.openElements[1].parent != null) {
1320 tree.openElements[1].parent.nodes.remove(tree.openElements[1]); 1320 tree.openElements[1].parent.nodes.remove(tree.openElements[1]);
1321 } 1321 }
1322 while (tree.openElements.last().tagName != "html") { 1322 while (tree.openElements.last.tagName != "html") {
1323 tree.openElements.removeLast(); 1323 tree.openElements.removeLast();
1324 } 1324 }
1325 tree.insertElement(token); 1325 tree.insertElement(token);
1326 parser.phase = parser._inFramesetPhase; 1326 parser.phase = parser._inFramesetPhase;
1327 } 1327 }
1328 } 1328 }
1329 1329
1330 void startTagCloseP(StartTagToken token) { 1330 void startTagCloseP(StartTagToken token) {
1331 if (tree.elementInScope("p", variant: "button")) { 1331 if (tree.elementInScope("p", variant: "button")) {
1332 endTagP(new EndTagToken("p", data: {})); 1332 endTagP(new EndTagToken("p", data: {}));
(...skipping 11 matching lines...) Expand all
1344 } 1344 }
1345 1345
1346 void startTagForm(StartTagToken token) { 1346 void startTagForm(StartTagToken token) {
1347 if (tree.formPointer != null) { 1347 if (tree.formPointer != null) {
1348 parser.parseError(token.span, "unexpected-start-tag", {"name": "form"}); 1348 parser.parseError(token.span, "unexpected-start-tag", {"name": "form"});
1349 } else { 1349 } else {
1350 if (tree.elementInScope("p", variant: "button")) { 1350 if (tree.elementInScope("p", variant: "button")) {
1351 endTagP(new EndTagToken("p", data: {})); 1351 endTagP(new EndTagToken("p", data: {}));
1352 } 1352 }
1353 tree.insertElement(token); 1353 tree.insertElement(token);
1354 tree.formPointer = tree.openElements.last(); 1354 tree.formPointer = tree.openElements.last;
1355 } 1355 }
1356 } 1356 }
1357 1357
1358 void startTagListItem(StartTagToken token) { 1358 void startTagListItem(StartTagToken token) {
1359 parser.framesetOK = false; 1359 parser.framesetOK = false;
1360 1360
1361 final stopNamesMap = const {"li": const ["li"], 1361 final stopNamesMap = const {"li": const ["li"],
1362 "dt": const ["dt", "dd"], 1362 "dt": const ["dt", "dd"],
1363 "dd": const ["dt", "dd"]}; 1363 "dd": const ["dt", "dd"]};
1364 var stopNames = stopNamesMap[token.name]; 1364 var stopNames = stopNamesMap[token.name];
(...skipping 20 matching lines...) Expand all
1385 endTagP(new EndTagToken("p", data: {})); 1385 endTagP(new EndTagToken("p", data: {}));
1386 } 1386 }
1387 tree.insertElement(token); 1387 tree.insertElement(token);
1388 parser.tokenizer.state = parser.tokenizer.plaintextState; 1388 parser.tokenizer.state = parser.tokenizer.plaintextState;
1389 } 1389 }
1390 1390
1391 void startTagHeading(StartTagToken token) { 1391 void startTagHeading(StartTagToken token) {
1392 if (tree.elementInScope("p", variant: "button")) { 1392 if (tree.elementInScope("p", variant: "button")) {
1393 endTagP(new EndTagToken("p", data: {})); 1393 endTagP(new EndTagToken("p", data: {}));
1394 } 1394 }
1395 if (headingElements.contains(tree.openElements.last().tagName)) { 1395 if (headingElements.contains(tree.openElements.last.tagName)) {
1396 parser.parseError(token.span, "unexpected-start-tag", 1396 parser.parseError(token.span, "unexpected-start-tag",
1397 {"name": token.name}); 1397 {"name": token.name});
1398 tree.openElements.removeLast(); 1398 tree.openElements.removeLast();
1399 } 1399 }
1400 tree.insertElement(token); 1400 tree.insertElement(token);
1401 } 1401 }
1402 1402
1403 void startTagA(StartTagToken token) { 1403 void startTagA(StartTagToken token) {
1404 var afeAElement = tree.elementInActiveFormattingElements("a"); 1404 var afeAElement = tree.elementInActiveFormattingElements("a");
1405 if (afeAElement != null) { 1405 if (afeAElement != null) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1552 parser.framesetOK = false; 1552 parser.framesetOK = false;
1553 startTagRawtext(token); 1553 startTagRawtext(token);
1554 } 1554 }
1555 1555
1556 /** iframe, noembed noframes, noscript(if scripting enabled). */ 1556 /** iframe, noembed noframes, noscript(if scripting enabled). */
1557 void startTagRawtext(StartTagToken token) { 1557 void startTagRawtext(StartTagToken token) {
1558 parser.parseRCDataRawtext(token, "RAWTEXT"); 1558 parser.parseRCDataRawtext(token, "RAWTEXT");
1559 } 1559 }
1560 1560
1561 void startTagOpt(StartTagToken token) { 1561 void startTagOpt(StartTagToken token) {
1562 if (tree.openElements.last().tagName == "option") { 1562 if (tree.openElements.last.tagName == "option") {
1563 parser.phase.processEndTag(new EndTagToken("option", data: {})); 1563 parser.phase.processEndTag(new EndTagToken("option", data: {}));
1564 } 1564 }
1565 tree.reconstructActiveFormattingElements(); 1565 tree.reconstructActiveFormattingElements();
1566 parser.tree.insertElement(token); 1566 parser.tree.insertElement(token);
1567 } 1567 }
1568 1568
1569 void startTagSelect(StartTagToken token) { 1569 void startTagSelect(StartTagToken token) {
1570 tree.reconstructActiveFormattingElements(); 1570 tree.reconstructActiveFormattingElements();
1571 tree.insertElement(token); 1571 tree.insertElement(token);
1572 parser.framesetOK = false; 1572 parser.framesetOK = false;
1573 1573
1574 if (parser._inTablePhase == parser.phase || 1574 if (parser._inTablePhase == parser.phase ||
1575 parser._inCaptionPhase == parser.phase || 1575 parser._inCaptionPhase == parser.phase ||
1576 parser._inColumnGroupPhase == parser.phase || 1576 parser._inColumnGroupPhase == parser.phase ||
1577 parser._inTableBodyPhase == parser.phase || 1577 parser._inTableBodyPhase == parser.phase ||
1578 parser._inRowPhase == parser.phase || 1578 parser._inRowPhase == parser.phase ||
1579 parser._inCellPhase == parser.phase) { 1579 parser._inCellPhase == parser.phase) {
1580 parser.phase = parser._inSelectInTablePhase; 1580 parser.phase = parser._inSelectInTablePhase;
1581 } else { 1581 } else {
1582 parser.phase = parser._inSelectPhase; 1582 parser.phase = parser._inSelectPhase;
1583 } 1583 }
1584 } 1584 }
1585 1585
1586 void startTagRpRt(StartTagToken token) { 1586 void startTagRpRt(StartTagToken token) {
1587 if (tree.elementInScope("ruby")) { 1587 if (tree.elementInScope("ruby")) {
1588 tree.generateImpliedEndTags(); 1588 tree.generateImpliedEndTags();
1589 var last = tree.openElements.last(); 1589 var last = tree.openElements.last;
1590 if (last.tagName != "ruby") { 1590 if (last.tagName != "ruby") {
1591 parser.parseError(last.span, 'undefined-error'); 1591 parser.parseError(last.span, 'undefined-error');
1592 } 1592 }
1593 } 1593 }
1594 tree.insertElement(token); 1594 tree.insertElement(token);
1595 } 1595 }
1596 1596
1597 void startTagMath(StartTagToken token) { 1597 void startTagMath(StartTagToken token) {
1598 tree.reconstructActiveFormattingElements(); 1598 tree.reconstructActiveFormattingElements();
1599 parser.adjustMathMLAttributes(token); 1599 parser.adjustMathMLAttributes(token);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 tree.insertElement(token); 1639 tree.insertElement(token);
1640 } 1640 }
1641 1641
1642 void endTagP(EndTagToken token) { 1642 void endTagP(EndTagToken token) {
1643 if (!tree.elementInScope("p", variant: "button")) { 1643 if (!tree.elementInScope("p", variant: "button")) {
1644 startTagCloseP(new StartTagToken("p", data: {})); 1644 startTagCloseP(new StartTagToken("p", data: {}));
1645 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); 1645 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"});
1646 endTagP(new EndTagToken("p", data: {})); 1646 endTagP(new EndTagToken("p", data: {}));
1647 } else { 1647 } else {
1648 tree.generateImpliedEndTags("p"); 1648 tree.generateImpliedEndTags("p");
1649 if (tree.openElements.last().tagName != "p") { 1649 if (tree.openElements.last.tagName != "p") {
1650 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); 1650 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"});
1651 } 1651 }
1652 popOpenElementsUntil("p"); 1652 popOpenElementsUntil("p");
1653 } 1653 }
1654 } 1654 }
1655 1655
1656 void endTagBody(EndTagToken token) { 1656 void endTagBody(EndTagToken token) {
1657 if (!tree.elementInScope("body")) { 1657 if (!tree.elementInScope("body")) {
1658 parser.parseError(token.span, 'undefined-error'); 1658 parser.parseError(token.span, 'undefined-error');
1659 return; 1659 return;
1660 } else if (tree.openElements.last().tagName != "body") { 1660 } else if (tree.openElements.last.tagName != "body") {
1661 for (Node node in slice(tree.openElements, 2)) { 1661 for (Node node in slice(tree.openElements, 2)) {
1662 switch (node.tagName) { 1662 switch (node.tagName) {
1663 case "dd": case "dt": case "li": case "optgroup": case "option": 1663 case "dd": case "dt": case "li": case "optgroup": case "option":
1664 case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": 1664 case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot":
1665 case "th": case "thead": case "tr": case "body": case "html": 1665 case "th": case "thead": case "tr": case "body": case "html":
1666 continue; 1666 continue;
1667 } 1667 }
1668 // Not sure this is the correct name for the parse error 1668 // Not sure this is the correct name for the parse error
1669 parser.parseError(token.span, "expected-one-end-tag-but-got-another", 1669 parser.parseError(token.span, "expected-one-end-tag-but-got-another",
1670 {"expectedName": "body", "gotName": node.tagName}); 1670 {"expectedName": "body", "gotName": node.tagName});
(...skipping 13 matching lines...) Expand all
1684 1684
1685 void endTagBlock(EndTagToken token) { 1685 void endTagBlock(EndTagToken token) {
1686 //Put us back in the right whitespace handling mode 1686 //Put us back in the right whitespace handling mode
1687 if (token.name == "pre") { 1687 if (token.name == "pre") {
1688 dropNewline = false; 1688 dropNewline = false;
1689 } 1689 }
1690 var inScope = tree.elementInScope(token.name); 1690 var inScope = tree.elementInScope(token.name);
1691 if (inScope) { 1691 if (inScope) {
1692 tree.generateImpliedEndTags(); 1692 tree.generateImpliedEndTags();
1693 } 1693 }
1694 if (tree.openElements.last().tagName != token.name) { 1694 if (tree.openElements.last.tagName != token.name) {
1695 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 1695 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
1696 } 1696 }
1697 if (inScope) { 1697 if (inScope) {
1698 popOpenElementsUntil(token.name); 1698 popOpenElementsUntil(token.name);
1699 } 1699 }
1700 } 1700 }
1701 1701
1702 void endTagForm(EndTagToken token) { 1702 void endTagForm(EndTagToken token) {
1703 var node = tree.formPointer; 1703 var node = tree.formPointer;
1704 tree.formPointer = null; 1704 tree.formPointer = null;
1705 if (node === null || !tree.elementInScope(node)) { 1705 if (node === null || !tree.elementInScope(node)) {
1706 parser.parseError(token.span, "unexpected-end-tag", {"name": "form"}); 1706 parser.parseError(token.span, "unexpected-end-tag", {"name": "form"});
1707 } else { 1707 } else {
1708 tree.generateImpliedEndTags(); 1708 tree.generateImpliedEndTags();
1709 if (tree.openElements.last() != node) { 1709 if (tree.openElements.last != node) {
1710 parser.parseError(token.span, "end-tag-too-early-ignored", {"name": "for m"}); 1710 parser.parseError(token.span, "end-tag-too-early-ignored", {"name": "for m"});
1711 } 1711 }
1712 tree.openElements.remove(node); 1712 tree.openElements.remove(node);
1713 } 1713 }
1714 } 1714 }
1715 1715
1716 void endTagListItem(EndTagToken token) { 1716 void endTagListItem(EndTagToken token) {
1717 var variant; 1717 var variant;
1718 if (token.name == "li") { 1718 if (token.name == "li") {
1719 variant = "list"; 1719 variant = "list";
1720 } else { 1720 } else {
1721 variant = null; 1721 variant = null;
1722 } 1722 }
1723 if (!tree.elementInScope(token.name, variant: variant)) { 1723 if (!tree.elementInScope(token.name, variant: variant)) {
1724 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 1724 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
1725 } else { 1725 } else {
1726 tree.generateImpliedEndTags(token.name); 1726 tree.generateImpliedEndTags(token.name);
1727 if (tree.openElements.last().tagName != token.name) { 1727 if (tree.openElements.last.tagName != token.name) {
1728 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}) ; 1728 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}) ;
1729 } 1729 }
1730 popOpenElementsUntil(token.name); 1730 popOpenElementsUntil(token.name);
1731 } 1731 }
1732 } 1732 }
1733 1733
1734 void endTagHeading(EndTagToken token) { 1734 void endTagHeading(EndTagToken token) {
1735 for (var item in headingElements) { 1735 for (var item in headingElements) {
1736 if (tree.elementInScope(item)) { 1736 if (tree.elementInScope(item)) {
1737 tree.generateImpliedEndTags(); 1737 tree.generateImpliedEndTags();
1738 break; 1738 break;
1739 } 1739 }
1740 } 1740 }
1741 if (tree.openElements.last().tagName != token.name) { 1741 if (tree.openElements.last.tagName != token.name) {
1742 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 1742 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
1743 } 1743 }
1744 1744
1745 for (var item in headingElements) { 1745 for (var item in headingElements) {
1746 if (tree.elementInScope(item)) { 1746 if (tree.elementInScope(item)) {
1747 item = tree.openElements.removeLast(); 1747 item = tree.openElements.removeLast();
1748 while (!headingElements.contains(item.tagName)) { 1748 while (!headingElements.contains(item.tagName)) {
1749 item = tree.openElements.removeLast(); 1749 item = tree.openElements.removeLast();
1750 } 1750 }
1751 break; 1751 break;
(...skipping 23 matching lines...) Expand all
1775 return; 1775 return;
1776 // Step 1 paragraph 2 1776 // Step 1 paragraph 2
1777 } else if (!tree.openElements.contains(formattingElement)) { 1777 } else if (!tree.openElements.contains(formattingElement)) {
1778 parser.parseError(token.span, "adoption-agency-1.2", 1778 parser.parseError(token.span, "adoption-agency-1.2",
1779 {"name": token.name}); 1779 {"name": token.name});
1780 tree.activeFormattingElements.remove(formattingElement); 1780 tree.activeFormattingElements.remove(formattingElement);
1781 return; 1781 return;
1782 } 1782 }
1783 1783
1784 // Step 1 paragraph 3 1784 // Step 1 paragraph 3
1785 if (formattingElement != tree.openElements.last()) { 1785 if (formattingElement != tree.openElements.last) {
1786 parser.parseError(token.span, "adoption-agency-1.3", 1786 parser.parseError(token.span, "adoption-agency-1.3",
1787 {"name": token.name}); 1787 {"name": token.name});
1788 } 1788 }
1789 1789
1790 // Step 2 1790 // Step 2
1791 // Start of the adoption agency algorithm proper 1791 // Start of the adoption agency algorithm proper
1792 var afeIndex = tree.openElements.indexOf(formattingElement); 1792 var afeIndex = tree.openElements.indexOf(formattingElement);
1793 Node furthestBlock = null; 1793 Node furthestBlock = null;
1794 for (Node element in slice(tree.openElements, afeIndex)) { 1794 for (Node element in slice(tree.openElements, afeIndex)) {
1795 if (specialElements.contains(element.nameTuple)) { 1795 if (specialElements.contains(element.nameTuple)) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 tree.openElements.remove(formattingElement); 1894 tree.openElements.remove(formattingElement);
1895 tree.openElements.insertRange( 1895 tree.openElements.insertRange(
1896 tree.openElements.indexOf(furthestBlock) + 1, 1, clone); 1896 tree.openElements.indexOf(furthestBlock) + 1, 1, clone);
1897 } 1897 }
1898 } 1898 }
1899 1899
1900 void endTagAppletMarqueeObject(EndTagToken token) { 1900 void endTagAppletMarqueeObject(EndTagToken token) {
1901 if (tree.elementInScope(token.name)) { 1901 if (tree.elementInScope(token.name)) {
1902 tree.generateImpliedEndTags(); 1902 tree.generateImpliedEndTags();
1903 } 1903 }
1904 if (tree.openElements.last().tagName != token.name) { 1904 if (tree.openElements.last.tagName != token.name) {
1905 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 1905 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
1906 } 1906 }
1907 if (tree.elementInScope(token.name)) { 1907 if (tree.elementInScope(token.name)) {
1908 popOpenElementsUntil(token.name); 1908 popOpenElementsUntil(token.name);
1909 tree.clearActiveFormattingElements(); 1909 tree.clearActiveFormattingElements();
1910 } 1910 }
1911 } 1911 }
1912 1912
1913 void endTagBr(EndTagToken token) { 1913 void endTagBr(EndTagToken token) {
1914 parser.parseError(token.span, "unexpected-end-tag-treated-as", 1914 parser.parseError(token.span, "unexpected-end-tag-treated-as",
1915 {"originalName": "br", "newName": "br element"}); 1915 {"originalName": "br", "newName": "br element"});
1916 tree.reconstructActiveFormattingElements(); 1916 tree.reconstructActiveFormattingElements();
1917 tree.insertElement(new StartTagToken("br", data: {})); 1917 tree.insertElement(new StartTagToken("br", data: {}));
1918 tree.openElements.removeLast(); 1918 tree.openElements.removeLast();
1919 } 1919 }
1920 1920
1921 void endTagOther(EndTagToken token) { 1921 void endTagOther(EndTagToken token) {
1922 for (Node node in reversed(tree.openElements)) { 1922 for (Node node in reversed(tree.openElements)) {
1923 if (node.tagName == token.name) { 1923 if (node.tagName == token.name) {
1924 tree.generateImpliedEndTags(token.name); 1924 tree.generateImpliedEndTags(token.name);
1925 if (tree.openElements.last().tagName != token.name) { 1925 if (tree.openElements.last.tagName != token.name) {
1926 parser.parseError(token.span, "unexpected-end-tag", 1926 parser.parseError(token.span, "unexpected-end-tag",
1927 {"name": token.name}); 1927 {"name": token.name});
1928 } 1928 }
1929 while (tree.openElements.removeLast() != node); 1929 while (tree.openElements.removeLast() != node);
1930 break; 1930 break;
1931 } else { 1931 } else {
1932 if (specialElements.contains(node.nameTuple)) { 1932 if (specialElements.contains(node.nameTuple)) {
1933 parser.parseError(token.span, "unexpected-end-tag", 1933 parser.parseError(token.span, "unexpected-end-tag",
1934 {"name": token.name}); 1934 {"name": token.name});
1935 break; 1935 break;
(...skipping 13 matching lines...) Expand all
1949 processEndTag(EndTagToken token) { 1949 processEndTag(EndTagToken token) {
1950 if (token.name == 'script') return endTagScript(token); 1950 if (token.name == 'script') return endTagScript(token);
1951 return endTagOther(token); 1951 return endTagOther(token);
1952 } 1952 }
1953 1953
1954 Token processCharacters(CharactersToken token) { 1954 Token processCharacters(CharactersToken token) {
1955 tree.insertText(token.data, token.span); 1955 tree.insertText(token.data, token.span);
1956 } 1956 }
1957 1957
1958 bool processEOF() { 1958 bool processEOF() {
1959 var last = tree.openElements.last(); 1959 var last = tree.openElements.last;
1960 parser.parseError(last.span, "expected-named-closing-tag-but-got-eof", 1960 parser.parseError(last.span, "expected-named-closing-tag-but-got-eof",
1961 {'name': last.tagName}); 1961 {'name': last.tagName});
1962 tree.openElements.removeLast(); 1962 tree.openElements.removeLast();
1963 parser.phase = parser.originalPhase; 1963 parser.phase = parser.originalPhase;
1964 return true; 1964 return true;
1965 } 1965 }
1966 1966
1967 void endTagScript(EndTagToken token) { 1967 void endTagScript(EndTagToken token) {
1968 var node = tree.openElements.removeLast(); 1968 var node = tree.openElements.removeLast();
1969 assert(node.tagName == "script"); 1969 assert(node.tagName == "script");
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2004 case "body": case "caption": case "col": case "colgroup": case "html": 2004 case "body": case "caption": case "col": case "colgroup": case "html":
2005 case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": 2005 case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr":
2006 return endTagIgnore(token); 2006 return endTagIgnore(token);
2007 default: return endTagOther(token); 2007 default: return endTagOther(token);
2008 } 2008 }
2009 } 2009 }
2010 2010
2011 // helper methods 2011 // helper methods
2012 void clearStackToTableContext() { 2012 void clearStackToTableContext() {
2013 // "clear the stack back to a table context" 2013 // "clear the stack back to a table context"
2014 while (tree.openElements.last().tagName != "table" && 2014 while (tree.openElements.last.tagName != "table" &&
2015 tree.openElements.last().tagName != "html") { 2015 tree.openElements.last.tagName != "html") {
2016 //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", 2016 //parser.parseError(token.span, "unexpected-implied-end-tag-in-table",
2017 // {"name": tree.openElements.last().name}) 2017 // {"name": tree.openElements.last.name})
2018 tree.openElements.removeLast(); 2018 tree.openElements.removeLast();
2019 } 2019 }
2020 // When the current node is <html> it's an innerHTML case 2020 // When the current node is <html> it's an innerHTML case
2021 } 2021 }
2022 2022
2023 // processing methods 2023 // processing methods
2024 bool processEOF() { 2024 bool processEOF() {
2025 var last = tree.openElements.last(); 2025 var last = tree.openElements.last;
2026 if (last.tagName != "html") { 2026 if (last.tagName != "html") {
2027 parser.parseError(last.span, "eof-in-table"); 2027 parser.parseError(last.span, "eof-in-table");
2028 } else { 2028 } else {
2029 assert(parser.innerHTMLMode); 2029 assert(parser.innerHTMLMode);
2030 } 2030 }
2031 //Stop parsing 2031 //Stop parsing
2032 return false; 2032 return false;
2033 } 2033 }
2034 2034
2035 Token processSpaceCharacters(SpaceCharactersToken token) { 2035 Token processSpaceCharacters(SpaceCharactersToken token) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2104 tree.openElements.removeLast(); 2104 tree.openElements.removeLast();
2105 } else { 2105 } else {
2106 startTagOther(token); 2106 startTagOther(token);
2107 } 2107 }
2108 } 2108 }
2109 2109
2110 void startTagForm(StartTagToken token) { 2110 void startTagForm(StartTagToken token) {
2111 parser.parseError(token.span, "unexpected-form-in-table"); 2111 parser.parseError(token.span, "unexpected-form-in-table");
2112 if (tree.formPointer === null) { 2112 if (tree.formPointer === null) {
2113 tree.insertElement(token); 2113 tree.insertElement(token);
2114 tree.formPointer = tree.openElements.last(); 2114 tree.formPointer = tree.openElements.last;
2115 tree.openElements.removeLast(); 2115 tree.openElements.removeLast();
2116 } 2116 }
2117 } 2117 }
2118 2118
2119 void startTagOther(StartTagToken token) { 2119 void startTagOther(StartTagToken token) {
2120 parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", 2120 parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo",
2121 {"name": token.name}); 2121 {"name": token.name});
2122 // Do the table magic! 2122 // Do the table magic!
2123 tree.insertFromTable = true; 2123 tree.insertFromTable = true;
2124 parser._inBodyPhase.processStartTag(token); 2124 parser._inBodyPhase.processStartTag(token);
2125 tree.insertFromTable = false; 2125 tree.insertFromTable = false;
2126 } 2126 }
2127 2127
2128 void endTagTable(EndTagToken token) { 2128 void endTagTable(EndTagToken token) {
2129 if (tree.elementInScope("table", variant: "table")) { 2129 if (tree.elementInScope("table", variant: "table")) {
2130 tree.generateImpliedEndTags(); 2130 tree.generateImpliedEndTags();
2131 var last = tree.openElements.last(); 2131 var last = tree.openElements.last;
2132 if (last.tagName != "table") { 2132 if (last.tagName != "table") {
2133 parser.parseError(token.span, "end-tag-too-early-named", 2133 parser.parseError(token.span, "end-tag-too-early-named",
2134 {"gotName": "table", "expectedName": last.tagName}); 2134 {"gotName": "table", "expectedName": last.tagName});
2135 } 2135 }
2136 while (tree.openElements.last().tagName != "table") { 2136 while (tree.openElements.last.tagName != "table") {
2137 tree.openElements.removeLast(); 2137 tree.openElements.removeLast();
2138 } 2138 }
2139 tree.openElements.removeLast(); 2139 tree.openElements.removeLast();
2140 parser.resetInsertionMode(); 2140 parser.resetInsertionMode();
2141 } else { 2141 } else {
2142 // innerHTML case 2142 // innerHTML case
2143 assert(parser.innerHTMLMode); 2143 assert(parser.innerHTMLMode);
2144 parser.parseError(token.span, "undefined-error"); 2144 parser.parseError(token.span, "undefined-error");
2145 } 2145 }
2146 } 2146 }
(...skipping 22 matching lines...) Expand all
2169 2169
2170 void flushCharacters() { 2170 void flushCharacters() {
2171 if (characterTokens.length == 0) return; 2171 if (characterTokens.length == 0) return;
2172 2172
2173 var data = joinStr(characterTokens.map((t) => t.data)); 2173 var data = joinStr(characterTokens.map((t) => t.data));
2174 var span = null; 2174 var span = null;
2175 2175
2176 if (parser.generateSpans) { 2176 if (parser.generateSpans) {
2177 span = new SourceSpan.union( 2177 span = new SourceSpan.union(
2178 characterTokens[0].span, 2178 characterTokens[0].span,
2179 characterTokens.last().span); 2179 characterTokens.last.span);
2180 } 2180 }
2181 2181
2182 if (!allWhitespace(data)) { 2182 if (!allWhitespace(data)) {
2183 parser._inTablePhase.insertText(new CharactersToken(data)..span = span); 2183 parser._inTablePhase.insertText(new CharactersToken(data)..span = span);
2184 } else if (data.length > 0) { 2184 } else if (data.length > 0) {
2185 tree.insertText(data, span); 2185 tree.insertText(data, span);
2186 } 2186 }
2187 characterTokens = <StringToken>[]; 2187 characterTokens = <StringToken>[];
2188 } 2188 }
2189 2189
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 } 2276 }
2277 2277
2278 Token startTagOther(StartTagToken token) { 2278 Token startTagOther(StartTagToken token) {
2279 return parser._inBodyPhase.processStartTag(token); 2279 return parser._inBodyPhase.processStartTag(token);
2280 } 2280 }
2281 2281
2282 void endTagCaption(EndTagToken token) { 2282 void endTagCaption(EndTagToken token) {
2283 if (!ignoreEndTagCaption()) { 2283 if (!ignoreEndTagCaption()) {
2284 // AT this code is quite similar to endTagTable in "InTable" 2284 // AT this code is quite similar to endTagTable in "InTable"
2285 tree.generateImpliedEndTags(); 2285 tree.generateImpliedEndTags();
2286 if (tree.openElements.last().tagName != "caption") { 2286 if (tree.openElements.last.tagName != "caption") {
2287 parser.parseError(token.span, "expected-one-end-tag-but-got-another", 2287 parser.parseError(token.span, "expected-one-end-tag-but-got-another",
2288 {"gotName": "caption", 2288 {"gotName": "caption",
2289 "expectedName": tree.openElements.last().tagName}); 2289 "expectedName": tree.openElements.last.tagName});
2290 } 2290 }
2291 while (tree.openElements.last().tagName != "caption") { 2291 while (tree.openElements.last.tagName != "caption") {
2292 tree.openElements.removeLast(); 2292 tree.openElements.removeLast();
2293 } 2293 }
2294 tree.openElements.removeLast(); 2294 tree.openElements.removeLast();
2295 tree.clearActiveFormattingElements(); 2295 tree.clearActiveFormattingElements();
2296 parser.phase = parser._inTablePhase; 2296 parser.phase = parser._inTablePhase;
2297 } else { 2297 } else {
2298 // innerHTML case 2298 // innerHTML case
2299 assert(parser.innerHTMLMode); 2299 assert(parser.innerHTMLMode);
2300 parser.parseError(token.span, "undefined-error"); 2300 parser.parseError(token.span, "undefined-error");
2301 } 2301 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 2335
2336 processEndTag(EndTagToken token) { 2336 processEndTag(EndTagToken token) {
2337 switch (token.name) { 2337 switch (token.name) {
2338 case "colgroup": return endTagColgroup(token); 2338 case "colgroup": return endTagColgroup(token);
2339 case "col": return endTagCol(token); 2339 case "col": return endTagCol(token);
2340 default: return endTagOther(token); 2340 default: return endTagOther(token);
2341 } 2341 }
2342 } 2342 }
2343 2343
2344 bool ignoreEndTagColgroup() { 2344 bool ignoreEndTagColgroup() {
2345 return tree.openElements.last().tagName == "html"; 2345 return tree.openElements.last.tagName == "html";
2346 } 2346 }
2347 2347
2348 bool processEOF() { 2348 bool processEOF() {
2349 var ignoreEndTag = ignoreEndTagColgroup(); 2349 var ignoreEndTag = ignoreEndTagColgroup();
2350 if (ignoreEndTag) { 2350 if (ignoreEndTag) {
2351 assert(parser.innerHTMLMode); 2351 assert(parser.innerHTMLMode);
2352 return false; 2352 return false;
2353 } else { 2353 } else {
2354 endTagColgroup(new EndTagToken("colgroup", data: {})); 2354 endTagColgroup(new EndTagToken("colgroup", data: {}));
2355 return true; 2355 return true;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2420 case "body": case "caption": case "col": case "colgroup": case "html": 2420 case "body": case "caption": case "col": case "colgroup": case "html":
2421 case "td": case "th": case "tr": 2421 case "td": case "th": case "tr":
2422 return endTagIgnore(token); 2422 return endTagIgnore(token);
2423 default: return endTagOther(token); 2423 default: return endTagOther(token);
2424 } 2424 }
2425 } 2425 }
2426 2426
2427 // helper methods 2427 // helper methods
2428 void clearStackToTableBodyContext() { 2428 void clearStackToTableBodyContext() {
2429 var tableTags = const ["tbody", "tfoot", "thead", "html"]; 2429 var tableTags = const ["tbody", "tfoot", "thead", "html"];
2430 while (!tableTags.contains(tree.openElements.last().tagName)) { 2430 while (!tableTags.contains(tree.openElements.last.tagName)) {
2431 //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", 2431 //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table",
2432 // {"name": tree.openElements.last().name}) 2432 // {"name": tree.openElements.last.name})
2433 tree.openElements.removeLast(); 2433 tree.openElements.removeLast();
2434 } 2434 }
2435 if (tree.openElements.last().tagName == "html") { 2435 if (tree.openElements.last.tagName == "html") {
2436 assert(parser.innerHTMLMode); 2436 assert(parser.innerHTMLMode);
2437 } 2437 }
2438 } 2438 }
2439 2439
2440 // the rest 2440 // the rest
2441 bool processEOF() { 2441 bool processEOF() {
2442 parser._inTablePhase.processEOF(); 2442 parser._inTablePhase.processEOF();
2443 return false; 2443 return false;
2444 } 2444 }
2445 2445
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 } 2481 }
2482 } 2482 }
2483 2483
2484 Token endTagTable(TagToken token) { 2484 Token endTagTable(TagToken token) {
2485 // XXX AT Any ideas on how to share this with endTagTable? 2485 // XXX AT Any ideas on how to share this with endTagTable?
2486 if (tree.elementInScope("tbody", variant: "table") || 2486 if (tree.elementInScope("tbody", variant: "table") ||
2487 tree.elementInScope("thead", variant: "table") || 2487 tree.elementInScope("thead", variant: "table") ||
2488 tree.elementInScope("tfoot", variant: "table")) { 2488 tree.elementInScope("tfoot", variant: "table")) {
2489 clearStackToTableBodyContext(); 2489 clearStackToTableBodyContext();
2490 endTagTableRowGroup( 2490 endTagTableRowGroup(
2491 new EndTagToken(tree.openElements.last().tagName, data: {})); 2491 new EndTagToken(tree.openElements.last.tagName, data: {}));
2492 return token; 2492 return token;
2493 } else { 2493 } else {
2494 // innerHTML case 2494 // innerHTML case
2495 assert(parser.innerHTMLMode); 2495 assert(parser.innerHTMLMode);
2496 parser.parseError(token.span, "undefined-error"); 2496 parser.parseError(token.span, "undefined-error");
2497 } 2497 }
2498 return null; 2498 return null;
2499 } 2499 }
2500 2500
2501 void endTagIgnore(EndTagToken token) { 2501 void endTagIgnore(EndTagToken token) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2533 case "body": case "caption": case "col": case "colgroup": case "html": 2533 case "body": case "caption": case "col": case "colgroup": case "html":
2534 case "td": case "th": 2534 case "td": case "th":
2535 return endTagIgnore(token); 2535 return endTagIgnore(token);
2536 default: return endTagOther(token); 2536 default: return endTagOther(token);
2537 } 2537 }
2538 } 2538 }
2539 2539
2540 // helper methods (XXX unify this with other table helper methods) 2540 // helper methods (XXX unify this with other table helper methods)
2541 void clearStackToTableRowContext() { 2541 void clearStackToTableRowContext() {
2542 while (true) { 2542 while (true) {
2543 var last = tree.openElements.last(); 2543 var last = tree.openElements.last;
2544 if (last.tagName == "tr" || last.tagName == "html") break; 2544 if (last.tagName == "tr" || last.tagName == "html") break;
2545 2545
2546 parser.parseError(last.span, "unexpected-implied-end-tag-in-table-row", 2546 parser.parseError(last.span, "unexpected-implied-end-tag-in-table-row",
2547 {"name": tree.openElements.last().tagName}); 2547 {"name": tree.openElements.last.tagName});
2548 tree.openElements.removeLast(); 2548 tree.openElements.removeLast();
2549 } 2549 }
2550 } 2550 }
2551 2551
2552 bool ignoreEndTagTr() { 2552 bool ignoreEndTagTr() {
2553 return !tree.elementInScope("tr", variant: "table"); 2553 return !tree.elementInScope("tr", variant: "table");
2554 } 2554 }
2555 2555
2556 // the rest 2556 // the rest
2557 bool processEOF() { 2557 bool processEOF() {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2682 } 2682 }
2683 } 2683 }
2684 2684
2685 Token startTagOther(StartTagToken token) { 2685 Token startTagOther(StartTagToken token) {
2686 return parser._inBodyPhase.processStartTag(token); 2686 return parser._inBodyPhase.processStartTag(token);
2687 } 2687 }
2688 2688
2689 void endTagTableCell(EndTagToken token) { 2689 void endTagTableCell(EndTagToken token) {
2690 if (tree.elementInScope(token.name, variant: "table")) { 2690 if (tree.elementInScope(token.name, variant: "table")) {
2691 tree.generateImpliedEndTags(token.name); 2691 tree.generateImpliedEndTags(token.name);
2692 if (tree.openElements.last().tagName != token.name) { 2692 if (tree.openElements.last.tagName != token.name) {
2693 parser.parseError(token.span, "unexpected-cell-end-tag", 2693 parser.parseError(token.span, "unexpected-cell-end-tag",
2694 {"name": token.name}); 2694 {"name": token.name});
2695 popOpenElementsUntil(token.name); 2695 popOpenElementsUntil(token.name);
2696 } else { 2696 } else {
2697 tree.openElements.removeLast(); 2697 tree.openElements.removeLast();
2698 } 2698 }
2699 tree.clearActiveFormattingElements(); 2699 tree.clearActiveFormattingElements();
2700 parser.phase = parser._inRowPhase; 2700 parser.phase = parser._inRowPhase;
2701 } else { 2701 } else {
2702 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 2702 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2742 switch (token.name) { 2742 switch (token.name) {
2743 case "option": return endTagOption(token); 2743 case "option": return endTagOption(token);
2744 case "optgroup": return endTagOptgroup(token); 2744 case "optgroup": return endTagOptgroup(token);
2745 case "select": return endTagSelect(token); 2745 case "select": return endTagSelect(token);
2746 default: return endTagOther(token); 2746 default: return endTagOther(token);
2747 } 2747 }
2748 } 2748 }
2749 2749
2750 // http://www.whatwg.org/specs/web-apps/current-work///in-select 2750 // http://www.whatwg.org/specs/web-apps/current-work///in-select
2751 bool processEOF() { 2751 bool processEOF() {
2752 var last = tree.openElements.last(); 2752 var last = tree.openElements.last;
2753 if (last.tagName != "html") { 2753 if (last.tagName != "html") {
2754 parser.parseError(last.span, "eof-in-select"); 2754 parser.parseError(last.span, "eof-in-select");
2755 } else { 2755 } else {
2756 assert(parser.innerHTMLMode); 2756 assert(parser.innerHTMLMode);
2757 } 2757 }
2758 return false; 2758 return false;
2759 } 2759 }
2760 2760
2761 Token processCharacters(CharactersToken token) { 2761 Token processCharacters(CharactersToken token) {
2762 if (token.data == "\u0000") { 2762 if (token.data == "\u0000") {
2763 return null; 2763 return null;
2764 } 2764 }
2765 tree.insertText(token.data, token.span); 2765 tree.insertText(token.data, token.span);
2766 } 2766 }
2767 2767
2768 void startTagOption(StartTagToken token) { 2768 void startTagOption(StartTagToken token) {
2769 // We need to imply </option> if <option> is the current node. 2769 // We need to imply </option> if <option> is the current node.
2770 if (tree.openElements.last().tagName == "option") { 2770 if (tree.openElements.last.tagName == "option") {
2771 tree.openElements.removeLast(); 2771 tree.openElements.removeLast();
2772 } 2772 }
2773 tree.insertElement(token); 2773 tree.insertElement(token);
2774 } 2774 }
2775 2775
2776 void startTagOptgroup(StartTagToken token) { 2776 void startTagOptgroup(StartTagToken token) {
2777 if (tree.openElements.last().tagName == "option") { 2777 if (tree.openElements.last.tagName == "option") {
2778 tree.openElements.removeLast(); 2778 tree.openElements.removeLast();
2779 } 2779 }
2780 if (tree.openElements.last().tagName == "optgroup") { 2780 if (tree.openElements.last.tagName == "optgroup") {
2781 tree.openElements.removeLast(); 2781 tree.openElements.removeLast();
2782 } 2782 }
2783 tree.insertElement(token); 2783 tree.insertElement(token);
2784 } 2784 }
2785 2785
2786 void startTagSelect(StartTagToken token) { 2786 void startTagSelect(StartTagToken token) {
2787 parser.parseError(token.span, "unexpected-select-in-select"); 2787 parser.parseError(token.span, "unexpected-select-in-select");
2788 endTagSelect(new EndTagToken("select", data: {})); 2788 endTagSelect(new EndTagToken("select", data: {}));
2789 } 2789 }
2790 2790
(...skipping 10 matching lines...) Expand all
2801 Token startTagScript(StartTagToken token) { 2801 Token startTagScript(StartTagToken token) {
2802 return parser._inHeadPhase.processStartTag(token); 2802 return parser._inHeadPhase.processStartTag(token);
2803 } 2803 }
2804 2804
2805 Token startTagOther(StartTagToken token) { 2805 Token startTagOther(StartTagToken token) {
2806 parser.parseError(token.span, "unexpected-start-tag-in-select", 2806 parser.parseError(token.span, "unexpected-start-tag-in-select",
2807 {"name": token.name}); 2807 {"name": token.name});
2808 } 2808 }
2809 2809
2810 void endTagOption(EndTagToken token) { 2810 void endTagOption(EndTagToken token) {
2811 if (tree.openElements.last().tagName == "option") { 2811 if (tree.openElements.last.tagName == "option") {
2812 tree.openElements.removeLast(); 2812 tree.openElements.removeLast();
2813 } else { 2813 } else {
2814 parser.parseError(token.span, "unexpected-end-tag-in-select", 2814 parser.parseError(token.span, "unexpected-end-tag-in-select",
2815 {"name": "option"}); 2815 {"name": "option"});
2816 } 2816 }
2817 } 2817 }
2818 2818
2819 void endTagOptgroup(EndTagToken token) { 2819 void endTagOptgroup(EndTagToken token) {
2820 // </optgroup> implicitly closes <option> 2820 // </optgroup> implicitly closes <option>
2821 if (tree.openElements.last().tagName == "option" && 2821 if (tree.openElements.last.tagName == "option" &&
2822 tree.openElements[tree.openElements.length - 2].tagName == "optgroup") { 2822 tree.openElements[tree.openElements.length - 2].tagName == "optgroup") {
2823 tree.openElements.removeLast(); 2823 tree.openElements.removeLast();
2824 } 2824 }
2825 // It also closes </optgroup> 2825 // It also closes </optgroup>
2826 if (tree.openElements.last().tagName == "optgroup") { 2826 if (tree.openElements.last.tagName == "optgroup") {
2827 tree.openElements.removeLast(); 2827 tree.openElements.removeLast();
2828 // But nothing else 2828 // But nothing else
2829 } else { 2829 } else {
2830 parser.parseError(token.span, "unexpected-end-tag-in-select", 2830 parser.parseError(token.span, "unexpected-end-tag-in-select",
2831 {"name": "optgroup"}); 2831 {"name": "optgroup"});
2832 } 2832 }
2833 } 2833 }
2834 2834
2835 void endTagSelect(EndTagToken token) { 2835 void endTagSelect(EndTagToken token) {
2836 if (tree.elementInScope("select", variant: "select")) { 2836 if (tree.elementInScope("select", variant: "select")) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2969 Token processCharacters(CharactersToken token) { 2969 Token processCharacters(CharactersToken token) {
2970 if (token.data == "\u0000") { 2970 if (token.data == "\u0000") {
2971 token.data = "\uFFFD"; 2971 token.data = "\uFFFD";
2972 } else if (parser.framesetOK && !allWhitespace(token.data)) { 2972 } else if (parser.framesetOK && !allWhitespace(token.data)) {
2973 parser.framesetOK = false; 2973 parser.framesetOK = false;
2974 } 2974 }
2975 super.processCharacters(token); 2975 super.processCharacters(token);
2976 } 2976 }
2977 2977
2978 Token processStartTag(StartTagToken token) { 2978 Token processStartTag(StartTagToken token) {
2979 var currentNode = tree.openElements.last(); 2979 var currentNode = tree.openElements.last;
2980 if (breakoutElements.contains(token.name) || 2980 if (breakoutElements.contains(token.name) ||
2981 (token.name == "font" && 2981 (token.name == "font" &&
2982 (token.data.containsKey("color") || 2982 (token.data.containsKey("color") ||
2983 token.data.containsKey("face") || 2983 token.data.containsKey("face") ||
2984 token.data.containsKey("size")))) { 2984 token.data.containsKey("size")))) {
2985 2985
2986 parser.parseError(token.span, 2986 parser.parseError(token.span,
2987 "unexpected-html-element-in-foreign-content", {'name': token.name}); 2987 "unexpected-html-element-in-foreign-content", {'name': token.name});
2988 while (tree.openElements.last().namespace != 2988 while (tree.openElements.last.namespace !=
2989 tree.defaultNamespace && 2989 tree.defaultNamespace &&
2990 !parser.isHTMLIntegrationPoint(tree.openElements.last()) && 2990 !parser.isHTMLIntegrationPoint(tree.openElements.last) &&
2991 !parser.isMathMLTextIntegrationPoint(tree.openElements.last())) { 2991 !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) {
2992 tree.openElements.removeLast(); 2992 tree.openElements.removeLast();
2993 } 2993 }
2994 return token; 2994 return token;
2995 2995
2996 } else { 2996 } else {
2997 if (currentNode.namespace == Namespaces.mathml) { 2997 if (currentNode.namespace == Namespaces.mathml) {
2998 parser.adjustMathMLAttributes(token); 2998 parser.adjustMathMLAttributes(token);
2999 } else if (currentNode.namespace == Namespaces.svg) { 2999 } else if (currentNode.namespace == Namespaces.svg) {
3000 adjustSVGTagNames(token); 3000 adjustSVGTagNames(token);
3001 parser.adjustSVGAttributes(token); 3001 parser.adjustSVGAttributes(token);
3002 } 3002 }
3003 parser.adjustForeignAttributes(token); 3003 parser.adjustForeignAttributes(token);
3004 token.namespace = currentNode.namespace; 3004 token.namespace = currentNode.namespace;
3005 tree.insertElement(token); 3005 tree.insertElement(token);
3006 if (token.selfClosing) { 3006 if (token.selfClosing) {
3007 tree.openElements.removeLast(); 3007 tree.openElements.removeLast();
3008 token.selfClosingAcknowledged = true; 3008 token.selfClosingAcknowledged = true;
3009 } 3009 }
3010 } 3010 }
3011 } 3011 }
3012 3012
3013 Token processEndTag(EndTagToken token) { 3013 Token processEndTag(EndTagToken token) {
3014 var nodeIndex = tree.openElements.length - 1; 3014 var nodeIndex = tree.openElements.length - 1;
3015 var node = tree.openElements.last(); 3015 var node = tree.openElements.last;
3016 if (node.tagName != token.name) { 3016 if (node.tagName != token.name) {
3017 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 3017 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
3018 } 3018 }
3019 3019
3020 var newToken = null; 3020 var newToken = null;
3021 while (true) { 3021 while (true) {
3022 if (asciiUpper2Lower(node.tagName) == token.name) { 3022 if (asciiUpper2Lower(node.tagName) == token.name) {
3023 //XXX this isn't in the spec but it seems necessary 3023 //XXX this isn't in the spec but it seems necessary
3024 if (parser.phase == parser._inTableTextPhase) { 3024 if (parser.phase == parser._inTableTextPhase) {
3025 InTableTextPhase inTableText = parser.phase; 3025 InTableTextPhase inTableText = parser.phase;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 } 3117 }
3118 3118
3119 processEndTag(EndTagToken token) { 3119 processEndTag(EndTagToken token) {
3120 switch (token.name) { 3120 switch (token.name) {
3121 case "frameset": return endTagFrameset(token); 3121 case "frameset": return endTagFrameset(token);
3122 default: return endTagOther(token); 3122 default: return endTagOther(token);
3123 } 3123 }
3124 } 3124 }
3125 3125
3126 bool processEOF() { 3126 bool processEOF() {
3127 var last = tree.openElements.last(); 3127 var last = tree.openElements.last;
3128 if (last.tagName != "html") { 3128 if (last.tagName != "html") {
3129 parser.parseError(last.span, "eof-in-frameset"); 3129 parser.parseError(last.span, "eof-in-frameset");
3130 } else { 3130 } else {
3131 assert(parser.innerHTMLMode); 3131 assert(parser.innerHTMLMode);
3132 } 3132 }
3133 return false; 3133 return false;
3134 } 3134 }
3135 3135
3136 Token processCharacters(CharactersToken token) { 3136 Token processCharacters(CharactersToken token) {
3137 parser.parseError(token.span, "unexpected-char-in-frameset"); 3137 parser.parseError(token.span, "unexpected-char-in-frameset");
(...skipping 11 matching lines...) Expand all
3149 Token startTagNoframes(StartTagToken token) { 3149 Token startTagNoframes(StartTagToken token) {
3150 return parser._inBodyPhase.processStartTag(token); 3150 return parser._inBodyPhase.processStartTag(token);
3151 } 3151 }
3152 3152
3153 Token startTagOther(StartTagToken token) { 3153 Token startTagOther(StartTagToken token) {
3154 parser.parseError(token.span, "unexpected-start-tag-in-frameset", 3154 parser.parseError(token.span, "unexpected-start-tag-in-frameset",
3155 {"name": token.name}); 3155 {"name": token.name});
3156 } 3156 }
3157 3157
3158 void endTagFrameset(EndTagToken token) { 3158 void endTagFrameset(EndTagToken token) {
3159 if (tree.openElements.last().tagName == "html") { 3159 if (tree.openElements.last.tagName == "html") {
3160 // innerHTML case 3160 // innerHTML case
3161 parser.parseError(token.span, 3161 parser.parseError(token.span,
3162 "unexpected-frameset-in-frameset-innerhtml"); 3162 "unexpected-frameset-in-frameset-innerhtml");
3163 } else { 3163 } else {
3164 tree.openElements.removeLast(); 3164 tree.openElements.removeLast();
3165 } 3165 }
3166 if (!parser.innerHTMLMode && tree.openElements.last().tagName != "frameset") { 3166 if (!parser.innerHTMLMode && tree.openElements.last.tagName != "frameset") {
3167 // If we're not in innerHTML mode and the the current node is not a 3167 // If we're not in innerHTML mode and the the current node is not a
3168 // "frameset" element (anymore) then switch. 3168 // "frameset" element (anymore) then switch.
3169 parser.phase = parser._afterFramesetPhase; 3169 parser.phase = parser._afterFramesetPhase;
3170 } 3170 }
3171 } 3171 }
3172 3172
3173 void endTagOther(EndTagToken token) { 3173 void endTagOther(EndTagToken token) {
3174 parser.parseError(token.span, "unexpected-end-tag-in-frameset", 3174 parser.parseError(token.span, "unexpected-end-tag-in-frameset",
3175 {"name": token.name}); 3175 {"name": token.name});
3176 } 3176 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3326 /** 3326 /**
3327 * Gets the human readable error message for this error. Does not include 3327 * Gets the human readable error message for this error. Does not include
3328 * any source span information, but you can use [span.getLocationMessage] 3328 * any source span information, but you can use [span.getLocationMessage]
3329 * if you want to provide a filename prefix, or [toString] if you want 3329 * if you want to provide a filename prefix, or [toString] if you want
3330 * "ParseError" to be the prefix. 3330 * "ParseError" to be the prefix.
3331 */ 3331 */
3332 String get message => formatStr(errorMessages[errorCode], data); 3332 String get message => formatStr(errorMessages[errorCode], data);
3333 3333
3334 String toString() => span.getLocationMessage('ParseError', message); 3334 String toString() => span.getLocationMessage('ParseError', message);
3335 } 3335 }
OLDNEW
« no previous file with comments | « lib/dom.dart ('k') | lib/src/inputstream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698