> I guess what confused me is that it would detect a [[NumberData]] internal slot, but instead of unboxing to that value it tries to ducktype call .valueOf on the object. So the presence of [[NumberData]] changes the behavior even if it does not actually use this value.
This surprised me too initially, but I think we can infer a rationale if we read between the lines a bit. A similar pattern appears in the JSON stringify algorithm itself (as opposed to the SerializeJSONProperty algorithm) when interpreting the "space" argument. So it might seem to be that it’s a peculiarity of how JSON-related operations are defined — but I don’t think that’s the pattern. What these two cases have in common is that either a numeric value or a string value would be valid: neither hint would be more correct. In the case of SerializeJSONProperty, this is because both string values and numeric values are valid JSON values; in the case of stringify’s space argument, it’s because this is overloaded to either specify a number of spaces or a whitespace string. In the absence of a reason to weight one to-primitive operation over another, it sniffs for the singular unambiguous clue about type that’s really available, the slot. Why doesn’t it then just use the slot value directly? Because this would depart from expectations about the @@toPrimitive / toValue / toString contract that is honored everywhere else, I believe. On Sun, Aug 5, 2018 at 12:30 AM Michael Theriot < michael.lee.ther...@gmail.com> wrote: > Regarding cases like Reflect.construct(Number, [], String), the reason >> this throws is because the ToNumber algorithm calls ToPrimitive if its >> operand is an object. This in turn will call String.prototype.valueOf on >> the object which does not have [[StringData]]. There’s nothing funny going >> on, it’s just a weird effect in aggregate. You would just need to implement >> all the steps here — internal ops like ToNumber, ToPrimitive, etc. It’s not >> that it "considers type", but rather that these algorithms will call >> methods by specific names on objects they receive. String.prototype and >> Object.prototype both implement "valueOf", but only the former will fail >> the slot check. >> > > Thanks for demystifying this. I never realized it was just ducktyping > .valueOf on the object. > > ```js > Number.prototype.valueOf = () => 0; > > JSON.stringify(1); // 1 > JSON.stringify(new Number(1)); // 0 > ``` > > I guess what confused me is that it would detect a [[NumberData]] internal > slot, but instead of unboxing to that value it tries to ducktype call > .valueOf on the object. So the presence of [[NumberData]] changes the > behavior even if it does not actually use this value. > > On Sat, Aug 4, 2018 at 10:14 PM Darien Valentine <valentin...@gmail.com> > wrote: > >> Is this a question about how/if one could replicate its behavior in >> theory from ES code, or are you suggesting a change to the existing >> behavior for these exotic cases? >> >> Assuming the former: >> >> The relevant steps are [here]( >> https://tc39.github.io/ecma262/#sec-serializejsonproperty). The >> `instanceof` a value isn’t significant in this algorithm, just its slots >> (if it is an object) or its primitive type. So one can handle number and >> string by leveraging branded checks as you’ve shown — nothing more is >> needed than branded methods and typeof to manage that one. >> >> However it is ultimately not possible to replicate because there is no >> possible brand test for [[BooleanData]]. >> _______________________________________________ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss