From 7b438ea15fdd850afff7ad9ac4d1530ae277361b Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Fri, 12 Apr 2024 08:44:49 -0500 Subject: [PATCH 1/4] Fix nullability for string constants --- proposals/js-string-builtins/Overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/js-string-builtins/Overview.md b/proposals/js-string-builtins/Overview.md index 17d8191f..cce34cf1 100644 --- a/proposals/js-string-builtins/Overview.md +++ b/proposals/js-string-builtins/Overview.md @@ -175,9 +175,9 @@ This proposal adds an extension to the JS-API compile routine to support optimiz The `WebAssemblyCompileOptions` dictionary is extended with a `boolean importedStringConstants` flag. When this is set, the module may define imports of the form `(import "'" "%stringConstant%"" (global externref))`, and the JS-API will use the provided `%stringConstant%` import field name to be the value of the global. This allows for any UTF-8 string to be imported with minimal overhead. -The string namespace is chosen to be the single quote ASCII character `'`. We may revise this to be a longer name before this proposal is finalized. +This works by having the JS-API create a `(global (ref extern))` for each string constant, and provide that as the import value to the module. The [normal import checking for globals](https://webassembly.github.io/gc/core/valid/matching.html#match-globaltype) is performed, which allows for a user to specify either nullable or non-nullable externref, as long as the import global type is immutable. This check is eager, resulting in a compile error if it fails. -All imports that reference this namespace must be globals of type immutable externref. If they are not, an eager compile error is emitted. +The string namespace is chosen to be the single quote ASCII character `'`. This is to reduce binary size impact. We may revise this to be a longer name before this proposal is finalized, if we can mitigate the binary size increase. ## JS String Builtin API From a0afe0d83772d180e5820e46f3bed4d0f054ebbc Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Tue, 25 Jun 2024 12:59:04 -0500 Subject: [PATCH 2/4] Expand section on string constants --- proposals/js-string-builtins/Overview.md | 38 +++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/proposals/js-string-builtins/Overview.md b/proposals/js-string-builtins/Overview.md index cce34cf1..c4099a22 100644 --- a/proposals/js-string-builtins/Overview.md +++ b/proposals/js-string-builtins/Overview.md @@ -84,7 +84,7 @@ The full extension to the JS-API WebIDL is: ```idl dictionary WebAssemblyCompileOptions { - optional sequence builtins; + optional record builtins; } [LegacyNamespace=WebAssembly, Exposed=*] @@ -173,11 +173,41 @@ The simplest way is to have a module import each string as an immutable global. This proposal adds an extension to the JS-API compile routine to support optimized 'imported string constants' to address this use-case. -The `WebAssemblyCompileOptions` dictionary is extended with a `boolean importedStringConstants` flag. When this is set, the module may define imports of the form `(import "'" "%stringConstant%"" (global externref))`, and the JS-API will use the provided `%stringConstant%` import field name to be the value of the global. This allows for any UTF-8 string to be imported with minimal overhead. +The `WebAssemblyCompileOptions` dictionary is extended with a `USVString? importedStringConstants` flag. -This works by having the JS-API create a `(global (ref extern))` for each string constant, and provide that as the import value to the module. The [normal import checking for globals](https://webassembly.github.io/gc/core/valid/matching.html#match-globaltype) is performed, which allows for a user to specify either nullable or non-nullable externref, as long as the import global type is immutable. This check is eager, resulting in a compile error if it fails. +``` +partial dictionary WebAssemblyCompileOptions { + USVString? importedStringConstants; +} +``` + +When this is set to a non-null value, the module may import globals of the form `(import "%importedStringConstants%" "%stringConstant%"" (global ...))`, and the JS-API will use the provided `%stringConstant%` import field name to be the value of the global. This allows for any UTF-8 string to be imported with minimal overhead. + +### Example + +```wasm +(module + (global (import "strings" "my string constant") (ref extern)) + (export "constant" (global 0)) +) +``` + +```js +let instance = WebAssembly.instantiate(bytes, {importedStringConstants: "strings"}); + +// The global is automatically populated with the string constant +assertEq(instance.exports.constant.value, "my string constant"); +``` + +### Details + +When `importedStringConstants` is non-null, the specified string becomes the `imported string namespace`. + +During the ['compile a module'](https://webassembly.github.io/spec/js-api/index.html#compile-a-webassembly-module) step of the JS-API, the imports of the module are examined to see which refer to the imported string namespace. If an import refers to the imported string namespace, then the import type is [matched](https://webassembly.github.io/spec/core/valid/types.html#globals) against an extern type of `(global (ref extern))`. If an import fails to match, then 'compile a module' fails. The resulting module is associated with the imported string namespace for use during instantiation. + +During the ['read the imports'](https://webassembly.github.io/spec/js-api/index.html#read-the-imports) step of the JS-API, if the module has an imported string namespace, then every import that refers to this namespace has a global created to hold the string constant specified in the import field. This global is added to the imports object. -The string namespace is chosen to be the single quote ASCII character `'`. This is to reduce binary size impact. We may revise this to be a longer name before this proposal is finalized, if we can mitigate the binary size increase. +When the imports object is used during ['instantiate a module'](https://webassembly.github.io/spec/js-api/index.html#instantiate-the-core-of-a-webassembly-module), these implicitly created globals should never cause a link error due to the eager matching done in 'compile a module'. ## JS String Builtin API From a166b56434b614bd9e4302d4a95a01fe177eac05 Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Tue, 25 Jun 2024 13:04:37 -0500 Subject: [PATCH 3/4] Revert unintentional change to builtins field --- proposals/js-string-builtins/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/js-string-builtins/Overview.md b/proposals/js-string-builtins/Overview.md index c4099a22..afd8c55b 100644 --- a/proposals/js-string-builtins/Overview.md +++ b/proposals/js-string-builtins/Overview.md @@ -84,7 +84,7 @@ The full extension to the JS-API WebIDL is: ```idl dictionary WebAssemblyCompileOptions { - optional record builtins; + optional sequence builtins; } [LegacyNamespace=WebAssembly, Exposed=*] From 52a334054144b5c4ee126cea7b4de2ec1bb4784d Mon Sep 17 00:00:00 2001 From: Ryan Hunt Date: Wed, 26 Jun 2024 15:52:58 -0500 Subject: [PATCH 4/4] Add note about empty imports object --- proposals/js-string-builtins/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/js-string-builtins/Overview.md b/proposals/js-string-builtins/Overview.md index afd8c55b..d40de356 100644 --- a/proposals/js-string-builtins/Overview.md +++ b/proposals/js-string-builtins/Overview.md @@ -205,7 +205,7 @@ When `importedStringConstants` is non-null, the specified string becomes the `im During the ['compile a module'](https://webassembly.github.io/spec/js-api/index.html#compile-a-webassembly-module) step of the JS-API, the imports of the module are examined to see which refer to the imported string namespace. If an import refers to the imported string namespace, then the import type is [matched](https://webassembly.github.io/spec/core/valid/types.html#globals) against an extern type of `(global (ref extern))`. If an import fails to match, then 'compile a module' fails. The resulting module is associated with the imported string namespace for use during instantiation. -During the ['read the imports'](https://webassembly.github.io/spec/js-api/index.html#read-the-imports) step of the JS-API, if the module has an imported string namespace, then every import that refers to this namespace has a global created to hold the string constant specified in the import field. This global is added to the imports object. +During the ['read the imports'](https://webassembly.github.io/spec/js-api/index.html#read-the-imports) step of the JS-API, if the module has an imported string namespace, then every import that refers to this namespace has a global created to hold the string constant specified in the import field. This global is added to the imports object. If all imports in a module are from the imported string namespace, no import object needs to be provided. When the imports object is used during ['instantiate a module'](https://webassembly.github.io/spec/js-api/index.html#instantiate-the-core-of-a-webassembly-module), these implicitly created globals should never cause a link error due to the eager matching done in 'compile a module'.