Closed bzbarsky closed 5 years ago
I'm also confused why "it performs brand checks" would affect anything; I'd expect to be able to get the original of anything - whether to get a brand checker, or only to obtain the original optimized behavior after it's been replaced.
Hmm, yeah, I guess we should probably allow this. Although it's not strictly necessary, since the non-brand-checking methods don't use any magic internal slots, and so can be emulated with author code.
The reason for the brand check restriction was that, if you just do getOriginalProperty(nonBrandedObject, "foo")
, the implementation has no idea what nonBrandedObject
is, and so can't look up its original "foo"
method.
Not sure how to solve this.
Are there non-branded things with spec-defined prototypes other than Arrays?
Object
, I guess? Although that barely counts.
https://streams.spec.whatwg.org/#blqs-class and https://streams.spec.whatwg.org/#cqs-class are the other examples I can think of. Definitely starting to regret not doing streams in Web IDL :-/. They're trivial though, and mostly used for communicating intent; any usage of them could be replaced with a one-liner.
Also Error, prior to the stacks proposal landing.
I think it would simplify the mental model greatly if this could be used to get any "original".
How?
Because then consumers of this “get originals” feature wouldn’t have to memorize which things have brand checks and which do not.
No, I meant, how would you do that? Given getOriginalProperty(nonBrandedObject, "foo")
, there's no way to figure out what the original method is.
Presumably the engine could retain a weak map that has the object as a key and a map of original methods as the value - but I’m sure there’s tons of ways to implement it, that’s just what occurs to me.
I don't think slowing down every object produced by the engine by making it a weak map key is feasible.
Can you elaborate how that “slows down” anything?
Tracking objects as weak map keys in the garbage collector is not free; it puts them on a very different path from normal objects, which requires more processing and tracking of their lifetimes so that associated data (such as the weak map itself) can get its lifetime appropriately entangled with the key.
Hmm - so you're saying that this cost would apply to any value made available via this proposal, and so there's some value in minimizing the number of those objects?
No, it applies to anything you put in a weak map to compensate for its lack of existing brand.
Without a weak map (or any equivalent concept), how would the implementation hold on to the original values of branded objects, that's different from how it'd hold on to unbranded objects?
Roughly speaking, those functions already exist in memory. The brand is then used to look up the place in memory where they are, so that you can call them.
Unbranded functions already exist in memory too, do they not?
Yes. What's missing is the brand, to look them up when given a target object.
Sorry to keep going back and forth on this, but I'm still not clear why holding on to Array.prototype.slice
is any different than holding on to String.prototype.toString
:-/
That's not the hard part. The hard part is knowing that the function you want is Array.prototype.slice, because in spec terms you can't really tell apart an array from any other object. Except by examining its internal methods, of course.
It's worse for Error instances; those don't even have interesting internal methods in the spec, so in spec terms they're just like Object instances with a different prototype.
Of course in implementations that's not how it actually works.
The language for
callOriginalMethod
says that the target can be "Any of the classes defined in the JavaScript specification which perform brand checks". But as far as I know Array does not perform any brand checks... There's a concept of "Array exotic object", but the only thing that checks that concept is Array.isArray.