| Index: third_party/WebKit/PerformanceTests/HTMLToDOM/dom/domparser.js
|
| diff --git a/third_party/WebKit/PerformanceTests/HTMLToDOM/dom/domparser.js b/third_party/WebKit/PerformanceTests/HTMLToDOM/dom/domparser.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f25fe672c999a04cfc5669efad7218b2aaeeeec9
|
| --- /dev/null
|
| +++ b/third_party/WebKit/PerformanceTests/HTMLToDOM/dom/domparser.js
|
| @@ -0,0 +1,199 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +"use strict";
|
| +
|
| +(function(exports) {
|
| +
|
| +var GREATER_THAN = 62;
|
| +var LESS_THAN = 60;
|
| +var EQUALS = 61;
|
| +var SINGLE_QUOTE = 39;
|
| +var DOUBLE_QUOTE = 34;
|
| +var SPACE = 32;
|
| +var NEW_LINE = 10;
|
| +var CARRIAGE_RETURN = 13;
|
| +var TAB = 9;
|
| +var SLASH = 47;
|
| +
|
| +class DomParser {
|
| + constructor(string, bindings) {
|
| + this.string = String(string || "");
|
| + this.state = "parseText";
|
| + this.offset = 0;
|
| + this.stack = [bindings.createDocumentFragment()];
|
| + this.bindings = bindings;
|
| + // Object.preventExtensions(this);
|
| + }
|
| +
|
| + parse() {
|
| + while (this.hasMoreChars()) {
|
| + // console.log({state: this.state}, this.string.substring(this.offset));
|
| + this[this.state]();
|
| + }
|
| + return this.stack[0];
|
| + }
|
| +
|
| + parseText() {
|
| + var value = this.consumeStringUntil(LESS_THAN);
|
| + if (value) {
|
| + var text = this.bindings.createText(value);
|
| + this.bindings.appendChild(this.currentNode(), text);
|
| + }
|
| + if (this.currentCharCode() === LESS_THAN) {
|
| + this.offset++;
|
| + this.state = "parseTagName";
|
| + }
|
| + // console.log("parseText", value);
|
| + }
|
| +
|
| + parseTagName() {
|
| + var endTag = false;
|
| + if (this.currentCharCode() === SLASH) {
|
| + this.offset++;
|
| + endTag = true;
|
| + }
|
| + var tagName = this.consumeTagIdent();
|
| + if (tagName && endTag) {
|
| + // Implicitly close all mis-nested tags.
|
| + while (this.currentNode().tagName != tagName && this.stack.length > 1) {
|
| + this.stack.pop();
|
| + }
|
| + if (this.currentNode().tagName === tagName)
|
| + this.stack.pop();
|
| + this.skipWhitespace();
|
| + if (this.currentCharCode() === GREATER_THAN)
|
| + this.offset++;
|
| + this.state = "parseText";
|
| + } else if (tagName && !endTag) {
|
| + var element = this.bindings.createElement(tagName);
|
| + this.bindings.appendChild(this.currentNode(), element);
|
| + if (this.currentCharCode() === SLASH) {
|
| + this.offset++;
|
| + if (this.currentCharCode() === GREATER_THAN) {
|
| + this.offset++;
|
| + endTag = true;
|
| + }
|
| + }
|
| + if (!endTag) {
|
| + this.stack.push(element);
|
| + this.state = "parseAttribute";
|
| + } else {
|
| + this.state = "parseText";
|
| + }
|
| + }
|
| +
|
| + // console.log("parseTagName", tagName, {endTag: endTag});
|
| + }
|
| +
|
| + parseAttribute() {
|
| + this.skipWhitespace();
|
| + var name = this.consumeAttributeName();
|
| + var value = "";
|
| + this.skipWhitespace();
|
| + var charCode = this.currentCharCode();
|
| + if (charCode === EQUALS) {
|
| + this.offset++;
|
| + this.skipWhitespace();
|
| + charCode = this.currentCharCode();
|
| + if (charCode === SINGLE_QUOTE || charCode === DOUBLE_QUOTE) {
|
| + this.offset++;
|
| + value = this.consumeStringUntil(charCode);
|
| + this.offset++;
|
| + } else {
|
| + value = this.consumeTagIdent();
|
| + }
|
| + }
|
| + if (name)
|
| + this.bindings.setAttribute(this.currentNode(), name, value || "");
|
| + this.skipWhitespace();
|
| + charCode = this.currentCharCode();
|
| + var endTag = false;
|
| + if (charCode === SLASH) {
|
| + this.offset++;
|
| + endTag = true;
|
| + }
|
| + charCode = this.currentCharCode();
|
| + if (charCode === GREATER_THAN) {
|
| + if (endTag)
|
| + this.stack.pop();
|
| + this.offset++;
|
| + this.state = "parseText";
|
| + }
|
| + // console.log("parseAttribute", name, value);
|
| + }
|
| +
|
| + consumeAttributeName() {
|
| + var startOffset = this.offset;
|
| + while (this.hasMoreChars() && !this.isWhitespaceChar()) {
|
| + var charCode = this.currentCharCode();
|
| + if (charCode === EQUALS || charCode === GREATER_THAN || charCode === SLASH)
|
| + break;
|
| + this.advance();
|
| + }
|
| + if (startOffset < this.offset)
|
| + return this.string.substring(this.offset, startOffset);
|
| + return "";
|
| + }
|
| +
|
| + consumeTagIdent() {
|
| + var startOffset = this.offset;
|
| + while (this.hasMoreChars() && !this.isWhitespaceChar()) {
|
| + var charCode = this.currentCharCode();
|
| + if (charCode === GREATER_THAN || charCode === SLASH)
|
| + break;
|
| + this.advance();
|
| + }
|
| + if (startOffset < this.offset)
|
| + return this.string.substring(this.offset, startOffset);
|
| + return "";
|
| + }
|
| +
|
| + consumeStringUntil(stopChar) {
|
| + var startOffset = this.offset;
|
| + while (this.hasMoreChars()) {
|
| + var charCode = this.currentCharCode();
|
| + if (charCode === stopChar)
|
| + break;
|
| + this.advance();
|
| + }
|
| + if (startOffset < this.offset)
|
| + return this.string.substring(this.offset, startOffset);
|
| + return "";
|
| + }
|
| +
|
| + skipWhitespace() {
|
| + while (this.hasMoreChars() && this.isWhitespaceChar())
|
| + this.advance();
|
| + }
|
| +
|
| + isWhitespaceChar() {
|
| + var charCode = this.currentCharCode();
|
| + return charCode === SPACE ||
|
| + charCode === NEW_LINE ||
|
| + charCode === CARRIAGE_RETURN ||
|
| + charCode === TAB;
|
| + }
|
| +
|
| + currentCharCode() {
|
| + return this.string.charCodeAt(this.offset);
|
| + }
|
| +
|
| + hasMoreChars() {
|
| + return this.offset < this.string.length;
|
| + }
|
| +
|
| + advance() {
|
| + this.offset++;
|
| + }
|
| +
|
| + currentNode() {
|
| + return this.stack[this.stack.length - 1];
|
| + }
|
| +}
|
| +
|
| +// Object.preventExtensions(DomParser.prototype);
|
| +
|
| +exports.DomParser = DomParser;
|
| +
|
| +})(this);
|
|
|