Stage 1 Draft / April 3, 2018

Extended Numeric Literal (Alternative Proposal)

Introduction

This document describes an alternative to the Extended Numeric Literals proposal. This design's primary goals are to avoid conflict with the Stage 3 Numeric Literal Separator feature and to provide a mechanism that protects extensions from shadowing hazards.

1Properties of the Number Constructor

1.1The Number.extensions Object

The Number.extensions object is the %Number_extensions% intrinsic object and the initial value of the extensions property of the Number object. The Number.extensions object is a single ordinary object.

The value of the [[Prototype]] internal slot of the Number.extensions object is the intrinsic object %ObjectPrototype%.

The Number.extensions object is not a function object. It does not have a [[Construct]] internal method; it is not possible to use the Number.extensions object as a constructor with the new operator. The Number.extensions object also does not have a [[Call]] internal method; it is not possible to invoke the Number.extensions object as a function.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

This object provides functions to interact with the [[NumericExtensionHandlerMap]].

1.1.1Function Properties of the Number.extensions Object

Table 1: Function Properties of the Number.extensions Object
Function Name Behavior
has(extensionKey)

When the has function is called with arguments extensionKey, the following steps are taken:

  1. Let key be ? ToString( extensionKey ).
  2. Assert: key is a String value.
  3. Let realm be the current Realm Record.
  4. Let handlerMap be realm.[[NumericExtensionHandlerMap]].
  5. For each element e of handlerMap, do
    1. If SameValue(e.[[Key]], key) is true, return true.
  6. Return false.
register(extensionKey, handler)

When the register function is called with arguments extensionKey and handler, the following steps are taken:

  1. Let key be ? ToString( extensionKey ).
  2. Assert: key is a String value.
  3. Let realm be the current Realm Record.
  4. Let handlerMap be realm.[[NumericExtensionHandlerMap]].
  5. If IsCallable(handler) is false, throw a TypeError exception.
  6. For each element e of handlerMap, do
    1. If SameValue(e.[[Key]], key) is true, then throw a TypeError exception.
  7. Perform SetIntegrityLevel(handler, "frozen").
  8. Append the Record{[[Key]]: key, [[Handler]]: handler} to handlerMap.
  9. Return undefined.

All methods of this instance have the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

2Syntax

PrimaryExpression[Yield, Await]:this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ExtendedNumericLiteral ExtendedNumericLiteral:NumericLiteral[no LineTerminator here]~Identifier Note
TODO: This grammar needs to be revisited to determine the correct location for definition

3Semantics

3.1Runtime Semantics: Evaluation

ExtendedNumericLiteral:NumericLiteral[no LineTerminator here]~Identifier
  1. Let string be a String Value consisting of the code units of NumericLiteral.
  2. Let number be the result of evaluating NumericLiteral.
  3. Let realm be the current Realm Record.
  4. Let nemcache be realm.[[NumericExtensionMap]].
  5. Let count be the number of elements in nemcache.
  6. Let object be null.
  7. Let done be false.
  8. Let k be 0.
  9. Repeat, while done is false and k < count,
    1. If ! SameValue(nemcache[k][[Key]], string) is true, then
      1. Set object to nemcache[k][[Object]].
      2. Set done to true.
    2. Increment k by 1;
  10. If object is null,
    1. Let object be ! ObjectCreate(null).
    2. Perform ! CreateDataProperty(object, "string", string).
    3. Perform ! CreateDataProperty(object, "number", number).
    4. Perform SetIntegrityLevel(object, "frozen").
    5. Append the Record{[[Key]]: string, [[Object]]: object} to nemcache.
  11. Let extension be the String Value of Identifer.
  12. Let handler be the empty String.
  13. Let handlerMap be realm.[[NumericExtensionHandlerMap]].
  14. For each element e of handlerMap, do
    1. If SameValue(e.[[Key]], extension) is true, then
      1. Set handler to e.[[Handler]].
  15. If handler is empty, throw a TypeError exception.
  16. Return ? Call(undefined, handler, object).

4Realms

Table 2: Realm Record Fields
Field Name Value Meaning
[[NumericExtensionMap]] A List of Record { [[Key]]: String, [[Object]]: Object }. Literal objects are canonicalized separately for each realm using its Realm Record's [[NumericExtensionMap]]. Each [[Key]] value is a String of the source text for the NumericLiteral part of the ExtendedNumericLiteral. The associated [[Object]] value is the corresponding object that is passed to a tag function.
[[NumericExtensionHandlerMap]] A List of Record { [[Key]]: String, [[Handler]]: Function }. Literal objects are canonicalized separately for each realm using its Realm Record's [[NumericExtensionHandlerMap]]. Each [[Key]] value is a String that corresponds to the Identifier part of the ExtendedNumericLiteral. The associated [[Handler]] value is a function that accepts an [[Object]] value (See [[NumericExtensionMap]]) and returns a user-defined value that will be used as the result of evaluating a ExtendedNumericLiteral.

5Well-Known Intrinsic Objects

Table 3: Well-Known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%Number_extensions% Number.extensions The initial value of the extensions data property of %Number% (1.1).