diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..68afe9b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,15 @@ +name: Build spec + +on: [pull_request, push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: ljharb/actions/node/install@main + name: 'nvm install lts/* && npm install' + with: + node-version: lts/* + - run: npm run build diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..9d042e2 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,23 @@ +name: Deploy gh-pages + +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: ljharb/actions/node/install@main + name: 'nvm install lts/* && npm install' + with: + node-version: lts/* + - run: npm run build + - uses: JamesIves/github-pages-deploy-action@v4.3.3 + with: + branch: gh-pages + folder: build + clean: true diff --git a/.gitignore b/.gitignore index fd18f10..697c2b9 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,6 @@ package-lock.json npm-shrinkwrap.json # Emacs droppings -*~ \ No newline at end of file +*~ + +build diff --git a/index.html b/index.html deleted file mode 100644 index da1b734..0000000 --- a/index.html +++ /dev/null @@ -1,1895 +0,0 @@ - - - - - -Array.isTemplateObject

Stage 2 Draft / January 12, 2021

Array.isTemplateObject

- -

Changes to ArrayCreate

- -

To enable the new API, this proposal modifies ArrayCreate to add an internal slot to each array.

- - -

1 ArrayCreate ( length [ , proto ] )

-

The abstract operation ArrayCreate takes argument length (a non-negative integer) and optional argument proto. It is used to specify the creation of new Array exotic objects. It performs the following steps when called:

-
  1. If length > 232 - 1, throw a RangeError exception.
  2. If proto is not present, set proto to %Array.prototype%.
  3. Let A be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[TemplateObject]] »).
  4. Set A.[[Prototype]] to proto.
  5. Set A.[[TemplateObject]] to false.
  6. Set A.[[DefineOwnProperty]] as specified in 9.4.2.1.
  7. Perform ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
  8. Return A.
-
- - -

Changes to GetTemplateObject

- -

To enable the new API, this proposal modifies GetTemplateObject to change the value of the new internal slot.

- - -

2 Runtime Semantics: GetTemplateObject ( templateLiteral )

-

The abstract operation GetTemplateObject is called with a Parse Node, templateLiteral, as an argument. It performs the following steps:

-
  1. Let realm be the current Realm Record.
  2. Let templateRegistry be realm.[[TemplateMap]].
  3. For each element e of templateRegistry, do
    1. If e.[[Site]] is the same Parse Node as templateLiteral, then
      1. Return e.[[Array]].
  4. Let rawStrings be TemplateStrings of templateLiteral with argument true.
  5. Let cookedStrings be TemplateStrings of templateLiteral with argument false.
  6. Let count be the number of elements in the List cookedStrings.
  7. Assert: count ≤ 232 - 1.
  8. Let template be ! ArrayCreate(count).
  9. Set template.[[TemplateObject]] to true.
  10. Let rawObj be ! ArrayCreate(count).
  11. Let index be 0.
  12. ...
- - -

New APIs

- -

This adds a builtin static method to Array to allow distinguishing template string literal objects

- -

Added under - Properties of the Array Constructor: -

- - -

3 Array.isTemplateObject ( value )

- -

When the isTemplateObject method is called with argument value the following steps are taken:

- -
  1. If IsArray(value) is true and value.[[TemplateObject]] is true then
    1. Return true.
  2. Return false.
- - Note
-

IsTemplateObject is realm-agnostic. Since template objects are frozen before - escaping GetTemplateObject, testing (IsTemplateObject(x) and x.[[Prototype]] - is the realm's %ArrayPrototype%) is sufficient to determine whether an x is - a template object in a particular realm.

-

In user code, Array.isTemplateObject(x) && x instanceof Array is an equivalent - test, assuming no changes to builtins.

-
-
-
\ No newline at end of file diff --git a/package.json b/package.json index 60020ba..98c2ea5 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,13 @@ { "private": true, "name": "proposal-array-is-template-object", - "version": "1.0.0", - "description": "npm, I just want to run some tests", + "version": "0.0.0", + "description": "", "main": "index.js", "scripts": { - "build": "ecmarkup spec.emu index.html", + "start": "npm run build-loose -- --watch", + "build": "npm run build-loose -- --strict", + "build-loose": "node -e 'fs.mkdirSync(\"build\", { recursive: true })' && ecmarkup --load-biblio @tc39/ecma262-biblio --verbose spec.emu build/index.html --lint-spec", "test": "mocha", "precommit": "npm run build && npm run test" }, @@ -20,8 +22,9 @@ }, "homepage": "https://github.com/tc39/proposal-array-is-template-object#readme", "devDependencies": { + "@tc39/ecma262-biblio": "^2.1.2730", "chai": "^4.2.0", - "ecmarkup": "^3.16.0", + "ecmarkup": "^18.3.1", "is-template-object": "^1.0.0", "mocha": "^6.1.4" } diff --git a/spec.emu b/spec.emu index 8c9cd23..4c2639b 100644 --- a/spec.emu +++ b/spec.emu @@ -7,80 +7,136 @@ title: Array.isTemplateObject stage: 2 copyright: false -contributors: Mike Samuel, Krzysztof Kotowicz +contributors: Mike Samuel, Krzysztof Kotowicz, Jordan Harband, Daniel Ehrenberg -

Changes to ArrayCreate

- -

To enable the new API, this proposal modifies ArrayCreate to add an internal slot to each array.

- - -

ArrayCreate ( _length_ [ , _proto_ ] )

-

The abstract operation ArrayCreate takes argument _length_ (a non-negative integer) and optional argument _proto_. It is used to specify the creation of new Array exotic objects. It performs the following steps when called:

- - 1. If _length_ > 232 - 1, throw a *RangeError* exception. - 1. If _proto_ is not present, set _proto_ to %Array.prototype%. - 1. Let _A_ be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[TemplateObject]] »). - 1. Set _A_.[[Prototype]] to _proto_. - 1. Set _A_.[[TemplateObject]] to *false*. - 1. Set _A_.[[DefineOwnProperty]] as specified in . - 1. Perform ! OrdinaryDefineOwnProperty(_A_, *"length"*, PropertyDescriptor { [[Value]]: 𝔽(_length_), [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false* }). - 1. Return _A_. - -
+ +

Ordinary and Exotic Objects Behaviours

+ + +

Built-in Exotic Object Internal Methods and Slots

+ + +

Array Exotic Objects

+ +

+ ArrayCreate ( + _length_: a non-negative integer, + optional _proto_: an Object, + ): either a normal completion containing an Array exotic object or a throw completion +

+
+
description
+
It is used to specify the creation of new Arrays.
+
skip global checks
+
true
+
-

Changes to GetTemplateObject

- -

To enable the new API, this proposal modifies GetTemplateObject to change the value of the new internal slot.

- - -

Runtime Semantics: GetTemplateObject ( _templateLiteral_ )

-

The abstract operation GetTemplateObject is called with a Parse Node, _templateLiteral_, as an argument. It performs the following steps:

- - 1. Let _realm_ be the current Realm Record. - 1. Let _templateRegistry_ be _realm_.[[TemplateMap]]. - 1. For each element _e_ of _templateRegistry_, do - 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then - 1. Return _e_.[[Array]]. - 1. Let _rawStrings_ be TemplateStrings of _templateLiteral_ with argument *true*. - 1. Let _cookedStrings_ be TemplateStrings of _templateLiteral_ with argument *false*. - 1. Let _count_ be the number of elements in the List _cookedStrings_. - 1. Assert: _count_ ≤ 232 - 1. - 1. Let _template_ be ! ArrayCreate(_count_). - 1. Set _template_.[[TemplateObject]] to *true*. - 1. Let _rawObj_ be ! ArrayCreate(_count_). - 1. Let _index_ be 0. - 1. ... + To enable the new API, this proposal modifies ArrayCreate to add an internal slot to each array. + + + 1. If _length_ > 232 - 1, throw a *RangeError* exception. + 1. If _proto_ is not present, set _proto_ to %Array.prototype%. + 1. Let _A_ be MakeBasicObject(« [[Prototype]], [[Extensible]], [[TemplateObject]] »). + 1. Set _A_.[[Prototype]] to _proto_. + 1. Set _A_.[[TemplateObject]] to *false*. + 1. Set _A_.[[DefineOwnProperty]] as specified in . + 1. Perform ! OrdinaryDefineOwnProperty(_A_, *"length"*, PropertyDescriptor { [[Value]]: 𝔽(_length_), [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *false* }). + 1. Return _A_. + +
+
+
+ +

ECMAScript Language: Expressions

+ + +

Primary Expression

+ + +

Template Literals

+ + +

+ GetTemplateObject ( + _templateLiteral_: a Parse Node, + ): an Array +

+
+
+ + To enable the new API, this proposal modifies GetTemplateObject to change the value of the new internal slot. + + + 1. Let _realm_ be the current Realm Record. + 1. Let _templateRegistry_ be _realm_.[[TemplateMap]]. + 1. For each element _e_ of _templateRegistry_, do + 1. If _e_.[[Site]] is the same Parse Node as _templateLiteral_, then + 1. Return _e_.[[Array]]. + 1. Let _rawStrings_ be the TemplateStrings of _templateLiteral_ with argument *true*. + 1. Assert: _rawStrings_ is a List of Strings. + 1. Let _cookedStrings_ be the TemplateStrings of _templateLiteral_ with argument *false*. + 1. Let _count_ be the number of elements in the List _cookedStrings_. + 1. Assert: _count_ ≤ 232 - 1. + 1. Let _template_ be ! ArrayCreate(_count_). + 1. Set _template_.[[TemplateObject]] to *true*. + 1. Let _rawObj_ be ! ArrayCreate(_count_). + 1. Let _index_ be 0. + 1. Repeat, while _index_ < _count_, + 1. Let _prop_ be ! ToString(𝔽(_index_)). + 1. Let _cookedValue_ be _cookedStrings_[_index_]. + 1. Perform ! DefinePropertyOrThrow(_template_, _prop_, PropertyDescriptor { [[Value]]: _cookedValue_, [[Writable]]: *false*, [[Enumerable]]: *true*, [[Configurable]]: *false* }). + 1. Let _rawValue_ be the String value _rawStrings_[_index_]. + 1. Perform ! DefinePropertyOrThrow(_rawObj_, _prop_, PropertyDescriptor { [[Value]]: _rawValue_, [[Writable]]: *false*, [[Enumerable]]: *true*, [[Configurable]]: *false* }). + 1. Set _index_ to _index_ + 1. + 1. Perform ! SetIntegrityLevel(_rawObj_, ~frozen~). + 1. Perform ! DefinePropertyOrThrow(_template_, *"raw"*, PropertyDescriptor { [[Value]]: _rawObj_, [[Writable]]: *false*, [[Enumerable]]: *false*, [[Configurable]]: *false* }). + 1. Perform ! SetIntegrityLevel(_template_, ~frozen~). + 1. Append the Record { [[Site]]: _templateLiteral_, [[Array]]: _template_ } to _realm_.[[TemplateMap]]. + 1. Return _template_. + + +

The creation of a template object cannot result in an abrupt completion.

+
+ +

Each |TemplateLiteral| in the program code of a realm is associated with a unique template object that is used in the evaluation of tagged Templates (). The template objects are frozen and the same template object is used each time a specific tagged Template is evaluated. Whether template objects are created lazily upon first evaluation of the |TemplateLiteral| or eagerly prior to first evaluation is an implementation choice that is not observable to ECMAScript code.

+
+ +

Future editions of this specification may define additional non-enumerable properties of template objects.

+
+
+
+
+
-

New APIs

+ +

Indexed Collections

-

This adds a builtin static method to Array to allow distinguishing template string literal objects

+ +

Array Objects

-

Added under - Properties of the Array Constructor: -

+ +

Properties of the Array Constructor

- -

Array.isTemplateObject ( _value_ )

+ +

Array.isTemplateObject ( _value_ )

-

When the `isTemplateObject` method is called with argument _value_ the following steps are taken:

+

When the `isTemplateObject` method is called with argument _value_ the following steps are taken:

- - 1. If IsArray(_value_) is *true* and _value_.[[TemplateObject]] is *true* then - 1. Return *true*. - 1. Return *false*. - + + 1. If ? IsArray(_value_) is *true* and _value_.[[TemplateObject]] is *true*, then + 1. Return *true*. + 1. Return *false*. + - -

IsTemplateObject is realm-agnostic. Since template objects are frozen before - escaping GetTemplateObject, testing (IsTemplateObject(_x_) and _x_.[[Prototype]] - is the _realm_'s %ArrayPrototype%) is sufficient to determine whether an _x_ is - a template object in a particular _realm_.

-

In user code, `Array.isTemplateObject(x) && x instanceof Array` is an equivalent - test, assuming no changes to builtins.

-
+ +

IsTemplateObject is realm-agnostic. Since template objects are frozen before escaping GetTemplateObject, testing (IsTemplateObject(_x_) and _x_.[[Prototype]] is the _realm_'s %Array.prototype%) is sufficient to determine whether an _x_ is a template object in a particular _realm_.

+

In user code, `Array.isTemplateObject(x) && x instanceof Array` is an equivalent test, assuming no changes to builtins.

+
+
+
+