Open ghost opened 7 years ago
Regarding your first example (updated to current syntax):
let ref accessor = typecounters[0];
let index = Atomics.add(...accessor, 1);
This would fail because accessor
is a Reference
type, and Reference
does not have a Symbol.iterator
method. A Reference
is opaque with respect to its base value, you can't get back typecounters
from accessor
.
I'm not sure I understand your second point.
I think what @ghost want could be something like
let accessor = ref typecounters[0]
let index = Atomics.add(...accessor, 1)
Aka, make ref expression create a Reference object with accessor[0] === typecounters
and accessors[1] === '0'
.
Theoretically it seems we could directly support using array:
const a = [1]
let ref a0 = [a, 0]
a0 // 1
++a0 // 2
a // [2]
I'm concerned that exposing the this
binding could possibly leak sensitive internals and could be a security vulnerability when working with untrusted code in a sandbox. I do not believe the suggestion above is a viable option. However, if ref
is added to the language, it could be feasible to have a variant of Atomics.add
that can accept a ref
to a typed array that could have privileged access to the underlying this
binding, i.e. Atomics.add(ref typecounters[0], 1)
.
@ghost regarding your second point:
Also, I suggest change behavior of
ref
.
ref
should refers to left value, not right value.let objvar = object; let objref = objvar; ref leftref = objvar;
objvar = anotherObject;
// objref != objvar // because reference directly with object // leftref == objvar // because left-value reference
I disagree. There are multiple possible operations we need to be able to perform:
Reference
object (this is necessary for the decorators case in the explainer due to TDZ and circular module dependencies):
ref x
ref o.x
ref ar[0]
Reference
into a variable binding that essentially acts like that variable (i.e. reading/writing to the variable reads/writes to the underlying reference):
let ref y = ...
ref y = ...
(ref y) => { ... }
This results in a matrix of operations:
let x = a; // `x` is a new binding with the value of `a`
let r = ref a; // `r` is a new binding whose value is a `Reference` object referring to `a`.
let ref z = r; // `z` is a new binding linked to the underlying binding of `r`.
let ref y = ref a; // `y` is a new binding linked to the same binding as `a`.
// also
ref z = r; // `z` is linked to the underlying binding of the `Reference` `r`.
ref y = ref a; // `y` linked to the same binding as `a`.
function f(ref p) {}
f(r); // parameter `p` in `f` is linked to the underlying binding of `r`.
f(ref a); // parameter `p` in `f` is linked to the same binding as `a`.
Therefore:
ref
on the left-hand side of an assignment, or as part of the declaration of a variable, parameter, or binding element, dereferences the value on the right-hand side into a variable.ref
on the right-hand side (or on its own) references the binding of its operand (which must be a variable, property access, or indexed access).So your example above, following these rules, would be this:
let objvar = object;
let objref = objvar;
let ref leftref = ref objvar; // take reference to `objvar` and dereference it as `leftref`.
objvar = anotherObject;
// objref != objvar // because reference directly with object
// leftref == objvar // because left-value reference
I'm interseting. If I ref to object or array members, how I can to pass to old functions through spreads?
Also, I suggest change behavior of
ref
.ref
should refers to left value, not right value.