jsdom / webidl2js

Auto-generate JS class structures for Web IDL specifications
MIT License
79 stars 30 forks source link

Use `[[Unforgeables]]` object for unforgeable properties #226

Closed ExE-Boss closed 3 years ago

ExE-Boss commented 4 years ago

This makes it so that:

console.assert(new Event("foo").__lookupGetter__("isTrusted") === new Event("bar").__lookupGetter__("isTrusted"));

Which passes in browsers.

See also:

create an interface object
> 5. Let unforgeables be [!] [OrdinaryObjectCreate]\(null\). > 6. [Define the unforgeable regular operations] of I on unforgeables, given realm. > 7. [Define the unforgeable regular attributes] of I on unforgeables, given realm. > 8. Set F.[[Unforgeables]] to unforgeables.
internally create a new object implementing the interface
> 9. [For every] [interface] ancestor interface in interfaces:
  1. Let unforgeables be the value of the [[Unforgeables]] slot of the [interface object] of ancestor interface in realm.
  2. Let keys be [!] unforgeables.[[OwnPropertyKeys]]\(\).
  3. [For each] element key of keys:
    1. Let descriptor be [!] unforgeables.[[GetOwnProperty]]\(key\).
    2. Perform [!] [DefinePropertyOrThrow]\(instance, key, descriptor\).

JSDOM benchmark results

| benchmark | `master` | `fix/ext-attr/legacy-unforgeable/use-unforgeables-object` | --------- | -------- | --------------------------------------------------------- | dom/compare-document-position/compare ancestor | jsdom × 31,680 ops/sec ±3.33% (8 runs sampled) | jsdom × 31,039 ops/sec ±4.80% (9 runs sampled) | dom/compare-document-position/compare descendant | jsdom × 33,229 ops/sec ±4.04% (10 runs sampled) | jsdom × 31,615 ops/sec ±5.98% (10 runs sampled) | dom/compare-document-position/compare siblings | jsdom × 1,092,845 ops/sec ±1.22% (11 runs sampled) | jsdom × 1,043,994 ops/sec ±1.51% (12 runs sampled) | dom/construction/createComment | jsdom × 1,301,196 ops/sec ±1.76% (94 runs sampled) | jsdom × 1,445,954 ops/sec ±1.76% (92 runs sampled) | dom/construction/createDocumentFragment | jsdom × 1,178,947 ops/sec ±0.53% (96 runs sampled) | jsdom × 1,320,875 ops/sec ±0.84% (93 runs sampled) | dom/construction/createElement | jsdom × 283,346 ops/sec ±0.21% (95 runs sampled) | jsdom × 283,587 ops/sec ±0.67% (94 runs sampled) | dom/construction/createEvent | jsdom × 206,199 ops/sec ±1.61% (93 runs sampled) | jsdom × 381,336 ops/sec ±0.76% (93 runs sampled) | dom/construction/createNodeIterator | jsdom × 1,326,075 ops/sec ±0.61% (94 runs sampled) | jsdom × 1,478,440 ops/sec ±0.79% (95 runs sampled) | dom/construction/createProcessingInstruction | jsdom × 664,399 ops/sec ±0.70% (94 runs sampled) | jsdom × 658,141 ops/sec ±2.20% (90 runs sampled) | dom/construction/createTextNode | jsdom × 1,042,538 ops/sec ±0.68% (92 runs sampled) | jsdom × 1,180,503 ops/sec ±1.91% (90 runs sampled) | dom/inner-html/tables | jsdom × 0.31 ops/sec ±3.76% (5 runs sampled) | jsdom × 0.30 ops/sec ±2.46% (5 runs sampled) | dom/named-properties/setAttribute(): Remove a named property from window | jsdom × 2,465 ops/sec ±0.52% (58 runs sampled) | jsdom × 2,283 ops/sec ±1.15% (55 runs sampled) | dom/tree-modification/appendChild: many parents | jsdom × 26.99 ops/sec ±1.15% (47 runs sampled) | jsdom × 25.85 ops/sec ±0.56% (45 runs sampled) | dom/tree-modification/appendChild: many siblings | jsdom × 246,844 ops/sec ±9.27% (18 runs sampled) | jsdom × 242,924 ops/sec ±8.88% (19 runs sampled) | dom/tree-modification/appendChild: no siblings | jsdom × 227,547 ops/sec ±4.73% (28 runs sampled) | jsdom × 217,066 ops/sec ±7.04% (29 runs sampled) | dom/tree-modification/insertBefore: many siblings | jsdom × 213,163 ops/sec ±11.42% (18 runs sampled) | jsdom × 213,551 ops/sec ±8.32% (18 runs sampled) | dom/tree-modification/removeChild: many parents | jsdom × 122 ops/sec ±1.00% (63 runs sampled) | jsdom × 117 ops/sec ±1.01% (60 runs sampled) | dom/tree-modification/removeChild: many siblings | jsdom × 152,153 ops/sec ±6.38% (40 runs sampled) | jsdom × 157,846 ops/sec ±6.10% (38 runs sampled) | dom/tree-modification/removeChild: no siblings | jsdom × 141,264 ops/sec ±8.47% (32 runs sampled) | jsdom × 148,015 ops/sec ±7.62% (28 runs sampled) | html/parsing/text | jsdom × 15.77 ops/sec ±1.75% (43 runs sampled) | jsdom × 15.93 ops/sec ±1.53% (44 runs sampled) | jsdom/api/new JSDOM() defaults | <Test #⁠10> × 290 ops/sec ±2.77% (78 runs sampled) | <Test #⁠10> × 291 ops/sec ±2.89% (80 runs sampled) | jsdom/api/new JSDOM() with many elements | <Test #⁠11> × 29.79 ops/sec ±4.19% (54 runs sampled) | <Test #⁠11> × 29.39 ops/sec ±5.70% (54 runs sampled)
domenic commented 4 years ago

This is an extraordinarily large increase in code size (both generated and webidl2js) for a very minor correctness improvement. I'd prefer to find a way to do this that wasn't so disruptive.

ExE-Boss commented 4 years ago

The generated code size is only a total increase of +12 lines per file, see #226?w=1 for evidence.


And most of the WebIDL2JS code is duplicated from genereateOnInstance and generateOffInstance, which could possibly use some refactoring into a common method for iterating over this._outputMethods.