Skip to content

Commit

Permalink
ECMA-402 v1 legacy constructor semantics compromise
Browse files Browse the repository at this point in the history
This patch addresses #57 by allowing certain legacy constructor
patterns to coexist with the new guarantees in ECMA-402 v2, which
allows for a pattern where all internal slots exist from the
beginning of the object's lifetime. The compromise is based on
storing a "real" object inside of a symbol-named property to allow
for object initialization in cases of the
Intl.<constructor>.call(Object.create(Intl.<constructor>) pattern.
Legacy methods have to forward their calls to this "real" object.

This patch specifies the change for Intl.NumberFormat, but an
analogous change would also be needed for Intl.DateTimeFormat and
Intl.Collator. This version is being sent out for review for feedback
from users and implementors. A sample implementation in V8 can
be found at
https://codereview.chromium.org/1828543007
  • Loading branch information
littledan committed Mar 25, 2016
1 parent cfee0ca commit 7e00a59
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
4 changes: 4 additions & 0 deletions spec/intl.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ <h1>The Intl Object</h1>
The Intl object is not a function object. It does not have a [[Construct]] internal method; it is not possible to use the Intl object as a constructor with the *new* operator. The Intl object does not have a [[Call]] internal method; it is not possible to invoke the Intl object as a function.
</p>

<p>
The Intl object has an internal slot, [[FallbackSymbol]], which is a new %Symbol% in the current realm.
</p>

<emu-clause id="sec-constructor-properties-of-the-intl-object">
<h1>Constructor Properties of the Intl Object</h1>

Expand Down
30 changes: 28 additions & 2 deletions spec/numberformat.html
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,25 @@ <h1>ToRawFixed(x, minInteger, minFraction, maxFraction)</h1>
1. Return _m_.
</emu-alg>
</emu-clause>

<emu-clause id="sec-unwrapnumberformat" aoid="UnwrapNumberFormat">
<h1>UnwrapNumberFormat(nf)</h1>
<p>
The UnwrapNumberFormat abstract operation gets the underlying NumberFormat operation
for various methods which implement ECMA-402 v1 semantics for supporting initializing
existing Intl objects.
</p>
<emu-alg>
1. If _nf_ does not have an [[initializedNumberFormat]] internal slot,
1. If ? InstanceofOperator(_nf_, %NumberFormat%),
1. Let _fallback_ be ? RequireObjectCoercible(Get(_nf_, Intl.[[FallbackSymbol]])).
1. If _fallback_ has an [[initializedNumberFormat]] internal slot,
1. Let _nf_ be _fallback_.
1. Else, throw a *TypeError* exception.
1. Else, throw a *TypeError* exception.
1. Return _nf_.
</emu-alg>
</emu-clause>
</emu-clause>

<emu-clause id="sec-intl-numberformat-constructor">
Expand All @@ -346,6 +365,13 @@ <h1>Intl.NumberFormat ([ locales [ , options ]])</h1>

<emu-alg>
1. If NewTarget is *undefined*, let _newTarget_ be the active function object, else let _newTarget_ be NewTarget.
1. Let _this_ be the receiver.
1. NOTE: The following step and nested steps implement legacy compatibility semantics
for ECMA-402 v1. See <a href="https://github.com/tc39/ecma402/issues/57">this bug</a>
for details.
1. If _this_ is not *undefined*, and ? InstanceofOperator(_this_, %NumberFormat%),
1. Perform ? DefineOwnPropertyOrThrow(_this_, Intl.[[FallbackSymbol]], { [[Value]]: Construct(%NumberFormat%, locales, options), [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }).
1. Return _this_.
1. Let _numberFormat_ be ? OrdinaryCreateFromConstructor(_newTarget_, `"%NumberFormatPrototype%"`, « [[initializedIntlObject]], [[initializedNumberFormat]], [[locale]], [[numberingSystem]], [[style]], [[currency]], [[currencyDisplay]], [[minimumIntegerDigits]], [[minimumFractionDigits]], [[maximumFractionDigits]], [[minimumSignificantDigits]], [[maximumSignificantDigits]], [[useGrouping]], [[positivePattern]], [[negativePattern]], [[boundFormat]] »).
1. Return ? InitializeNumberFormat(_numberFormat_, _locales_, _options_).
</emu-alg>
Expand Down Expand Up @@ -457,7 +483,7 @@ <h1>get Intl.NumberFormat.prototype.format</h1>
<emu-alg>
1. Let _nf_ be *this* value.
1. If Type(_nf_) is not Object, throw a *TypeError* exception.
1. If _nf_ does not have an [[initializedNumberFormat]] internal slot, throw a *TypeError* exception.
1. Let _nf_ be ? UnwrapNumberFormat(_nf_);
1. If _nf_.[[boundFormat]] is *undefined*, then
1. Let _F_ be a new built-in function object as defined in Number Format Functions (<emu-xref href="#sec-number-format-functions"></emu-xref>).
1. Let _bf_ be BoundFunctionCreate(_F_, _nf_, « »).
Expand All @@ -471,7 +497,7 @@ <h1>get Intl.NumberFormat.prototype.format</h1>
<h1>Intl.NumberFormat.prototype.resolvedOptions ()</h1>

<p>
This function provides access to the locale and formatting options computed during initialization of the object.
This function provides access to the locale and formatting options computed during initialization of the object. This function initially invokes the internal algorithm UnwrapNumberFormat to get the %NumberFormat% object on which to operate.
</p>
<p>
The function returns a new object whose properties and attributes are set as if constructed by an object literal assigning to each of the following properties the value of the corresponding internal slot of this NumberFormat object (see <emu-xref href="#sec-properties-of-intl-numberformat-instances"></emu-xref>): locale, numberingSystem, style, currency, currencyDisplay, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits, maximumSignificantDigits, and useGrouping. Properties whose corresponding internal slots have the value *undefined* are not assigned.
Expand Down

0 comments on commit 7e00a59

Please sign in to comment.