mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 02:54:11 +08:00

Add parsers for the background css shorthand property, make ViewBase unit testable in node environment Add background parser and linear-gradient parser Use sticky regexes Simplify some types, introduce generic Parsed<T> instead of & TokenRange Apply each parser to return a { start, end, value } object Move the css selector parser to the css/parser and unify types Add the first steps toward building homegrown css parser Add somewhat standards compliant tokenizer, add baseline, rework and shady css parsers Enable all tests again, skip flaky perf test Improve css parser tokenizer by converting some char token types to simple string Implement 'parse a stylesheet' Add gonzales css-parser Add parseLib and css-tree perf Add a thin parser layer that will convert CSS3 tokens to values, for now output is compatible with rework Make root tsc green Return the requires of tns-core-modules to use relative paths for webpack to work Implement support for '@import 'url-string'; Fix function parser, function-token is no-longer neglected Make the style-scope be able to load from "css" and "css-ast" modules Add a loadAppCss event so theme can be added to snapshot separately from loaded
462 lines
25 KiB
TypeScript
462 lines
25 KiB
TypeScript
import { assert } from "chai";
|
|
import {
|
|
parseURL,
|
|
parseColor,
|
|
parsePercentageOrLength,
|
|
parseBackgroundPosition,
|
|
parseBackground,
|
|
parseSelector,
|
|
AttributeSelectorTest,
|
|
CSS3Parser,
|
|
TokenObjectType,
|
|
CSSNativeScript,
|
|
} from "tns-core-modules/css/parser";
|
|
import {
|
|
parse
|
|
} from "tns-core-modules/css";
|
|
|
|
import * as fs from "fs";
|
|
import * as shadyCss from 'shady-css-parser';
|
|
import * as reworkCss from 'css';
|
|
|
|
const parseCss: any = require('parse-css');
|
|
const gonzales: any = require('gonzales');
|
|
const parserlib: any = require("parserlib");
|
|
const csstree: any = require('css-tree');
|
|
|
|
describe("css", () => {
|
|
describe("parser", () => {
|
|
function test<T>(parse: (value: string, lastIndex?: number) => T, value: string, expected: T);
|
|
function test<T>(parse: (value: string, lastIndex?: number) => T, value: string, lastIndex: number, expected: T);
|
|
function test<T>(parse: (value: string, lastIndex?: number) => T, value: string, lastIndexOrExpected: number | T, expected?: T) {
|
|
if (arguments.length === 3) {
|
|
it(`${lastIndexOrExpected ? "can parse " : "can not parse "}"${value}"`, () => {
|
|
const result = parse(value);
|
|
assert.deepEqual(result, lastIndexOrExpected);
|
|
});
|
|
} else {
|
|
it(`${expected ? "can parse " : "can not parse "}"${value}" starting at index ${lastIndexOrExpected}`, () => {
|
|
const result = parse(value, <number>lastIndexOrExpected);
|
|
assert.deepEqual(result, expected);
|
|
});
|
|
}
|
|
}
|
|
|
|
describe("values", () => {
|
|
describe("url", () => {
|
|
test(parseURL, "url('smiley.gif') ", { start: 0, end: 19, value: "smiley.gif" });
|
|
test(parseURL, ' url("frown.gif") ', { start: 0, end: 19, value: "frown.gif" });
|
|
test(parseURL, " url(lucky.gif)", { start: 0, end: 16, value: "lucky.gif" });
|
|
test(parseURL, "url(lucky.gif) #FF0000", 15, null);
|
|
test(parseURL, "repeat url(lucky.gif) #FF0000", 6, { start: 6, end: 22, value: "lucky.gif" });
|
|
});
|
|
describe("color", () => {
|
|
test(parseColor, " #369 ", { start: 0, end: 7, value: 0xFF336699 });
|
|
test(parseColor, " #456789 ", { start: 0, end: 10, value: 0xFF456789 });
|
|
test(parseColor, " #85456789 ", { start: 0, end: 12, value: 0x85456789 });
|
|
test(parseColor, " rgb(255, 8, 128) ", { start: 0, end: 18, value: 0xFFFF0880 });
|
|
test(parseColor, " rgba(255, 8, 128, 0.5) ", { start: 0, end: 24, value: 0x80FF0880 });
|
|
test(parseColor, "#FF0000 url(lucky.gif)", 8, null);
|
|
test(parseColor, "url(lucky.gif) #FF0000 repeat", 15, { start: 15, end: 23, value: 0xFFFF0000 });
|
|
});
|
|
describe("units", () => {
|
|
test(parsePercentageOrLength, " 100% ", { start: 0, end: 6, value: { value: 1, unit: "%" }});
|
|
test(parsePercentageOrLength, " 100px ", { start: 0, end: 7, value: { value: 100, unit: "px" }});
|
|
test(parsePercentageOrLength, " 0.5px ", { start: 0, end: 7, value: { value: 0.5, unit: "px" }});
|
|
test(parsePercentageOrLength, " 100dip ", { start: 0, end: 8, value: { value: 100, unit: "dip" }});
|
|
test(parsePercentageOrLength, " 100 ", { start: 0, end: 5, value: { value: 100, unit: "dip" }});
|
|
test(parsePercentageOrLength, " 100 ", { start: 0, end: 5, value: { value: 100, unit: "dip" }});
|
|
test(parsePercentageOrLength, " +-12.2 ", null);
|
|
});
|
|
describe("position", () => {
|
|
test(parseBackgroundPosition, "left", { start: 0, end: 4, value: { x: "left", y: "center" }});
|
|
test(parseBackgroundPosition, "center", { start: 0, end: 6, value: { x: "center", y: "center" }});
|
|
test(parseBackgroundPosition, "right", { start: 0, end: 5, value: { x: "right", y: "center" }});
|
|
test(parseBackgroundPosition, "top", { start: 0, end: 3, value: { x: "center", y: "top" }});
|
|
test(parseBackgroundPosition, "bottom", { start: 0, end: 6, value: { x: "center", y: "bottom" }});
|
|
test(parseBackgroundPosition, "top 75px left 100px", { start: 0, end: 19, value: {
|
|
x: { align: "left", offset: { value: 100, unit: "px" }},
|
|
y: { align: "top", offset: { value: 75, unit: "px" }}
|
|
}});
|
|
test(parseBackgroundPosition, "left 100px top 75px", { start: 0, end: 19, value: {
|
|
x: { align: "left", offset: { value: 100, unit: "px" }},
|
|
y: { align: "top", offset: { value: 75, unit: "px" }}
|
|
}});
|
|
test(parseBackgroundPosition, "right center", { start: 0, end: 12, value: { x: "right", y: "center" }});
|
|
test(parseBackgroundPosition, "center left 100%", { start: 0, end: 16, value: { x: { align: "left", offset: { value: 1, unit: "%" }}, y: "center" }});
|
|
test(parseBackgroundPosition, "top 50% left 100%", { start: 0, end: 17, value: { x: { align: "left", offset: { value: 1, unit: "%" }}, y: { align: "top", offset: { value: 0.5, unit: "%" }}}});
|
|
test(parseBackgroundPosition, "bottom left 25%", { start: 0, end: 15, value: { x: { align: "left", offset: { value: 0.25, unit: "%" }}, y: "bottom" }});
|
|
test(parseBackgroundPosition, "top 100% left 25%", { start: 0, end: 17, value: { x: { align: "left", offset: { value: 0.25, unit: "%" }}, y: { align: "top", offset: { value: 1, unit: "%" }}}});
|
|
});
|
|
describe("background", () => {
|
|
test(parseBackground, " #996633 ", { start: 0, end: 12, value: { color: 0xFF996633 }});
|
|
test(parseBackground, ' #00ff00 url("smiley.gif") repeat-y ', { start: 0, end: 37, value: { color: 0xFF00FF00, image: "smiley.gif", repeat: "repeat-y" }});
|
|
test(parseBackground, ' url(smiley.gif) no-repeat top 50% left 100% #00ff00', { start: 0, end: 56, value: {
|
|
color: 0xFF00FF00,
|
|
image: "smiley.gif",
|
|
repeat: "no-repeat",
|
|
position: {
|
|
x: { align: "left", offset: { value: 1, unit: "%" }},
|
|
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
|
}
|
|
}});
|
|
test(parseBackground, ' url(smiley.gif) no-repeat top 50% left 100% / 100px 100px #00ff00', { start: 0, end: 70, value: {
|
|
color: 0xFF00FF00,
|
|
image: "smiley.gif",
|
|
repeat: "no-repeat",
|
|
position: {
|
|
x: { align: "left", offset: { value: 1, unit: "%" }},
|
|
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
|
},
|
|
size: { x: { value: 100, unit: "px" }, y: { value: 100, unit: "px" }}
|
|
}});
|
|
test(parseBackground, ' linear-gradient(to right top) ', { start: 0, end: 32, value: {
|
|
image: {
|
|
angle: Math.PI * 1/4,
|
|
colors: []
|
|
}
|
|
}});
|
|
test(parseBackground, ' linear-gradient(45deg, #0000FF, #00FF00) ', { start: 0, end: 43, value: {
|
|
image: {
|
|
angle: Math.PI * 1/4,
|
|
colors: [
|
|
{ argb: 0xFF0000FF },
|
|
{ argb: 0xFF00FF00 }
|
|
]
|
|
}
|
|
}});
|
|
test(parseBackground, 'linear-gradient(0deg, blue, green 40%, red)', { start: 0, end: 43, value: {
|
|
image: {
|
|
angle: Math.PI * 0/4,
|
|
colors: [
|
|
{ argb: 0xFF0000FF },
|
|
{ argb: 0xFF008000, offset: { value: 0.4, unit: "%" }},
|
|
{ argb: 0xFFFF0000 }
|
|
]
|
|
}
|
|
}});
|
|
});
|
|
});
|
|
|
|
describe("selectors", () => {
|
|
test(parseSelector, ` listview#products.mark gridlayout:selected[row="2"] a> b > c >d>e *[src] `, {
|
|
start: 0, end: 79, value: [
|
|
[
|
|
{ type: "", identifier: "listview" },
|
|
{ type: "#", identifier: "products" },
|
|
{ type: ".", identifier: "mark" }
|
|
],
|
|
" ",
|
|
[
|
|
{ type: "", identifier: "gridlayout" },
|
|
{ type: ":", identifier: "selected" },
|
|
{ type: "[]", property: "row", test: "=", value: "2" }
|
|
],
|
|
" ",
|
|
[{ type: "", identifier: "a"}],
|
|
">",
|
|
[{ type: "", identifier: "b"}],
|
|
">",
|
|
[{ type: "", identifier: "c"}],
|
|
">",
|
|
[{ type: "", identifier: "d"}],
|
|
">",
|
|
[{ type: "", identifier: "e"}],
|
|
" ",
|
|
[
|
|
{ type: "*" },
|
|
{ type: "[]", property: "src" }
|
|
],
|
|
undefined
|
|
],
|
|
});
|
|
test(parseSelector, "*", { start: 0, end: 1, value: [[{ type: "*" }], undefined ]});
|
|
test(parseSelector, "button", { start: 0, end: 6, value: [[{ type: "", identifier: "button" }], undefined]});
|
|
test(parseSelector, ".login", { start: 0, end: 6, value: [[{ type: ".", identifier: "login" }], undefined]});
|
|
test(parseSelector, "#login", { start: 0, end: 6, value: [[{ type: "#", identifier: "login" }], undefined]});
|
|
test(parseSelector, ":hover", { start: 0, end: 6, value: [[{ type: ":", identifier: "hover" }], undefined]});
|
|
test(parseSelector, "[src]", { start: 0, end: 5, value: [[{ type: "[]", property: "src" }], undefined]});
|
|
test(parseSelector, `[src = "res://"]`, { start: 0, end: 16, value: [[{ type: "[]", property: "src", test: "=", value: `res://`}], undefined]});
|
|
(<AttributeSelectorTest[]>["=", "^=", "$=", "*=", "=", "~=", "|="]).forEach(attributeTest => {
|
|
test(parseSelector, `[src ${attributeTest} "val"]`, { start: 0, end: 12 + attributeTest.length, value: [[{ type: "[]", property: "src", test: attributeTest, value: "val"}], undefined]});
|
|
});
|
|
test(parseSelector, "listview > .image", { start: 0, end: 17, value: [[{ type: "", identifier: "listview"}], ">", [{ type: ".", identifier: "image"}], undefined]});
|
|
test(parseSelector, "listview .image", { start: 0, end: 16, value: [[{ type: "", identifier: "listview"}], " ", [{ type: ".", identifier: "image"}], undefined]});
|
|
test(parseSelector, "button:hover", { start: 0, end: 12, value: [[{ type: "", identifier: "button" }, { type: ":", identifier: "hover"}], undefined]});
|
|
test(parseSelector, "listview>:selected image.product", { start: 0, end: 32, value: [
|
|
[{ type: "", identifier: "listview" }],
|
|
">",
|
|
[{ type: ":", identifier: "selected" }],
|
|
" ",
|
|
[
|
|
{ type: "", identifier: "image" },
|
|
{ type: ".", identifier: "product" }
|
|
],
|
|
undefined
|
|
]});
|
|
test(parseSelector, "button[testAttr]", { start: 0, end: 16, value: [
|
|
[
|
|
{ type: "", identifier: "button" },
|
|
{ type: "[]", property: "testAttr" },
|
|
],
|
|
undefined
|
|
]});
|
|
test(parseSelector, "button#login[user][pass]:focused:hovered", { start: 0, end: 40, value: [
|
|
[
|
|
{ type: "", identifier: "button" },
|
|
{ type: "#", identifier: "login" },
|
|
{ type: "[]", property: "user" },
|
|
{ type: "[]", property: "pass" },
|
|
{ type: ":", identifier: "focused" },
|
|
{ type: ":", identifier: "hovered" }
|
|
],
|
|
undefined
|
|
]});
|
|
});
|
|
|
|
describe("css3", () => {
|
|
let themeCoreLightIos: string;
|
|
let whatIsNewIos: string;
|
|
|
|
before("Read the core.light.css file", () => {
|
|
themeCoreLightIos = fs.readFileSync(`${__dirname}/assets/core.light.css`).toString();
|
|
whatIsNewIos = fs.readFileSync(`${__dirname}/assets/what-is-new.ios.css`).toString();
|
|
});
|
|
|
|
describe("tokenizer", () => {
|
|
it("the tokenizer roundtrips the core.light.css theme", () => {
|
|
const cssparser = new CSS3Parser(themeCoreLightIos);
|
|
const stylesheet = cssparser.tokenize();
|
|
|
|
let original = themeCoreLightIos.replace(/\/\*([^\/]|\/[^\*])*\*\//g, "").replace(/\n/g, " ");
|
|
let roundtrip = stylesheet.map(m => {
|
|
if (!m) return "";
|
|
if (typeof m === "string") return m;
|
|
return m.text;
|
|
}).join("");
|
|
|
|
let lastIndex = Math.min(original.length, roundtrip.length);
|
|
for(var i = 0; i < lastIndex; i++)
|
|
if (original[i] != roundtrip[i])
|
|
assert.equal(roundtrip.substr(i, 50), original.substr(i, 50), "Round-tripped CSS string differ at index: " + i);
|
|
|
|
assert.equal(roundtrip.length, original.length, "Expected round-tripped string lengths to match.");
|
|
});
|
|
|
|
it("test what-is-new.ios.css from nativescript-marketplace-demo", () => {
|
|
const parser = new CSS3Parser(whatIsNewIos);
|
|
const tokens = parser.tokenize();
|
|
assert.deepEqual(tokens, [
|
|
{ type: TokenObjectType.atKeyword, text: "import" },
|
|
" ",
|
|
{ type: TokenObjectType.url, text: "url('~/views/what-is-new-common.css')" },
|
|
";", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "news-card" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "margin" },
|
|
":", " ",
|
|
{ type: TokenObjectType.number, text: "12" },
|
|
" ",
|
|
{ type: TokenObjectType.number, text: "12" },
|
|
" ",
|
|
{ type: TokenObjectType.number, text: "0" },
|
|
" ",
|
|
{ type: TokenObjectType.number, text: "12" },
|
|
";", " ", "}", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "title" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "font-size" },
|
|
":", " ",
|
|
{ type: TokenObjectType.number, text: "14" },
|
|
";", " ", "}", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "body" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "font-size" },
|
|
":", " ",
|
|
{ type: TokenObjectType.number, text: "14" },
|
|
";", " ", "}", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "learn-more" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "font-size" },
|
|
":", " ",
|
|
{ type: TokenObjectType.number, text: "14" },
|
|
";", " ", "}", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "date" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "font-size" },
|
|
":", " ",
|
|
{ type: TokenObjectType.number, text: "12" },
|
|
";", " ", "}", " ",
|
|
{ type: TokenObjectType.delim, text: "." },
|
|
{ type: TokenObjectType.ident, text: "empty-placeholder" },
|
|
" ", "{", " ",
|
|
{ type: TokenObjectType.ident, text: "vertical-align" },
|
|
":", " ",
|
|
{ type: TokenObjectType.ident, text: "center" },
|
|
";", " ",
|
|
{ type: TokenObjectType.ident, text: "text-align" },
|
|
":", " ",
|
|
{ type: TokenObjectType.ident, text: "center" },
|
|
";", " ", "}",
|
|
undefined // EOF
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("parser", () => {
|
|
it("test what-is-new.ios.css from nativescript-marketplace-demo", () => {
|
|
const parser = new CSS3Parser(whatIsNewIos);
|
|
const stylesheet = parser.parseAStylesheet();
|
|
// console.log(JSON.stringify(stylesheet, null, "\t"));
|
|
// TODO: Assert...
|
|
});
|
|
|
|
it(".btn-primary{border-color:rgba(255,0,0,0)}", () => {
|
|
const parser = new CSS3Parser(".btn-primary{border-color:rgba(255,0,0,0)}");
|
|
const stylesheet = parser.parseAStylesheet();
|
|
|
|
assert.deepEqual(stylesheet, {rules:[
|
|
{
|
|
type: "qualified-rule",
|
|
prelude: [{ type: 2, text: "." }, { type: 6, text: "btn-primary" }],
|
|
block: { type: 9, text: "{border-color:rgba(255,0,0,0)}", associatedToken: "{", values: [
|
|
{ type: 6, text: "border-color" },
|
|
":",
|
|
{ type: 14, name: "rgba", text: "rgba(255,0,0,0)", components: [
|
|
{ type: 3, text: "255" }, ",",
|
|
{ type: 3, text: "0"}, ",",
|
|
{ type: 3, text: "0"}, ",",
|
|
{ type: 3, text: "0"}
|
|
]}
|
|
]}
|
|
}]},
|
|
"NativeScript parsed AST doesn't match.");
|
|
|
|
const cssToNS = new CSSNativeScript();
|
|
const nativescriptAst = cssToNS.parseStylesheet(stylesheet);
|
|
|
|
assert.deepEqual(nativescriptAst, { type: "stylesheet", stylesheet: { rules: [
|
|
{
|
|
type: "rule",
|
|
selectors: [".btn-primary"],
|
|
declarations: [{
|
|
"type": "declaration",
|
|
"property": "border-color",
|
|
"value": "rgba(255,0,0,0)"
|
|
}]
|
|
}]}},
|
|
"NativeScript AST mapped to rework doesn't match.");
|
|
});
|
|
});
|
|
|
|
it("serialization", () => {
|
|
const reworkAst = reworkCss.parse(themeCoreLightIos, { source: "nativescript-theme-core/css/core.light.css" });
|
|
fs.writeFileSync("unit-tests/css/out/rework.css.json", JSON.stringify(reworkAst, (k, v) => k === "position" ? undefined : v, " "));
|
|
|
|
const nsParser = new CSS3Parser(themeCoreLightIos);
|
|
const nativescriptStylesheet = nsParser.parseAStylesheet();
|
|
const cssToNS = new CSSNativeScript();
|
|
const nativescriptAst = cssToNS.parseStylesheet(nativescriptStylesheet);
|
|
|
|
fs.writeFileSync("unit-tests/css/out/nativescript.css.json", JSON.stringify(nativescriptAst, null, " "));
|
|
});
|
|
|
|
it.skip("our parser is fast (this test is flaky, gc, opts.)", () => {
|
|
function trapDuration(action: () => void) {
|
|
const [startSec, startMSec] = process.hrtime();
|
|
action();
|
|
const [endSec, endMSec] = process.hrtime();
|
|
return (endSec - startSec) * 1000 + (endMSec - startMSec) / 1000000;
|
|
}
|
|
const charCodeByCharCodeDuration = trapDuration(() => {
|
|
let count = 0;
|
|
for (let i = 0; i < themeCoreLightIos.length; i++) {
|
|
count += themeCoreLightIos.charCodeAt(i);
|
|
}
|
|
assert.equal(count, 1218711);
|
|
});
|
|
const charByCharDuration = trapDuration(() => {
|
|
let char;
|
|
for (let i = 0; i < themeCoreLightIos.length; i++) {
|
|
char = themeCoreLightIos.charAt(i);
|
|
}
|
|
assert.equal(char, "\n");
|
|
});
|
|
const compareCharIfDuration = trapDuration(() => {
|
|
let char;
|
|
let c = 0;
|
|
for (let i = 0; i < themeCoreLightIos.length; i++) {
|
|
const char = themeCoreLightIos[i];
|
|
if ((char >= "a" && char <= "z") || (char >= "A" && char <= "Z") || char === "_") {
|
|
c++;
|
|
}
|
|
}
|
|
assert.equal(c, 8774);
|
|
});
|
|
const compareCharRegEx = /[a-zA-Z_]/;
|
|
const compareCharRegExDuration = trapDuration(() => {
|
|
let char;
|
|
let c = 0;
|
|
for (let i = 0; i < themeCoreLightIos.length; i++) {
|
|
const char = themeCoreLightIos[i];
|
|
if (compareCharRegEx.test(char)) {
|
|
c++;
|
|
}
|
|
}
|
|
assert.equal(c, 8774);
|
|
});
|
|
const indexerDuration = trapDuration(() => {
|
|
let char;
|
|
for (let i = 0; i < themeCoreLightIos.length; i++) {
|
|
char = themeCoreLightIos[i];
|
|
}
|
|
assert.equal(char, "\n");
|
|
});
|
|
const reworkDuration = trapDuration(() => {
|
|
const ast = reworkCss.parse(themeCoreLightIos, { source: "nativescript-theme-core/css/core.light.css" });
|
|
// fs.writeFileSync("rework.css.json", JSON.stringify(ast, null, "\t"));
|
|
});
|
|
const shadyDuration = trapDuration(() => {
|
|
const shadyParser = new shadyCss.Parser();
|
|
const ast = shadyParser.parse(themeCoreLightIos);
|
|
// fs.writeFileSync("shady.css.json", JSON.stringify(ast, null, "\t"));
|
|
});
|
|
const parseCssDuration = trapDuration(() => {
|
|
const tokens = parseCss.tokenize(themeCoreLightIos);
|
|
const ast = parseCss.parseAStylesheet(tokens);
|
|
// fs.writeFileSync("parse.css.json", JSON.stringify(ast, null, "\t"));
|
|
});
|
|
const gonzalesDuration = trapDuration(() => {
|
|
const ast = gonzales.srcToCSSP(themeCoreLightIos);
|
|
});
|
|
const parserlibDuration = trapDuration(() => {
|
|
const parser = new parserlib.css.Parser({ starHack: true, underscoreHack: true });
|
|
const ast = parser.parse(themeCoreLightIos);
|
|
});
|
|
const csstreeDuration = trapDuration(() => {
|
|
const ast = csstree.parse(themeCoreLightIos);
|
|
});
|
|
const nativescriptToReworkAstDuration = trapDuration(() => {
|
|
const cssparser = new CSS3Parser(themeCoreLightIos);
|
|
const stylesheet = cssparser.parseAStylesheet();
|
|
const cssNS = new CSSNativeScript();
|
|
const ast = cssNS.parseStylesheet(stylesheet);
|
|
});
|
|
const nativescriptParseDuration = trapDuration(() => {
|
|
const cssparser = new CSS3Parser(themeCoreLightIos);
|
|
const stylesheet = cssparser.parseAStylesheet();
|
|
});
|
|
console.log(` * Baseline perf: .charCodeAt: ${charCodeByCharCodeDuration}ms. .charAt: ${charByCharDuration}ms. []:${indexerDuration}ms. compareCharIf: ${compareCharIfDuration} compareCharRegEx: ${compareCharRegExDuration}`);
|
|
console.log(` * Parsers perf: rework: ${reworkDuration}ms. shady: ${shadyDuration}ms. parse-css: ${parseCssDuration}ms. gonzalesDuration: ${gonzalesDuration} parserlib: ${parserlibDuration} csstree: ${csstreeDuration} nativescript-parse: ${nativescriptParseDuration}ms. nativescriptToReworkAst: ${nativescriptToReworkAstDuration}`);
|
|
assert.isAtMost(nativescriptParseDuration, reworkDuration / 3);
|
|
assert.isAtMost(nativescriptParseDuration, shadyDuration / 1.5);
|
|
});
|
|
});
|
|
});
|
|
});
|