tc39 / proposal-structs

JavaScript Structs: Fixed Layout Objects
http://tc39.es/proposal-structs/
624 stars 11 forks source link

Add `unsafe` blocks #32

Closed rbuckton closed 2 months ago

rbuckton commented 2 months ago

This adds unsafe {} blocks as a mechanism to restrict unsafe reads and writes to shared memory to only occur in a Block marked with the unsafe keyword:

shared struct Point {
  x;
  y;
}

const p = new Point();
p.x = 0; // throws
unsafe {
  p.x = 0; // ok
}

An unsafe {} block grants access to unsafe reads and writes to any code lexically scoped within the block, including functions within the block:

function f1(p, x) {
  p.x = x; // will throw 
}

unsafe {
  function f2(p, x) {
    p.x = x; // will succeed
  }

  const p = new Point();
  f1(p, 0); // throws
  f2(p, 0); // ok
}

Neither Reflect nor Proxy handlers distinguish between safe and unsafe reads and writes, so Reflect.get(p, "x") will succeed even when not in an unsafe block.

rbuckton commented 2 months ago

lgtm for the spec draft, though I'm curious why the preference for two new MOP operations instead of adding a 3rd parameter to [[Get]] and [[Set]]? They should be equivalent, right?

This was something that was discussed on Matrix at one point as a way to ensure that runtimes don't have to pay a heavy cost for every [[Get]]/[[Set]], by only bifurcating [[Get]]/[[Set]] behavior when inside of an unsafe {} block. I'm perfectly happy to refactor it to a 3rd parameter since runtimes can choose whatever implementation they want so long as observable semantics don't change.