Execution — bi-05-bindings-v8

Steps extracted from CONCEPTS.md. Read the concepts first; this file is the doing.

Record results in observation.md; tick checkpoints in verification.md.


Lab

Mini-binding layer. Build a toy that demonstrates the boundary rather than reimplementing V8:

  1. A tiny IDL-like schema format: interface name, attributes with types, methods with argument types, plus a [ForcesLayout] and a [CrossOrigin] marker.
  2. A generator that emits JS accessor definitions from the schema.
  3. A "C++ side" (plain JS objects standing in) with a wrapper map enforcing identity.
  4. Type coercion per your schema, including throwing on invalid input.
  5. A [ForcesLayout] attribute whose getter runs a flush() — reuse the dirty-marking scheme from mini-browser M3.
  6. Two worlds: two wrapper maps over the same backing objects. Demonstrate that expandos do not leak between them.

Then measure: property access through your wrapper vs a plain JS property, over 1e6 iterations. Explain the gap in terms of the four costs above.


Failure Lab

  1. Break wrapper identity — create a new wrapper per access. Show two failures: expandos vanishing, and === returning false. Explain which is worse and why.
  2. Remove the world separation — show an "extension" expando becoming visible to "page" code. Write two sentences on what an attacker does with that.
  3. Layout thrash through a getter — mark an attribute [ForcesLayout], read it in a loop that also writes. Measure the complexity change.
  4. Live vs static collections — implement both; write the infinite loop; then write the version that terminates and explain the difference precisely.

Debugging Exercise

  1. In DevTools, profile a loop that reads offsetWidth each iteration. Find the layout cost. Then find it again in a Perfetto trace with the blink category, and note which view made it obvious faster.
  2. In the local checkout: pick a Web API, find its .idl, predict the generated C++ name, then confirm with git grep. Do this for one attribute and one method.
  3. Find an interface member with [Unforgeable]. Explain the attack it prevents.
  4. Find an interface member with [RuntimeEnabled] that is not on by default, and verify with --enable-blink-features on stock Chrome that the behaviour appears.