Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Update JS API to handle index types #75

Merged
merged 2 commits into from
Aug 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 86 additions & 46 deletions document/js-api/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT
text: SetFunctionLength; url: sec-setfunctionlength
text: the Number value; url: sec-ecmascript-language-types-number-type
text: is a Number; url: sec-ecmascript-language-types-number-type
text: is a BigInt; url: sec-ecmascript-language-types-bigint-type
text: NumberToRawBytes; url: sec-numbertorawbytes
text: Built-in Function Objects; url: sec-built-in-function-objects
text: NativeError Object Structure; url: sec-nativeerror-object-structure
Expand All @@ -61,6 +62,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT
text: NativeError Object Structure; url: sec-nativeerror-object-structure
text: 𝔽; url: #𝔽
text: ℤ; url: #ℤ
text: mathematical value; url: #mathematical-value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new definition, and its uses, looks like it it could be an upstream change?

text: SameValue; url: sec-samevalue
urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn
url: valid/modules.html#valid-module
Expand Down Expand Up @@ -121,6 +123,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
text: match_valtype; url: appendix/embedding.html#embed-match-valtype
text: error; url: appendix/embedding.html#embed-error
text: store; url: exec/runtime.html#syntax-store
text: index type; url: syntax/types.html#syntax-idxtype
text: table type; url: syntax/types.html#syntax-tabletype
text: table address; url: exec/runtime.html#syntax-tableaddr
text: function address; url: exec/runtime.html#syntax-funcaddr
Expand All @@ -139,6 +142,9 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
text: exn_alloc; url: appendix/embedding.html#embed-exn-alloc
text: exn_tag; url: appendix/embedding.html#embed-exn-tag
text: exn_read; url: appendix/embedding.html#embed-exn-read
url: syntax/values.html#syntax-int
text: u32
text: u64
url: syntax/types.html#syntax-numtype
text: i32
text: i64
Expand Down Expand Up @@ -200,6 +206,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
urlPrefix: https://heycam.github.io/webidl/; spec: WebIDL
type: dfn
text: create a namespace object; url: create-a-namespace-object
text: [EnforceRange]; url: #EnforceRange
urlPrefix: https://webassembly.github.io/js-types/js-api/; spec: WebAssembly JS API (JS Type Reflection)
type: abstract-op; text: FromValueType; url: abstract-opdef-fromvaluetype
urlPrefix: https://tc39.es/proposal-resizablearraybuffer/; spec: ResizableArrayBuffer proposal
Expand Down Expand Up @@ -561,6 +568,8 @@ enum IndexType {
"i64",
};

typedef ([EnforceRange] unsigned long long or bigint) IndexValue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to file a bug as mentioned in the warning here: https://webidl.spec.whatwg.org/#dfn-union-type ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be wise, yes. Hopefully it's a quick rubber stamp and we can move on.

I'm traveling at the moment, so I would appreciate if you could open that issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


