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

Update JS API for exnref #301

Merged
merged 22 commits into from
Apr 11, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
apply review comments
  • Loading branch information
dschuff committed Apr 5, 2024
commit 51338d7e32f1129a9409e6f7c3d9436d5ff14b51
15 changes: 7 additions & 8 deletions document/js-api/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ urlPrefix: https://webassembly.github.io/exception-handling/core/; spec: WebAsse
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: tag type; url: syntax/types.html#syntax-tagtype
text: tag address; url: exec/runtime.html#syntax-tagaddr
text: tag_alloc; url: appendix/embedding.html#embed-tag-alloc
text: tag_type; url: appendix/embedding.html#embed-tag-type
Expand Down Expand Up @@ -1080,20 +1081,18 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
1. [=Clean up after running a callback=] with |stored settings|.
1. [=Clean up after running script=] with |relevant settings|.
1. Assert: |result|.\[[Type]] is <emu-const>throw</emu-const> or <emu-const>normal</emu-const>.
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then:
1. Let |v| be |result|.\[[Value]].
1. If |v| [=implements=] {{Exception}},
1. Let |type| be |v|.\[[Type]].
1. Let |payload| be |v|.\[[Payload]].
1. Let |address| be |v|.\[[Address]].
Copy link
Member

Choose a reason for hiding this comment

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

Does a WebAssembly.Exception object have Address?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, Address is initialized in "initialize an Exception object". Exception is now just like all the other JS-exposed objects which also have their wasm Addresses stored in an internal slot in the JS object. (Although I just noticed that the naming convention isn't consistent right now; The Exception and Tag objects have the address in a field named Address whereas the rest have that field named after the object type, e.g. Global. Maybe I'll fix that in a followup change).

1. [=WebAssembly/Throw=] with |address|.
1. Otherwise,
1. Let |type| be the result of [=get the JavaScript exception tag |getting the JavaScript exception tag=].
1. Let |payload| be [=ToWebAssemblyValue=](|v|, [=externref=]).
1. Let |payload| be [=!=] [=ToWebAssemblyValue=](|v|, [=externref=]).
Copy link
Member

Choose a reason for hiding this comment

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

It looks v contains Type and Value. Shouldn't we only convert the Value part, rather than the whole v?

Copy link
Member Author

Choose a reason for hiding this comment

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

The Type and Value fields come from ECMAScript completion record, and result is the completion record.
On lines 1086 - 1087 above, result.Type is THROW and then v is result.Value, i.e. the value returned by the JS host function called on line 1081, so it's already a value. So I think that's the thing that we need to convert to a wasm externref and throw back into wasm.

... actually though, I just noticed that the handling of completion records between 'run a host function' and 'create a host function' wasn't quite right even before the EH spec. I just filed WebAssembly/spec#1743 about that.

1. Let (|store|, |address|) be [=exn_alloc=](|store|, |type|, « |payload| »).
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. [=WebAssembly/Throw=] with |address|.
1. Otherwise, return |result|.\[[Value]].
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1. Let (|store|, |funcaddr|) be [=func_alloc=](|store|, |functype|, |hostfunc|).
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. Return |funcaddr|.
Expand Down Expand Up @@ -1312,7 +1311,7 @@ constructor steps are:
1. Throw a {{TypeError}}.
1. Let |wasmPayload| be « ».
1. [=list/iterate|For each=] |value| and |resultType| of |payload| and |types|, paired linearly,
1. [=list/Append=] ? [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmPayload|.
1. [=list/Append=] [=?=] [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmPayload|.
1. Let (|store|, |exceptionAddr|) be [=exn_alloc=](|store|, |exceptionTag|.\[[Address]], |wasmPayload|)
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1. [=initialize an Exception object|Initialize=] **this** from |exceptionAddr|.
Expand Down Expand Up @@ -1357,7 +1356,7 @@ The <dfn attribute for="Exception">stack</dfn> getter steps are:

The <dfn>JavaScript exception tag</dfn> is a [=tag address=] associated with
the surrounding agent. It is allocated in the agent's [=associated store=] on
first use and cached. It always has the tag type « [=externref=] » → « ».
first use and cached. It always has the [=tag type=] « [=externref=] » → « ».


<div algorithm>
Expand All @@ -1376,7 +1375,7 @@ To <dfn>get the JavaScript exception tag</dfn>, perform the following steps:

<div algorithm>

To <dfn for=WebAssembly>throw</dfn> with a [=tag address=] |type|, a matching [=list=] of WebAssembly values |payload|, and an [=exception address=] |address|, perform the following steps:
To <dfn for=WebAssembly>throw</dfn> with an [=exception address=] |address|, perform the following steps:

1. Unwind the stack until reaching the *catching try block* given |type|.
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the main bit that still needs to be updated, as there is currently nothing in the embedding appendix that I could find that even describes calling from wasm into the embedder, and thus nowhere to put a description of what happens when such calls throw.

Copy link
Member

Choose a reason for hiding this comment

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

The problem is that this can not be an "external" function, since it could only be invoked inside a Wasm context. So it can't easily be defined as a proper embedder function, which need a closed evaluation context. To make it work, we would need to pass it the "current evaluation context", which would require means for reifying an entire host/Wasm execution. There is no way to make that work with the JS spec style.

But this algorithm is invoked from another one that already describes Wasm semantics, not host semantics. So we're morally "inside Wasm". So what I'd suggest is to say something like "execute the Wasm instructions (ref.exn |address|) (throw_ref).

And with my other comment there is only one place left where this is invoked, so I'd just inline that step there and remove this algorithm.

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense, done.

1. Invoke the catch block with |payload| and |address|.
Expand Down