From 62e97a941a8a98de53fe8177cdf43b24a0f38f52 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Wed, 8 Feb 2023 16:50:48 -0800 Subject: [PATCH 1/3] [spec] Initial JS API formal spec for the GC proposal This commit adds formal spec test for the JS API portion of the GC proposal. The semantics is based on the "no-frills" JS API proposal in the following document: https://docs.google.com/document/d/17hCQXOyeSgogpJ0I0wir4LRmdvu4l7Oca6e1NkbVN8M/ The text assumes that the Wasm GC formal spec will expose certain operations to the embedder, such as `ref.cast`. Comments have been left where references between specs will need to be fixed up. --- document/js-api/index.bs | 171 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 162 insertions(+), 9 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index f99f9f578..539d1b707 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -90,6 +90,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT text: IterableToList; url: sec-iterabletolist text: ToBigInt64; url: #sec-tobigint64 text: BigInt; url: #sec-ecmascript-language-types-bigint-type + text: MakeBasicObject; url: #sec-makebasicobject type: abstract-op text: CreateMethodProperty; url: sec-createmethodproperty urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn @@ -113,6 +114,10 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: ref.null text: ref.func text: ref.extern + + text: ref.i31 + text: ref.array + text: ref.struct text: function index; url: syntax/modules.html#syntax-funcidx text: function instance; url: exec/runtime.html#function-instances text: store_init; url: appendix/embedding.html#embed-store-init @@ -142,6 +147,12 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: global_read; url: appendix/embedding.html#embed-global-read text: global_write; url: appendix/embedding.html#embed-global-write text: error; url: appendix/embedding.html#embed-error + + text: i31_new; url: appendix/embedding.html#embed-gc + text: i31_get; url: appendix/embedding.html#embed-gc + text: ref_cast; url: appendix/embedding.html#embed-gc + text: extern_internalize; url: appendix/embedding.html#embed-gc + text: extern_externalize; url: appendix/embedding.html#embed-gc text: store; url: exec/runtime.html#syntax-store text: table type; url: syntax/types.html#syntax-tabletype text: table address; url: exec/runtime.html#syntax-tableaddr @@ -149,6 +160,8 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: memory address; url: exec/runtime.html#syntax-memaddr text: global address; url: exec/runtime.html#syntax-globaladdr text: extern address; url: exec/runtime.html#syntax-externaddr + + text: object address; url: exec/runtime.html#syntax-objectaddr url: syntax/types.html#syntax-numtype text: i32 text: i64 @@ -159,6 +172,12 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: reftype text: funcref text: externref + text: ref + url: syntax/types.html#heap-types; for: heap-type + text: extern + text: func + text: i31 + text: any text: function element; url: exec/runtime.html#syntax-funcelem text: import component; url: syntax/modules.html#imports text: external value; url: exec/runtime.html#syntax-externval @@ -167,7 +186,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: module; url: syntax/modules.html#syntax-module text: imports; url: syntax/modules.html#syntax-module text: import; url: syntax/modules.html#syntax-import - url: syntax/types.html#external-types + url: syntax/types.html#external-types; for: external-type text: external type text: func text: table @@ -358,7 +377,7 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje 1. Let |o| be ? [=Get=](|importObject|, |moduleName|). 1. If [=Type=](|o|) is not Object, throw a {{TypeError}} exception. 1. Let |v| be ? [=Get=](|o|, |componentName|). - 1. If |externtype| is of the form [=func=] |functype|, + 1. If |externtype| is of the form [=external-type/func=] |functype|, 1. If [=IsCallable=](|v|) is false, throw a {{LinkError}} exception. 1. If |v| has a \[[FunctionAddress]] internal slot, and therefore is an [=Exported Function=], 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. @@ -407,7 +426,7 @@ The verification of WebAssembly type requirements is deferred to the 1. [=list/iterate|For each=] (|name|, |externtype|) of [=module_exports=](|module|), 1. Let |externval| be [=instance_export=](|instance|, |name|). 1. Assert: |externval| is not [=error=]. - 1. If |externtype| is of the form [=func=] functype, + 1. If |externtype| is of the form [=external-type/func=] functype, 1. Assert: |externval| is of the form [=external value|func=] |funcaddr|. 1. Let [=external value|func=] |funcaddr| be |externval|. 1. Let |func| be the result of creating [=a new Exported Function=] from |funcaddr|. @@ -544,7 +563,7 @@ interface Module {
The string value of the extern type |type| is - * "function" if |type| is of the form [=func=] functype + * "function" if |type| is of the form [=external-type/func=] functype * "table" if |type| is of the form [=table=] tabletype * "memory" if |type| is of the form [=mem=] memtype * "global" if |type| is of the form [=global=] globaltype @@ -1090,6 +1109,11 @@ The algorithm ToJSValue(|w|) coerces a [=WebAssembly value=] to a Jav 1. If |w| is of the form [=ref.null=] t, return null. 1. If |w| is of the form [=ref.func=] |funcaddr|, return the result of creating [=a new Exported Function=] from |funcaddr|. 1. If |w| is of the form [=ref.extern=] |externaddr|, return the result of [=retrieving an extern value=] from |externaddr|. +1. If |w| is of the form [=ref.array=] |arrayaddr|, return the result of creating [=a new GC Exported Object=] from |arrayaddr|. +1. If |w| is of the form [=ref.struct=] |structaddr|, return the result of creating [=a new GC Exported Object=] from |structaddr|. +1. If |w| is of the form [=ref.i31=] |i31addr|, + 1. Let |i32| be [=i31_get=](|i31addr|). + 1. Return [=the Number value=] for |i32|. Note: Number values which are equal to NaN may have various observable NaN payloads; see [=NumberToRawBytes=] for details.
@@ -1120,26 +1144,155 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va 1. If |type| is [=f64=], 1. Let |f64| be ? [=ToNumber=](|v|). 1. Return [=f64.const=] |f64|. -1. If |type| is [=funcref=], +1. If |type| is of the form [=ref=] |null| |heaptype| and is a subtype of [=ref=] |null| [=heap-type/func=], 1. If |v| is null, - 1. Return [=ref.null=] [=funcref=]. + 1. If |null| is present, + 1. Return [=ref.null=] |heaptype|. + 1. Otherwise, + 1. Throw a {{TypeError}}. 1. If |v| is an [=Exported Function=], 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. - 1. Return [=ref.func=] |funcaddr|. + 1. Let |casted| be [=ref_cast=](|heaptype|, |funcaddr|). + 1. Return |casted|. 1. Throw a {{TypeError}}. -1. If |type| is [=externref=], +1. If |type| is of the form [=ref=] |null| [=extern=], 1. If |v| is null, - 1. Return [=ref.null=] [=externref=]. + 1. If |null| is present, + 1. Return [=ref.null=] [=externref=]. + 1. Otherwise, + 1. Throw a {{TypeError}}. 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. 1. If a [=extern address=] |externaddr| exists such that |map|[|externaddr|] is the same as |v|, 1. Return [=ref.extern=] |externaddr|. 1. Let [=extern address=] |externaddr| be the smallest address such that |map|[|externaddr|] [=map/exists=] is false. 1. [=map/Set=] |map|[|externaddr|] to |v|. 1. Return [=ref.extern=] |externaddr|. +1. If |type| is of the form [=ref=] |null| |heaptype| and is a subtype of [=ref=] |null| [=any=], + 1. If |v| is null, + 1. If |null| is present, + 1. Return [=ref.null=] |heaptype|. + 1. Otherwise, + 1. Throw a {{TypeError}}. + 1. If |heaptype| is [=i31=], + 1. Let |i32value| be [=ToWebAssemblyValue=](|v|, [=i32=]). + 1. Let |ref| be [=i31_new=](|i32value|). + 1. Return |ref|. + 1. If |v| is a [=GC Exported Object=], + 1. Let |objectaddr| be the value of |v|'s \[[ObjectAddress]] internal slot. + 1. Let |intern| be [=extern_internalize=]([=ref.extern=] |objectaddr|). + 1. Let |casted| be [=ref_cast=](|heaptype|, |intern|). + 1. Return |casted|. + 1. Throw a {{TypeError}}. 1. Assert: This step is not reached. +