dictionary ModuleExportDescriptor {
required USVString name;
required ImportExportKind kind;
Expand Down Expand Up @@ -665,15 +674,15 @@ Note: The use of this synchronous API is discouraged, as some implementations so

<pre class="idl">
dictionary MemoryDescriptor {
required [EnforceRange] unsigned long long initial;
[EnforceRange] unsigned long long maximum;
required IndexValue initial;
IndexValue maximum;
IndexType index;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Memory {
constructor(MemoryDescriptor descriptor);
unsigned long grow([EnforceRange] unsigned long long delta);
unsigned long grow(IndexValue delta);
ArrayBuffer toFixedLengthBuffer();
ArrayBuffer toResizableBuffer();
readonly attribute ArrayBuffer buffer;
Expand Down Expand Up @@ -736,11 +745,11 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each

<div algorithm>
The <dfn constructor for="Memory">Memory(|descriptor|)</dfn> constructor, when invoked, performs the following steps:
1. Let |initial| be |descriptor|["initial"].
1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty.
1. If |descriptor|["index"] [=map/exists=], let |indextype| be |descriptor|["index"]; otherwise, let |indextype| be "i32".
1. Let |initial| be [=?=] [=IndexValueToU64=](|descriptor|["initial"], |indextype|).
1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be [=?=] [=IndexValueToU64=](|descriptor|["maximum"], |indextype|); otherwise, let |maximum| be empty.
1. If |maximum| is not empty and |maximum| &lt; |initial|, throw a {{RangeError}} exception.
1. If |descriptior|["index"] [=map/exists=], let |index| be |descriptor|["index"]; otherwise, let |index| be "i32".
1. Let |memtype| be { min |initial|, max |maximum|, index |index| }.
1. Let |memtype| be |indextype| { **min** |initial|, **max** |maximum| }.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |memaddr|) be [=mem_alloc=](|store|, |memtype|). If allocation fails, throw a {{RangeError}} exception.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
Expand Down Expand Up @@ -779,7 +788,10 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
<div algorithm=dom-Memory-grow>
The <dfn method for="Memory">grow(|delta|)</dfn> method, when invoked, performs the following steps:
1. Let |memaddr| be **this**.\[[Memory]].
1. Return the result of [=grow the memory buffer|growing the memory buffer=] associated with |memaddr| by |delta|.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |indextype| be the [=index type=] in [=mem_type=](|store|, |memaddr|).
1. Let |delta64| be [=?=] [=IndexValueToU64=](|delta|, |indextype|).
1. Return the result of [=grow the memory buffer|growing the memory buffer=] associated with |memaddr| by |delta64|.
</div>

Immediately after a WebAssembly [=memory.grow=] instruction executes, perform the following steps:
Expand Down Expand Up @@ -857,18 +869,18 @@ enum TableKind {

dictionary TableDescriptor {
required TableKind element;
required [EnforceRange] unsigned long long initial;
[EnforceRange] unsigned long long maximum;
required IndexValue initial;
IndexValue maximum;
IndexType index;
};

[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
constructor(TableDescriptor descriptor, optional any value);
unsigned long long grow([EnforceRange] unsigned long long delta, optional any value);
any get([EnforceRange] unsigned long long index);
undefined set([EnforceRange] unsigned long long index, optional any value);
readonly attribute unsigned long length;
IndexValue grow(IndexValue delta, optional any value);
any get(IndexValue index);
undefined set(IndexValue index, optional any value);
readonly attribute IndexValue length;
};
</pre>

Expand Down Expand Up @@ -896,19 +908,19 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address

<div algorithm>
The <dfn constructor for="Table">Table(|descriptor|, |value|)</dfn> constructor, when invoked, performs the following steps:
1. Let |elementType| be [=ToValueType=](|descriptor|["element"]).
1. If |elementType| is not a [=reftype=],
1. Throw a {{TypeError}} exception.
1. Let |initial| be |descriptor|["initial"].
1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be |descriptor|["maximum"]; otherwise, let |maximum| be empty.
1. Let |elementtype| be [=ToValueType=](|descriptor|["element"]).
1. If |elementtype| is not a [=reftype=],
1. [=Throw=] a {{TypeError}} exception.
1. If |descriptor|["index"] [=map/exists=], let |indextype| be |descriptor|["index"]; otherwise, let |indextype| be "i32".
1. Let |initial| be [=?=] [=IndexValueToU64=](|descriptor|["initial"], |indextype|).
1. If |descriptor|["maximum"] [=map/exists=], let |maximum| be [=?=] [=IndexValueToU64=](|descriptor|["maximum"], |indextype|); otherwise, let |maximum| be empty.
1. If |maximum| is not empty and |maximum| &lt; |initial|, throw a {{RangeError}} exception.
1. If |value| is missing,
1. Let |ref| be [=DefaultValue=](|elementType|).
1. Let |ref| be [=DefaultValue=](|elementtype|).
1. Assert: |ref| is not [=error=].
1. Otherwise,
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
1. If |descriptior|["index"] [=map/exists=], let |index| be |descriptor|["index"]; otherwise, let |index| be "i32".
1. Let |type| be the [=table type=] [=table type|index=] |index| {[=table type|min=] |initial|, [=table type|max=] |maximum|} [=table type|refType=] |elementType|.
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementtype|).
1. Let |type| be the [=table type=] (|indextype|, { **min** |initial|, **max** |maximum| }, |elementtype|).
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |tableaddr|) be [=table_alloc=](|store|, |type|, |ref|). <!-- TODO(littledan): Report allocation failure https://github.com/WebAssembly/spec/issues/584 -->
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
Expand All @@ -920,13 +932,14 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
1. Let |tableaddr| be **this**.\[[Table]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |initialSize| be [=table_size=](|store|, |tableaddr|).
1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|tableaddr|).
1. Let (|indextype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|).
1. Let |delta64| be [=?=] [=IndexValueToU64=](|delta|, |indextype|).
1. If |value| is missing,
1. Let |ref| be [=DefaultValue=](|elementType|).
1. Let |ref| be [=DefaultValue=](|elementtype|).
1. If |ref| is [=error=], throw a {{TypeError}} exception.
1. Otherwise,
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|, |ref|).
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementtype|).
1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta64|, |ref|).
1. If |result| is [=error=], throw a {{RangeError}} exception.

