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:
- A tiny IDL-like schema format: interface name, attributes with types, methods with argument
types, plus a
[ForcesLayout]and a[CrossOrigin]marker. - A generator that emits JS accessor definitions from the schema.
- A "C++ side" (plain JS objects standing in) with a wrapper map enforcing identity.
- Type coercion per your schema, including throwing on invalid input.
- A
[ForcesLayout]attribute whose getter runs aflush()— reuse the dirty-marking scheme from mini-browser M3. - 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
- Break wrapper identity — create a new wrapper per access. Show two failures: expandos
vanishing, and
===returning false. Explain which is worse and why. - Remove the world separation — show an "extension" expando becoming visible to "page" code. Write two sentences on what an attacker does with that.
- Layout thrash through a getter — mark an attribute
[ForcesLayout], read it in a loop that also writes. Measure the complexity change. - Live vs static collections — implement both; write the infinite loop; then write the version that terminates and explain the difference precisely.
Debugging Exercise
- In DevTools, profile a loop that reads
offsetWidtheach iteration. Find the layout cost. Then find it again in a Perfetto trace with theblinkcategory, and note which view made it obvious faster. - In the local checkout: pick a Web API, find its
.idl, predict the generated C++ name, then confirm withgit grep. Do this for one attribute and one method. - Find an interface member with
[Unforgeable]. Explain the attack it prevents. - Find an interface member with
[RuntimeEnabled]that is not on by default, and verify with--enable-blink-featureson stock Chrome that the behaviour appears.