Garbage Collected Objects

+ +A WebAssembly struct or array is made available in JavaScript as a GC Exported Object. +A [=GC Exported Object=] is an exotic object that wraps a garbage collected WebAssembly reference value. +Most JavaScript operations on a [=GC Exported Object=] will throw an exception. + +Note: These operations may be refined in the future to allow richer interactions in JavaScript with WebAssembly structs and arrays. + +A [=GC Exported Object=] contains an \[[ObjectAddress]] internal slot. +This slot holds a [=extern address=] relative to the [=surrounding agent=]'s [=associated store=]. + +Note: A [=GC Exported Object=] holds an extern address, rather than the internal address of the corresponding struct or array. This is because the struct or array is first converted to an external representation via [=extern_externalize=] before it is exported to JavaScript. + +The internal methods of a [=GC Exported Object=] use the following implementations. + +
+ The \[[GetPrototypeOf]] internal method of a GC Exported Object O takes no arguments and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[SetPrototypeOf]] internal method of a GC Exported Object O takes argument V (an Object or null) and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[IsExtensible]] internal method of a GC Exported Object O takes no arguments and returns a boolean. It performs the following steps when called: + + 1. Return false. +
+ +
+ The \[[PreventExtensions]] internal method of a GC Exported Object O takes no arguments and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[GetOwnProperty]] internal method of a GC Exported Object O takes argument P (a property key) and returns undefined. It performs the following steps when called: + + 1. Return undefined. +
+ +
+ The \[[DefineOwnProperty]] internal method of a GC Exported Object O takes arguments P (a property key) and Desc (a property descriptor) and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[HasProperty]] internal method of a GC Exported Object O takes argument P (a property key) and returns a boolean. It performs the following steps when called: + + 1. Return false. +
+ +
+ The \[[Get]] internal method of a GC Exported Object O takes arguments P (a property key) and Receiver (an ECMAScript language value) and returns undefined. It performs the following steps when called: + + 1. Return undefined. +
+ +
+ The \[[Set]] internal method of a GC Exported Object O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[Delete]] internal method of a GC Exported Object O takes argument P (a property key) and throws an exception. It performs the following steps when called: + + 1. Throw a {{TypeError}}. +
+ +
+ The \[[OwnPropertyKeys]] internal method of a GC Exported Object O takes no arguments and returns a list. It performs the following steps when called: + + 1. Let keys be a new empty list. + 1. Return keys. +
+ +
+ To create a new GC Exported Object from a WebAssembly [=object address=] |objectaddr|, perform the following steps: + + 1. Let |externaddr| be [=extern_externalize=](|objectaddr|). + 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. + 1. If |map|[|externaddr|] [=map/exists=], + 1. Return |map|[|externaddr|]. + 1. Let |object| be [=MakeBasicObject=](« \[[ObjectAddress]] »). + 1. Set |object|.\[[ObjectAddress]] to |externaddr|. + 1. Set |object|.\[[GetPrototypeOf]] as specified in [=[[GetPrototypeOf]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[SetPrototypeOf]] as specified in [=[[SetPrototypeOf]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[IsExtensible]] as specified in [=[[IsExtensible]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[PreventExtensions]] as specified in [=[[PreventExtensions]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[GetOwnProperty]] as specified in [=[[GetOwnProperty]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[DefineOwnProperty]] as specified in [=[[DefineOwnProperty]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[HasProperty]] as specified in [=[[HasProperty]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[Get]] as specified in [=[[Get]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[Set]] as specified in [=[[Set]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[Delete]] as specified in [=[[Delete]] internal method of a GC Exported Object=]. + 1. Set |object|.\[[OwnPropertyKeys]] as specified in [=[[OwnPropertyKeys]] internal method of a GC Exported Object=]. + 1. [=map/Set=] |map|[|externaddr|] to |object|. + 1. Return |object|. +
+

Error Objects

WebAssembly defines the following Error classes: CompileError, LinkError, and RuntimeError. From 2d39b2254b8198b49b8e4a03a3de6fcfca18bfe0 Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Tue, 14 Feb 2023 14:26:41 -0800 Subject: [PATCH 2/3] Made various revisions, most in response to feedback * Renamed "GC Exported Object" to "Exported GC Object" * Made [[DefineOwnProperty]], [[PreventExtensions]], and [[SetPrototypeOf]] return false instead of throwing. (this will cause operations to throw after they check for a false return value) * Creating an Exported GC Object now puts it in a dedicated exported GC object cache instead of using the extern cache (this only worked when externalize was called on the stored address, but now we store the internal address instead) * extern_internalize and extern_externalize have their behavior specified in this spec. * Use the conversion functions above more in the JS spec. * i31refs are now converted in the conversion functions, so it does not matter what type is used at the boundary (i31 or any) * Added ref.host value type (still to be defined in the Wasm spec) that is used for any value that the JS API doesn't explicitly convert into an internal reference (i.e., non-i31s and non-GC objects). * Consolidate null cases in ToWebAssemblyValue * Added [[ObjectKind]] slot in Exported GC Object. This is just used so the spec knows whether to make a ref.array or ref.struct from the object address. --- document/js-api/index.bs | 195 +++++++++++++++++++++++---------------- 1 file changed, 114 insertions(+), 81 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 539d1b707..10adb902f 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -82,6 +82,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT text: SetFunctionName; url: sec-setfunctionname 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: NumberToRawBytes; url: sec-numbertorawbytes text: Built-in Function Objects; url: sec-built-in-function-objects text: NativeError Object Structure; url: sec-nativeerror-object-structure @@ -91,6 +92,7 @@ urlPrefix: https://tc39.github.io/ecma262/; spec: ECMASCRIPT text: ToBigInt64; url: #sec-tobigint64 text: BigInt; url: #sec-ecmascript-language-types-bigint-type text: MakeBasicObject; url: #sec-makebasicobject + text: ℝ; url: #ℝ type: abstract-op text: CreateMethodProperty; url: sec-createmethodproperty urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: dfn @@ -118,6 +120,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: ref.i31 text: ref.array text: ref.struct + text: ref.host text: function index; url: syntax/modules.html#syntax-funcidx text: function instance; url: exec/runtime.html#function-instances text: store_init; url: appendix/embedding.html#embed-store-init @@ -150,9 +153,11 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df text: i31_new; url: appendix/embedding.html#embed-gc text: i31_get; url: appendix/embedding.html#embed-gc - text: ref_cast; url: appendix/embedding.html#embed-gc - text: extern_internalize; url: appendix/embedding.html#embed-gc - text: extern_externalize; url: appendix/embedding.html#embed-gc + text: ref_test; url: appendix/embedding.html#embed-gc + text: extern_internalize; url: appendix/embedding.html#embed-gc; for: embedder + text: extern_externalize; url: appendix/embedding.html#embed-gc; for: embedder + text: extern.internalize; url: syntax/instructions.html#reference-instructions + text: extern.externalize; url: syntax/instructions.html#reference-instructions text: store; url: exec/runtime.html#syntax-store text: table type; url: syntax/types.html#syntax-tabletype text: table address; url: exec/runtime.html#syntax-tableaddr @@ -286,6 +291,7 @@ Each [=agent=] is associated with the following [=ordered map=]s: * The Memory object cache, mapping [=memory address=]es to {{Memory}} objects. * The Table object cache, mapping [=table address=]es to {{Table}} objects. * The Exported Function cache, mapping [=function address=]es to [=Exported Function=] objects. + * The Exported GC Object cache, mapping [=object address=]es to [=Exported GC Object=] objects. * The Global object cache, mapping [=global address=]es to {{Global}} objects. * The Extern value cache, mapping [=extern address=]es to values. @@ -1109,11 +1115,8 @@ The algorithm ToJSValue(|w|) coerces a [=WebAssembly value=] to a Jav 1. If |w| is of the form [=ref.null=] t, return null. 1. If |w| is of the form [=ref.func=] |funcaddr|, return the result of creating [=a new Exported Function=] from |funcaddr|. 1. If |w| is of the form [=ref.extern=] |externaddr|, return the result of [=retrieving an extern value=] from |externaddr|. -1. If |w| is of the form [=ref.array=] |arrayaddr|, return the result of creating [=a new GC Exported Object=] from |arrayaddr|. -1. If |w| is of the form [=ref.struct=] |structaddr|, return the result of creating [=a new GC Exported Object=] from |structaddr|. -1. If |w| is of the form [=ref.i31=] |i31addr|, - 1. Let |i32| be [=i31_get=](|i31addr|). - 1. Return [=the Number value=] for |i32|. +1. If |w| is of the form [=ref.array=] arrayaddr, [=ref.struct=] structaddr, [=ref.i31=] i31addr, or [=ref.host=] hostaddr, + 1. Return the result of [=extern_externalize=](|w|). Note: Number values which are equal to NaN may have various observable NaN payloads; see [=NumberToRawBytes=] for details. @@ -1144,152 +1147,139 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va 1. If |type| is [=f64=], 1. Let |f64| be ? [=ToNumber=](|v|). 1. Return [=f64.const=] |f64|. -1. If |type| is of the form [=ref=] |null| |heaptype| and is a subtype of [=ref=] |null| [=heap-type/func=], +1. If |type| is of the form [=ref=] |null| |heaptype|, 1. If |v| is null, 1. If |null| is present, 1. Return [=ref.null=] |heaptype|. 1. Otherwise, 1. Throw a {{TypeError}}. - 1. If |v| is an [=Exported Function=], - 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. - 1. Let |casted| be [=ref_cast=](|heaptype|, |funcaddr|). - 1. Return |casted|. - 1. Throw a {{TypeError}}. -1. If |type| is of the form [=ref=] |null| [=extern=], - 1. If |v| is null, - 1. If |null| is present, - 1. Return [=ref.null=] [=externref=]. - 1. Otherwise, - 1. Throw a {{TypeError}}. - 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. - 1. If a [=extern address=] |externaddr| exists such that |map|[|externaddr|] is the same as |v|, + 1. If |type| is a subtype of [=ref=] |null| [=heap-type/func=], + 1. If |v| is an [=Exported Function=], + 1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot. + 1. Let |testresult| be [=ref_test=](|heaptype|, [=ref.func=] |funcaddr|). + 1. If |testresult| is true, + 1. Return [=ref.func=] |funcaddr|. + 1. Throw a {{TypeError}}. + 1. If |heaptype| is [=extern=], + 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. + 1. If a [=extern address=] |externaddr| exists such that |map|[|externaddr|] is the same as |v|, + 1. Return [=ref.extern=] |externaddr|. + 1. Let [=extern address=] |externaddr| be the smallest address such that |map|[|externaddr|] [=map/exists=] is false. + 1. [=map/Set=] |map|[|externaddr|] to |v|. 1. Return [=ref.extern=] |externaddr|. - 1. Let [=extern address=] |externaddr| be the smallest address such that |map|[|externaddr|] [=map/exists=] is false. - 1. [=map/Set=] |map|[|externaddr|] to |v|. - 1. Return [=ref.extern=] |externaddr|. -1. If |type| is of the form [=ref=] |null| |heaptype| and is a subtype of [=ref=] |null| [=any=], - 1. If |v| is null, - 1. If |null| is present, - 1. Return [=ref.null=] |heaptype|. - 1. Otherwise, - 1. Throw a {{TypeError}}. - 1. If |heaptype| is [=i31=], - 1. Let |i32value| be [=ToWebAssemblyValue=](|v|, [=i32=]). - 1. Let |ref| be [=i31_new=](|i32value|). - 1. Return |ref|. - 1. If |v| is a [=GC Exported Object=], - 1. Let |objectaddr| be the value of |v|'s \[[ObjectAddress]] internal slot. - 1. Let |intern| be [=extern_internalize=]([=ref.extern=] |objectaddr|). - 1. Let |casted| be [=ref_cast=](|heaptype|, |intern|). - 1. Return |casted|. - 1. Throw a {{TypeError}}. + 1. If |type| is a subtype of [=ref=] |null| [=any=], + 1. Let |externref| be [=ToWebAssemblyValue=](|v|, [=ref=] [=extern=]). + 1. Let |internref| be [=extern_internalize=](|externref|). + 1. Let |testresult| be [=ref_test=](|heaptype|, |internref|). + 1. If |testresult| is true, + 1. Return |internref|. + 1. Throw a {{TypeError}}. 1. Assert: This step is not reached.

Garbage Collected Objects

-A WebAssembly struct or array is made available in JavaScript as a GC Exported Object. -A [=GC Exported Object=] is an exotic object that wraps a garbage collected WebAssembly reference value. -Most JavaScript operations on a [=GC Exported Object=] will throw an exception. +A WebAssembly struct or array is made available in JavaScript as an Exported GC Object. +An [=Exported GC Object=] is an exotic object that wraps a garbage collected WebAssembly reference value. +Most JavaScript operations on an [=Exported GC Object=] will throw an exception or return undefined. Note: These operations may be refined in the future to allow richer interactions in JavaScript with WebAssembly structs and arrays. -A [=GC Exported Object=] contains an \[[ObjectAddress]] internal slot. -This slot holds a [=extern address=] relative to the [=surrounding agent=]'s [=associated store=]. +An [=Exported GC Object=] contains an \[[ObjectAddress]] internal slot, which holds a [=object address=] relative to the [=surrounding agent=]'s [=associated store=], +and an \[[ObjectKind]] internal slot, which holds the string value "struct" or "array". -Note: A [=GC Exported Object=] holds an extern address, rather than the internal address of the corresponding struct or array. This is because the struct or array is first converted to an external representation via [=extern_externalize=] before it is exported to JavaScript. - -The internal methods of a [=GC Exported Object=] use the following implementations. +The internal methods of an [=Exported GC Object=] use the following implementations.
- The \[[GetPrototypeOf]] internal method of a GC Exported Object O takes no arguments and throws an exception. It performs the following steps when called: + The \[[GetPrototypeOf]] internal method of an Exported GC Object O takes no arguments and throws an exception. It performs the following steps when called: 1. Throw a {{TypeError}}.
- The \[[SetPrototypeOf]] internal method of a GC Exported Object O takes argument V (an Object or null) and throws an exception. It performs the following steps when called: + The \[[SetPrototypeOf]] internal method of an Exported GC Object O takes argument V (an Object or null) and returns a boolean. It performs the following steps when called: - 1. Throw a {{TypeError}}. + 1. Return false.
- The \[[IsExtensible]] internal method of a GC Exported Object O takes no arguments and returns a boolean. It performs the following steps when called: + The \[[IsExtensible]] internal method of an Exported GC Object O takes no arguments and returns a boolean. It performs the following steps when called: 1. Return false.
- The \[[PreventExtensions]] internal method of a GC Exported Object O takes no arguments and throws an exception. It performs the following steps when called: + The \[[PreventExtensions]] internal method of an Exported GC Object O takes no arguments and returns a boolean. It performs the following steps when called: - 1. Throw a {{TypeError}}. + 1. Return false.
- The \[[GetOwnProperty]] internal method of a GC Exported Object O takes argument P (a property key) and returns undefined. It performs the following steps when called: + The \[[GetOwnProperty]] internal method of an Exported GC Object O takes argument P (a property key) and returns undefined. It performs the following steps when called: 1. Return undefined.
- The \[[DefineOwnProperty]] internal method of a GC Exported Object O takes arguments P (a property key) and Desc (a property descriptor) and throws an exception. It performs the following steps when called: + The \[[DefineOwnProperty]] internal method of an Exported GC Object O takes arguments P (a property key) and Desc (a property descriptor) and returns a boolean. It performs the following steps when called: - 1. Throw a {{TypeError}}. + 1. Return false.
- The \[[HasProperty]] internal method of a GC Exported Object O takes argument P (a property key) and returns a boolean. It performs the following steps when called: + The \[[HasProperty]] internal method of an Exported GC Object O takes argument P (a property key) and returns a boolean. It performs the following steps when called: 1. Return false.
- The \[[Get]] internal method of a GC Exported Object O takes arguments P (a property key) and Receiver (an ECMAScript language value) and returns undefined. It performs the following steps when called: + The \[[Get]] internal method of an Exported GC Object O takes arguments P (a property key) and Receiver (an ECMAScript language value) and returns undefined. It performs the following steps when called: 1. Return undefined.
- The \[[Set]] internal method of a GC Exported Object O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and throws an exception. It performs the following steps when called: + The \[[Set]] internal method of an Exported GC Object O takes arguments P (a property key), V (an ECMAScript language value), and Receiver (an ECMAScript language value) and throws an exception. It performs the following steps when called: 1. Throw a {{TypeError}}.
- The \[[Delete]] internal method of a GC Exported Object O takes argument P (a property key) and throws an exception. It performs the following steps when called: + The \[[Delete]] internal method of an Exported GC Object O takes argument P (a property key) and throws an exception. It performs the following steps when called: 1. Throw a {{TypeError}}.
- The \[[OwnPropertyKeys]] internal method of a GC Exported Object O takes no arguments and returns a list. It performs the following steps when called: + The \[[OwnPropertyKeys]] internal method of an Exported GC Object O takes no arguments and returns a list. It performs the following steps when called: 1. Let keys be a new empty list. 1. Return keys.
- To create a new GC Exported Object from a WebAssembly [=object address=] |objectaddr|, perform the following steps: + To create a new Exported GC Object from a WebAssembly [=object address=] |objectaddr| and a string |objectkind|, perform the following steps: - 1. Let |externaddr| be [=extern_externalize=](|objectaddr|). - 1. Let |map| be the [=surrounding agent=]'s associated [=extern value cache=]. - 1. If |map|[|externaddr|] [=map/exists=], - 1. Return |map|[|externaddr|]. + 1. Assert: |objectkind| is either "array" or "struct". + 1. Let |map| be the [=surrounding agent=]'s associated [=exported GC object cache=]. + 1. If |map|[|objectaddr|] [=map/exists=], + 1. Return |map|[|objectaddr|]. 1. Let |object| be [=MakeBasicObject=](« \[[ObjectAddress]] »). - 1. Set |object|.\[[ObjectAddress]] to |externaddr|. - 1. Set |object|.\[[GetPrototypeOf]] as specified in [=[[GetPrototypeOf]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[SetPrototypeOf]] as specified in [=[[SetPrototypeOf]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[IsExtensible]] as specified in [=[[IsExtensible]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[PreventExtensions]] as specified in [=[[PreventExtensions]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[GetOwnProperty]] as specified in [=[[GetOwnProperty]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[DefineOwnProperty]] as specified in [=[[DefineOwnProperty]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[HasProperty]] as specified in [=[[HasProperty]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[Get]] as specified in [=[[Get]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[Set]] as specified in [=[[Set]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[Delete]] as specified in [=[[Delete]] internal method of a GC Exported Object=]. - 1. Set |object|.\[[OwnPropertyKeys]] as specified in [=[[OwnPropertyKeys]] internal method of a GC Exported Object=]. - 1. [=map/Set=] |map|[|externaddr|] to |object|. + 1. Set |object|.\[[ObjectAddress]] to |objectaddr|. + 1. Set |object|.\[[ObjectKind]] to |objectkind|. + 1. Set |object|.\[[GetPrototypeOf]] as specified in [=[[GetPrototypeOf]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[SetPrototypeOf]] as specified in [=[[SetPrototypeOf]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[IsExtensible]] as specified in [=[[IsExtensible]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[PreventExtensions]] as specified in [=[[PreventExtensions]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[GetOwnProperty]] as specified in [=[[GetOwnProperty]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[DefineOwnProperty]] as specified in [=[[DefineOwnProperty]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[HasProperty]] as specified in [=[[HasProperty]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[Get]] as specified in [=[[Get]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[Set]] as specified in [=[[Set]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[Delete]] as specified in [=[[Delete]] internal method of an Exported GC Object=]. + 1. Set |object|.\[[OwnPropertyKeys]] as specified in [=[[OwnPropertyKeys]] internal method of an Exported GC Object=]. + 1. [=map/Set=] |map|[|objectaddr|] to |object|. 1. Return |object|.
@@ -1355,6 +1345,49 @@ Note: ECMAScript doesn't specify any sort of behavior on out-of-memory condition See [Issue 879](https://github.com/WebAssembly/spec/issues/879) for further discussion. +

Requirements on External Conversion Operations in WebAssembly

+ +The WebAssembly core specification defines the [=extern.externalize=] and [=extern.internalize=] instructions +(exposed as [=embedder/extern_externalize=] and [=embedder/extern_internalize=] in the embedding API) +for the purpose of converting internal WebAssembly references to or from an external host representation. +The behavior of these operations is partially host-defined. + +A JavaScript host implementation must implement [=embedder/extern_internalize=] and [=embedder/extern_externalize=] as follows: + +
+The extern_internalize(|externref|) operation takes one argument |externref| and performs the following steps: + +1. Let [=ref.extern=] |externaddr| be |externref|. +1. Let |v| be the result of [=retrieving an extern value=] from |externaddr|. +1. If |v| [=is a Number=], + 1. Let |i32| be ? [=ToInt32=](|v|). + 1. If |v| is equal to |i32| and [=ℝ=](|v|) < 230 and [=ℝ=](|v|) ⩾ -230, + 1. Return [=i31_new=]([=i32.const=] |v|). +1. If |v| is an [=Exported GC Object=], + 1. Let |objectaddr| be the value of |v|'s \[[ObjectAddress]] internal slot. + 1. Let |objecttype| be the value of |v|'s \[[ObjectType]] internal slot. + 1. If |objecttype| is "array", + 1. Return [=ref.array=] |objectaddr|. + 1. If |objecttype| is "struct", + 1. Return [=ref.struct=] |objectaddr|. +1. Otherwise, + 1. Return [=ref.host=] |externaddr|. + +
+ +
+The extern_externalize(|internref|) operation takes one argument |internref| and performs the following steps: + +1. If |internref| is of the form [=ref.i31=] |i31addr|, + 1. Let |i32| be [=i31_get=](|i31addr|). + 1. Return [=the Number value=] for |i32|. +1. If |internref| is of the form [=ref.struct=] |structaddr|, return the result of creating [=a new Exported GC Object=] from |structaddr| and "struct". +1. If |internref| is of the form [=ref.array=] |arrayaddr|, return the result of creating [=a new Exported GC Object=] from |arrayaddr| and "array". +1. If |internref| is of the form [=ref.host=] |externaddr|, return the result of [=retrieving an extern value=] from |externaddr|. +1. Assert: This step is not reached. + +
+

Implementation-defined Limits

The WebAssembly core specification allows an implementation to define limits on the syntactic structure of the module. From 5a367025a1883dfc74bffdf9fd1401f6dfafb64f Mon Sep 17 00:00:00 2001 From: Asumu Takikawa Date: Mon, 20 Feb 2023 11:41:47 -0800 Subject: [PATCH 3/3] Update [[GetPrototypeOf]] to return null --- document/js-api/index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 10adb902f..2f3588843 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -1192,9 +1192,9 @@ and an \[[ObjectKind]] internal slot, which holds the string value "struct" or " The internal methods of an [=Exported GC Object=] use the following implementations.
- The \[[GetPrototypeOf]] internal method of an Exported GC Object O takes no arguments and throws an exception. It performs the following steps when called: + The \[[GetPrototypeOf]] internal method of an Exported GC Object O takes no arguments and returns null. It performs the following steps when called: - 1. Throw a {{TypeError}}. + 1. Return null.