Note: The above exception can happen due to either insufficient memory or an invalid size parameter.
Expand All @@ -939,17 +952,20 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
The getter of the <dfn attribute for="Table">length</dfn> attribute of {{Table}}, when invoked, performs the following steps:
1. Let |tableaddr| be **this**.\[[Table]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Return [=table_size=](|store|, |tableaddr|).
1. Let |indextype| be the [=index type=] in [=table_type=](|store|, |tableaddr|).
1. Let |length64| be [=table_size=](|store|, |tableaddr|).
1. Return [=U64ToIndexValue=](|length64|, |indextype|).
</div>

<div algorithm>
The <dfn method for="Table">get(|index|)</dfn> method, when invoked, performs the following steps:
1. Let |tableaddr| be **this**.\[[Table]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|store|, |tableaddr|).
1. If |elementType| is [=exnref=],
1. Let (|indextype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|).
1. If |elementtype| is [=exnref=],
1. Throw a {{TypeError}} exception.
1. Let |result| be [=table_read=](|store|, |tableaddr|, |index|).
1. Let |index64| be [=?=] [=IndexValueToU64=](|index|, |indextype|).
1. Let |result| be [=table_read=](|store|, |tableaddr|, |index64|).
1. If |result| is [=error=], throw a {{RangeError}} exception.
1. Return [=ToJSValue=](|result|).
</div>
Expand All @@ -958,16 +974,16 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
The <dfn method for="Table">set(|index|, |value|)</dfn> method, when invoked, performs the following steps:
1. Let |tableaddr| be **this**.\[[Table]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|store|, |tableaddr|).
1. If |elementType| is [=exnref=],
1. Let (|indextype|, <var ignore>limits</var>, |elementtype|) be [=table_type=](|store|, |tableaddr|).
1. If |elementtype| is [=exnref=],
1. Throw a {{TypeError}} exception.
1. Let |index64| be [=?=] [=IndexValueToU64=](|index|, |indextype|).
1. If |value| is missing,
1. Let |ref| be [=DefaultValue=](|elementType|).
1. Let |ref| be [=DefaultValue=](|elementtype|).
1. If |ref| is [=error=], throw a {{TypeError}} exception.
1. Otherwise,
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let |store| be [=table_write=](|store|, |tableaddr|, |index|, |ref|).
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementtype|).
1. Let |store| be [=table_write=](|store|, |tableaddr|, |index64|, |ref|).
1. If |store| is [=error=], throw a {{RangeError}} exception.
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
</div>
Expand Down Expand Up @@ -1236,18 +1252,18 @@ The algorithm <dfn>ToJSValue</dfn>(|w|) coerces a [=WebAssembly value=] to a Jav
1. Assert: |w| is not of the form [=ref.exn=] <var ignore>exnaddr</var>.
1. If |w| is of the form [=i64.const=] |u64|,
1. Let |i64| be [=signed_64=](|u64|).
1. Return [=ℤ=](|i64| interpreted as a mathematical value).
1. If |w| is of the form [=i32.const=] |i32|,
1. Let |i32| be [=signed_32=](|i32|).
2. Return [=𝔽=](|i32| interpreted as a mathematical value).
1. Return [=ℤ=](|i64| interpreted as a [=mathematical value=]).
1. If |w| is of the form [=i32.const=] |u32|,
1. Let |i32| be [=signed_32=](|u32|).
2. Return [=𝔽=](|i32| interpreted as a [=mathematical value=]).
1. If |w| is of the form [=f32.const=] |f32|,
1. If |f32| is [=+∞=] or [=−∞=], return **+∞**<sub>𝔽</sub> or **-∞**<sub>𝔽</sub>, respectively.
1. If |f32| is [=nan=], return **NaN**.
1. Return [=𝔽=](|f32| interpreted as a mathematical value).
1. Return [=𝔽=](|f32| interpreted as a [=mathematical value=]).
1. If |w| is of the form [=f64.const=] |f64|,
1. If |f64| is [=+∞=] or [=−∞=], return **+∞**<sub>𝔽</sub> or **-∞**<sub>𝔽</sub>, respectively.
1. If |f64| is [=nan=], return **NaN**.
1. Return [=𝔽=](|f64| interpreted as a mathematical value).
1. Return [=𝔽=](|f64| interpreted as a [=mathematical value=]).
1. If |w| is of the form [=ref.null=] <var ignore>t</var>, return null.
1. If |w| is of the form [=ref.i31=] |u31|,
1. Let |i31| be [=signed_31=](|u31|).
Expand Down Expand Up @@ -1288,15 +1304,15 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript va
1. If |type| is [=f32=],
1. Let |number| be [=?=] [$ToNumber$](|v|).
1. If |number| is **NaN**,
1. Let |n| be an implementation-defined integer such that [=canon=]<sub>32</sub> |n| < 2<sup>[=signif=](32)</sup>.
1. Let |n| be an implementation-defined integer such that [=canon=]<sub>32</sub> &leq; |n| &lt; 2<sup>[=signif=](32)</sup>.
1. Let |f32| be [=nan=](n).
1. Otherwise,
1. Let |f32| be |number| rounded to the nearest representable value using IEEE 754-2008 round to nearest, ties to even mode. [[IEEE-754]]
1. Return [=f32.const=] |f32|.
1. If |type| is [=f64=],
1. Let |number| be [=?=] [$ToNumber$](|v|).
1. If |number| is **NaN**,
1. Let |n| be an implementation-defined integer such that [=canon=]<sub>64</sub> |n| < 2<sup>[=signif=](64)</sup>.
1. Let |n| be an implementation-defined integer such that [=canon=]<sub>64</sub> &leq; |n| &lt; 2<sup>[=signif=](64)</sup>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanups in this div could also be upstream change maybe?

