Rename classname attr; update bench results; mention decoding to U+FFFD

This commit is contained in:
Wilson Lin 2020-01-15 22:57:47 +11:00
parent f8b0bbe3e0
commit 4eeb70639a
10 changed files with 92 additions and 92 deletions

View File

@ -313,6 +313,8 @@ Spaces are removed between attributes if possible.
### Entities
Entities are decoded if valid (see relevant parsing section) and their decoded characters as UTF-8 is shorter or equal in length.
Numeric entities that do not refer to a valid Unicode Scalar Value are decoded to U+FFFD REPLACEMENT CHARACTER.
If an entity is unintentionally formed after decoding, the leading ampersand is encoded, e.g. `&` becomes `&ampamp;`. This is done as `&amp` is equal to or shorter than all other entity representations of characters part of an entity (`[&#a-zA-Z0-9;]`), and there is no other conflicting entity name that starts with `amp`.

View File

@ -1,10 +1,14 @@
const benchmark = require('benchmark');
const childProcess = require('child_process');
const fs = require('fs');
const minimist = require('minimist');
const path = require('path');
const programs = require('./minifiers');
const tests = require('./tests');
const args = minimist(process.argv.slice(2));
const shouldRunRust = !!args.rust;
const cmd = (command, ...args) => {
const throwErr = msg => {
throw new Error(`${msg}\n ${command} ${args.join(' ')}`);
@ -83,15 +87,17 @@ const runTest = test => new Promise((resolve, reject) => {
});
(async () => {
const results = {};
const results = fromEntries(tests.map(t => [t.name, {}]));
// Run Rust library.
for (const [testName, testOps] of JSON.parse(cmd(
path.join(__dirname, 'hyperbuild-bench', 'target', 'release', 'hyperbuild-bench'),
'--iterations', 512,
'--tests', path.join(__dirname, 'tests'),
))) {
results[testName] = {hyperbuild: testOps};
if (shouldRunRust) {
for (const [testName, testOps] of JSON.parse(cmd(
path.join(__dirname, 'hyperbuild-bench', 'target', 'release', 'hyperbuild-bench'),
'--iterations', 512,
'--tests', path.join(__dirname, 'tests'),
))) {
Object.assign(results[testName], {hyperbuild: testOps});
}
}
for (const t of tests) {

View File

@ -5,8 +5,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 353050,
"relative": 0.9619497840687711
"absolute": 351742,
"relative": 0.9583858970341812
},
"html-minifier": {
"absolute": 351955,
@ -23,8 +23,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 231552,
"relative": 0.9424943015304461
"absolute": 231431,
"relative": 0.9420017909475741
},
"html-minifier": {
"absolute": 233884,
@ -41,8 +41,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 89811,
"relative": 0.9843164332215427
"absolute": 89717,
"relative": 0.9832862059139431
},
"html-minifier": {
"absolute": 89834,
@ -59,8 +59,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 271254,
"relative": 0.8757417463566453
"absolute": 271218,
"relative": 0.8756255205945593
},
"html-minifier": {
"absolute": 270355,
@ -77,8 +77,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 79875,
"relative": 0.9438365552772132
"absolute": 79832,
"relative": 0.9433284492130264
},
"html-minifier": {
"absolute": 79273,
@ -95,8 +95,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 5719969,
"relative": 0.9055757965508457
"absolute": 5719864,
"relative": 0.9055591731288241
},
"html-minifier": {
"absolute": 5663106,
@ -113,8 +113,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 196435,
"relative": 0.9969093197458435
"absolute": 196337,
"relative": 0.9964119689003471
},
"html-minifier": {
"absolute": 196322,
@ -131,8 +131,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 28949,
"relative": 0.8393204024238207
"absolute": 28661,
"relative": 0.8309703980748601
},
"html-minifier": {
"absolute": 28593,
@ -149,8 +149,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 941143,
"relative": 0.9956867184359197
"absolute": 940973,
"relative": 0.9955068661264045
},
"html-minifier": {
"absolute": 940656,
@ -167,8 +167,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 668280,
"relative": 0.994633018101285
"absolute": 668097,
"relative": 0.99436065046749
},
"html-minifier": {
"absolute": 667808,
@ -185,8 +185,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 86850,
"relative": 0.7735953254711939
"absolute": 86801,
"relative": 0.7731588698471514
},
"html-minifier": {
"absolute": 86422,
@ -203,8 +203,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 273313,
"relative": 0.8649474030659392
"absolute": 273258,
"relative": 0.8647733458232592
},
"html-minifier": {
"absolute": 265976,
@ -221,8 +221,8 @@
"relative": 1
},
"hyperbuild-nodejs": {
"absolute": 1342122,
"relative": 0.9510804978900262
"absolute": 1319364,
"relative": 0.9349532829490736
},
"html-minifier": {
"absolute": 1308864,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -7,6 +7,7 @@
"html-minifier": "3.5.19",
"hyperbuild": "file:../nodejs",
"minimize": "2.2.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"request": "^2.88.0",
"request-promise-native": "^1.0.8"

View File

@ -1,80 +1,67 @@
{
"Amazon.html": {
"hyperbuild": 465.50245835303156,
"hyperbuild-nodejs": 455.0487568010082,
"html-minifier": 42.132362101867265,
"minimize": 114.1876564245339
"hyperbuild-nodejs": 453.9446367209197,
"html-minifier": 42.41045313663229,
"minimize": 114.74500577302787
},
"BBC.html": {
"hyperbuild": 487.9227758294946,
"hyperbuild-nodejs": 469.00501299771,
"html-minifier": 45.539082044496425,
"minimize": 142.67976760586086
},
"Bootstrap.html": {
"hyperbuild": 211.4224043526581,
"hyperbuild-nodejs": 212.90708528176216,
"html-minifier": 9.185406543150869,
"minimize": 23.327303724107708
"hyperbuild-nodejs": 471.95373182009035,
"html-minifier": 44.62434122645009,
"minimize": 143.76941073868343
},
"Bing.html": {
"hyperbuild": 2048.4087148940653,
"hyperbuild-nodejs": 1994.5824867881042,
"html-minifier": 227.72432719779127,
"minimize": 546.3653509215457
"hyperbuild-nodejs": 1983.283549298642,
"html-minifier": 224.4254863951391,
"minimize": 547.4731257876035
},
"Bootstrap.html": {
"hyperbuild-nodejs": 207.1001839706425,
"html-minifier": 9.155727796452659,
"minimize": 23.405526541070603
},
"Coding Horror.html": {
"hyperbuild": 1026.0665966280021,
"hyperbuild-nodejs": 1002.065473186622,
"html-minifier": 57.63675661339994,
"minimize": 188.64083891044802
"hyperbuild-nodejs": 1009.9271101767229,
"html-minifier": 58.570673337738285,
"minimize": 192.6296247484631
},
"ECMA-262.html": {
"hyperbuild": 12.86713855992782,
"hyperbuild-nodejs": 12.477324823911884,
"html-minifier": 0.5195474427689735,
"minimize": 1.3164929278223723
"hyperbuild-nodejs": 12.651620170239344,
"html-minifier": 0.5175151408492638,
"minimize": 1.3331944009226142
},
"Google.html": {
"hyperbuild": 1883.669674755918,
"hyperbuild-nodejs": 1756.2993142315204,
"html-minifier": 332.19134317308385,
"minimize": 580.4716141570754
"hyperbuild-nodejs": 1755.84144550864,
"html-minifier": 327.57989037094177,
"minimize": 559.7413104037764
},
"Hacker News.html": {
"hyperbuild": 1722.167784079985,
"hyperbuild-nodejs": 1688.259096611799,
"html-minifier": 87.14413060022541,
"minimize": 271.02689069188085
"hyperbuild-nodejs": 1698.4814577832713,
"html-minifier": 86.84874410099094,
"minimize": 272.4655268930861
},
"NY Times.html": {
"hyperbuild": 322.3939564734156,
"hyperbuild-nodejs": 303.0917508322731,
"html-minifier": 41.90685076570727,
"minimize": 104.3222139613737
"hyperbuild-nodejs": 303.09869941070536,
"html-minifier": 42.081296690280986,
"minimize": 105.9439759928125
},
"Reddit.html": {
"hyperbuild": 365.45195046927216,
"hyperbuild-nodejs": 347.2682176821133,
"html-minifier": 44.22015518636509,
"minimize": 118.24035770803926
"hyperbuild-nodejs": 347.3501992232369,
"html-minifier": 43.965316436512296,
"minimize": 119.53066163219651
},
"Stack Overflow.html": {
"hyperbuild": 717.9290791655839,
"hyperbuild-nodejs": 701.7259205288996,
"html-minifier": 49.142772908926695,
"minimize": 157.39557262183592
"hyperbuild-nodejs": 699.0528884626148,
"html-minifier": 48.9868522505873,
"minimize": 158.237902766563
},
"Twitter.html": {
"hyperbuild": 268.6410506444874,
"hyperbuild-nodejs": 251.62962766725312,
"html-minifier": 42.17252196756126,
"minimize": 164.92088297175664
"hyperbuild-nodejs": 261.0846884406236,
"html-minifier": 41.807088664465276,
"minimize": 165.579606845361
},
"Wikipedia.html": {
"hyperbuild": 47.84321953380644,
"hyperbuild-nodejs": 46.509118305923565,
"html-minifier": 3.1796252429460234,
"minimize": 8.686220803188926
"hyperbuild-nodejs": 47.35485721052862,
"html-minifier": 3.1776064565607642,
"minimize": 8.735035310526898
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -27,6 +27,10 @@ const attrInterfaceToTagName = {
'anchor': 'a',
};
const attrNameNormalised = {
'classname': 'class',
};
const reactSpecificAttributes = [
'defaultChecked', 'defaultValue', 'suppressContentEditableWarning', 'suppressHydrationWarning',
];
@ -46,7 +50,7 @@ const processReactTypeDeclarations = async (source) => {
if (!['all', 'webview'].includes(tagName)) {
for (const n of node.members.filter(n => n.kind === ts.SyntaxKind.PropertySignature)) {
// TODO Is escapedText the API for getting name?
const attr = n.name.escapedText.toLowerCase();
const attr = [n.name.escapedText.toLowerCase()].map(n => attrNameNormalised[n] || n)[0];
const types = n.type.kind === ts.SyntaxKind.UnionType
? n.type.types.map(t => t.kind)
: [n.type.kind];

View File

@ -63,12 +63,12 @@
"ins",
"quote"
],
"class": [
""
],
"classid": [
"object"
],
"classname": [
""
],
"color": [
""
],

View File

@ -55,7 +55,7 @@ fn parse_numeric(proc: &mut Processor, skip_amount: usize, max_len: usize, digit
proc.skip_amount_expect(skip_amount);
// This is required because leading zeros do not count towards digit limit.
let has_leading_zeros = chain!(proc.match_while_char(b'0').discard().matched());
// Browser actually consumes unlimited amount of digits, but decodes to 0xFFFD if not a valid Unicode scalar value.
// Browser actually consumes unlimited amount of digits, but decodes to 0xFFFD if not a valid Unicode Scalar Value.
// UnintentionalEntityState (UES) encodes leading ampersand in any sequence matching /&#x?\d/. This means that we need to be careful in keeping malformed behaviour consistent between this function and UES methods.
// For example, if we simply output the entity literally, it will be interpreted as an unintentional entity by UEP and cause the written output to be shifted down to make room for inserting `amp`, which could lead to overwriting source code. This is because this function considers the entity as malformed whereas UEP doesn't and encodes the `&`.
// Currently, since browsers decode to a replacement character (U+FFFD) if malformed, we'll simply decode to that, which won't trigger any UEP encoding behaviour.