1. Let |f64| be [=nan=](n).
1. Otherwise,
1. Let |f64| be |number|.
Expand Down Expand Up @@ -1337,6 +1353,31 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript va

</div>

<div algorithm>
The algorithm <dfn>IndexValueToU64</dfn>(|v|, |indextype|) asserts that a JavaScript value is the appropriate variant of {{IndexValue}} for an {{IndexType}}, and ensures that its value is in [=u64=] range for WebAssembly embedding operations, by performing the following steps:

1. If |indextype| is "i32",
1. If |v| [=is a Number=],
1. Assert: Due to WebIDL types and [=[EnforceRange]=], 0 ≤ [=ℝ=](|v|) < 2<sup>64</sup>.
1. Return [=ℝ=](|v|) as a WebAssembly [=u64=].
1. Otherwise, [=throw=] a {{TypeError}}.
1. Else if |indextype| is "i64",
1. If |v| [=is a BigInt=],
1. If |v| is not equal to [=!=] [$ToBigUint64$](|v|), [=throw=] a {{RangeError}}.
1. Return [=ℝ=](|v|) as a WebAssembly [=u64=].
1. Otherwise, [=throw=] a {{TypeError}}.
1. Assert: This step is not reached.

</div>

<div algorithm>
The algorithm <dfn>U64ToIndexValue</dfn>(|v|, |indextype|) converts a [=u64=] value from a WebAssembly embedding operation to the correct variant of {{IndexValue}} for an {{IndexType}}, by performing the following steps:

1. If |indextype| is "i32", return [=𝔽=](|v| interpreted as a [=mathematical value=]).
1. Else if |indextype| is "i64", return [=ℤ=](|v| interpreted as a [=mathematical value=]).
1. Assert: This step is not reached.

</div>

<h3 id="tags">Tags</h3>

Expand Down Expand Up @@ -1369,7 +1410,6 @@ To <dfn>initialize a Tag object</dfn> |tag| from a [=tag address=] |tagAddress|,
</div>

<div algorithm>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this line maybe?

To <dfn>create a Tag object</dfn> from a [=tag address=] |tagAddress|, perform the following steps:

1. Let |map| be the [=surrounding agent=]'s associated [=Tag object cache=].
Expand Down
Loading