Bug 265151 - `WebAssembly` is no longer part of the global object
Summary: `WebAssembly` is no longer part of the global object
Status: RESOLVED WONTFIX
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: Other
Hardware: Mac (Apple Silicon) macOS 14
: P2 Blocker
Assignee: Nobody
URL:
Keywords: BrowserCompat, InRadar
Depends on: 263763
Blocks:
  Show dependency treegraph
 
Reported: 2023-11-20 10:40 PST by Ivan Enderlin
Modified: 2023-11-23 13:48 PST (History)
6 users (show)

See Also:


Attachments
Test case (1.13 KB, text/x-csrc)
2023-11-20 20:47 PST, Ross Kirsling
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan Enderlin 2023-11-20 10:40:32 PST
Hi,

Before the update to macOS 14 (Sonoma), `WebAssembly` was defined on the global object (from a `JSContext` + `JSContextGetGlobalObject` + `JSObjectGetProperty`).  Since the update, `WebAssembly` is undefined. Worst: evaluating the following simple script `const wasm = WebAssembly.Instance` makes the process crash with a SIGSEGV. It seems to affect macOS and iOS (the latter must be confirmed). I'm using XCode 15. I'm also using the JavaScriptCore bundled framework, with the C API.

Is it normal? Is it expected? I didn't see any announcement or anything particular. It's a blocker because it's a breaking change.

Thanks for your help.
Comment 1 Ivan Enderlin 2023-11-20 10:46:48 PST
Other people reproduce the error, like here https://github.com/endoli/javascriptcore.rs/issues/33 or here https://mastodon.social/@ccgus/111428590581033066.
Comment 2 Karl Dubost 2023-11-20 14:33:41 PST
Thanks Ivan. 
Maybe Justin will have something to say about this.
Comment 3 Radar WebKit Bug Importer 2023-11-20 14:33:51 PST
<rdar://problem/118662587>
Comment 4 Karl Dubost 2023-11-20 14:35:32 PST
A clear simple testcase should be added to this bug report.
Comment 5 Ross Kirsling 2023-11-20 17:35:25 PST
(Note that bug 263763 is not relevant here; the patch that was ultimately landed there, 270100@main, just made it possible to pass --useWebAssembly=1 when JIT is off.)
Comment 6 Ross Kirsling 2023-11-20 20:47:14 PST
Created attachment 468698 [details]
Test case

Hmm, I'm not managing to reproduce this on an Intel MBP with Sonoma 14.1.1 (Safari 17.1, Xcode 15.0.1).

The attached test file does what was described in the bug report, namely:
1. get WebAssembly property on global object and verify it's an object with an Instance property
2. execute the one-line script `const wasm = WebAssembly.Instance;`

Compiling this with the following command produces an executable which works as expected:
> clang++ -framework JavaScriptCore -std=c++20 -o ./main wasm-test.cpp

It also works via Xcode, by setting up a Command Line Tool project which depends on JavaScriptCore.framework.
Comment 7 Ivan Enderlin 2023-11-20 23:30:59 PST
Thanks Ross for your test case. I've modified line 11 to:

```cpp
    assert(!exception);
    assert(JSValueIsObject(globalContext, wasmValue));
```

Running the script if your command-line:

```shell
$ clang++ -framework JavaScriptCore -std=c++20 -o ./wasm-test wasm-test.cp
$ ./wasm-test
Assertion failed: (JSValueIsObject(globalContext, wasmValue)), function main, file wasm-test.cpp, line 12.
```

I've added this new assertion before line 11:

```cpp
    assert(JSValueIsUndefined(globalContext, wasmValue));
```

and it passes. So `wasmValue` is indeed undefined, and… `WebAssembly` isn't a property of the global object.

I'm using macOS Sonoma 14.1.1 (23B81) if that helps, on a MacBook Pro M1.
Comment 8 Ivan Enderlin 2023-11-21 00:01:09 PST
Someone else has tried this test program on macOS Sonoma, but on x86_64, and it works, just like for Ross. It seems to be an issue on aarch64 only. Maybe.
Comment 9 Ross Kirsling 2023-11-21 05:13:42 PST
(In reply to Ivan Enderlin from comment #8)
> Someone else has tried this test program on macOS Sonoma, but on x86_64, and
> it works, just like for Ross. It seems to be an issue on aarch64 only. Maybe.

Looks like it. I've had a chance to try on an M1 machine now, and I repro the behavior you describe (though unfortunately I won't have time to dig deeper right away).
Comment 10 Mark Lam 2023-11-21 07:58:47 PST
Ivan, your test case implies that you're using the JSC API, which I don't think officially supported WebAssembly.  WebAssembly is still available in WebViews.

You say this is a breaking change and a blocker.  What app is this breaking, and why does it need WebAssembly?  Thanks.
Comment 11 Ivan Enderlin 2023-11-21 08:06:30 PST
Mark, I'm using JSC to execute Wasm on iOS, where I can't use another Wasm runtime (like wasmtime for instance). Our Rust SDK needs to work on multiple platforms.

`WebAssembly` is defined in the global object, except now on aarch64, but I believe it's a bug/regression. It was previously working, it's no longer the case only on aarch64, that's a good sign of a regression :-). I've not tested on iOS though, but we need it to work on macOS too for development purposes.

Using a WebView isn't an option here, it would imply to rewrite an entire component of our infrastructure just because of this regression.
Comment 12 Mark Lam 2023-11-21 08:26:06 PST
(In reply to Ivan Enderlin from comment #11)
> Mark, I'm using JSC to execute Wasm on iOS, where I can't use another Wasm
> runtime (like wasmtime for instance). Our Rust SDK needs to work on multiple
> platforms.
> 
> `WebAssembly` is defined in the global object, except now on aarch64, but I
> believe it's a bug/regression. It was previously working, it's no longer the
> case only on aarch64, that's a good sign of a regression :-). I've not
> tested on iOS though, but we need it to work on macOS too for development
> purposes.
> 
> Using a WebView isn't an option here, it would imply to rewrite an entire
> component of our infrastructure just because of this regression.

Currently, JSC's Wasm implementation still requires JIT support in order to work. On iOS, JSC API clients never had JIT support.  So, it's never been possible to run Wasm on iOS via a JSC API client.  If you were using a WKWebView / SFSafariViewController, then Wasm is available.  If `WebAssembly` is defined in the global object via the JSC API on iOS, then that's a bug that the symbol was ever exposed.  Even so, Wasm would not have run.

On macOS for aarch64, if your app is opted into the hardened runtime option (which adds greater security), then there is also no JIT support via the JSC APIs.  This has been the case since before macOS Sonoma.  Hence, it is not a regression.  However, if your app did not opt into the hardened runtime, then it will be able to use the JIT, and Wasm will work.
Comment 13 Ivan Enderlin 2023-11-21 08:38:12 PST
Mark, do you mean that the fact it was working before _was a bug_, and now it _is fixed_? Well, since it works on x86_64, it means that the bug “is fixed” only on aarch64, but not yet on x86_64?

What I don't understand is: where/how LLInt fits here? If JIT is disabled, isn't it possible to run Wasm only with the interpreter? That's what I thought was happening to be honest.
Comment 14 Ivan Enderlin 2023-11-21 09:11:23 PST
With this patch https://github.com/WebKit/WebKit/commit/2c0494fcc3fe018670c408476931c3698d9b2ee2, it is possible to use WebAssembly if JIT is off/disabled. Why JSC C API cannot have this configuration by default?

Again, since this bug (described here) only happens on aarch64, is WebAssembly turns on and JIT off for x86_84?
Comment 15 Mark Lam 2023-11-21 09:57:33 PST
(In reply to Ivan Enderlin from comment #13)
> Mark, do you mean that the fact it was working before _was a bug_, and now
> it _is fixed_? Well, since it works on x86_64, it means that the bug “is
> fixed” only on aarch64, but not yet on x86_64?

You were mistaken about it ever working on iOS.

On macOS, I think x86_64 does not support the hardened runtime option in your Xcode project.  On aarch64, the hardened runtime option is supported.  If you enable the hardened runtime option, then JIT will not be supported and you won’t be able to use Wasm.  If you disable it, you can use it if you disable the hardened runtime option for your app’s Xcode project.


> What I don't understand is: where/how LLInt fits here? If JIT is disabled,
> isn't it possible to run Wasm only with the interpreter? That's what I
> thought was happening to be honest.

The current Wasm implementation still use JIT glue for marshaling arguments.  Even the LLInt replies in this.

(In reply to Ivan Enderlin from comment #14)
> With this patch
> https://github.com/WebKit/WebKit/commit/
> 2c0494fcc3fe018670c408476931c3698d9b2ee2, it is possible to use WebAssembly
> if JIT is off/disabled. Why JSC C API cannot have this configuration by
> default?

That is Sony’s prep work for paving the way to Wasm LLInt working without JIT.  AFAIK, LLInt still relies on JIT glue code today.

> Again, since this bug (described here) only happens on aarch64, is
> WebAssembly turns on and JIT off for x86_84?

Again, this is not a bug and there is no regression. The feature you’re asking for has never existed on iOS.  On macOS, you can use Wasm if you opt out of the hardened runtime option in your Xcode project.
Comment 16 Ivan Enderlin 2023-11-22 00:11:45 PST
Mark,

I can't use a `WKWebView` because I need my Wasm module import functions to be defined as JS callbacks, so that I can implement them in Rust. As far as I know, it's not possible to pass `Function` objects from the “host” to a `WKWebView` via `postMessage`. Is there a safe way to achieve that maybe?

> You were mistaken about it ever working on iOS.

I'm sorry but… before running into this project, we have tested running Wasm on iOS and it was working great via JSC. 2 persons have tested it on 2 different devices, and we have seen the same thing: Wasm was running on iOS via JSC. 

Anyway, is there a chance that we will be able to run Wasm in a short-future without JIT, only purely with LLInt? Or is there a chance that JIT will be enabled inside JSC C API? Do you have a public roadmap about that topic?

Thanks.
Comment 17 Justin Michaud 2023-11-22 17:34:12 PST
>I can't use a `WKWebView` because I need my Wasm module import functions to be defined as JS callbacks

If you try https://developer.apple.com/documentation/webkit/wkscriptmessagehandler with worker + SAB + Async.await, you can probably get a nice speed improvement.

In particular, I have been meaning to hack up a demo of how to do this for a while. It is a recipe for a much more responsive user experience, but I understand it is a lot of glue code.

> I'm sorry but… before running into this project, we have tested running Wasm on iOS and it was working great via JSC

Do you have a test case that reproduces this? The current test case does not actually execute any wasm. As Mark said, this should have crashed the second you tried to actually use WASM, unless you were using a WKWebView. Simulator acts mostly like macOS, so it is super important to test on real hardware.

> Anyway, is there a chance that we will be able to run Wasm in a short-future without JIT, only purely with LLInt? Or is there a chance that JIT will be enabled inside JSC C API? Do you have a public roadmap about that topic?

We have nothing public at this time

> where I can't use another Wasm runtime
You totally can, you just can't use JIT. For example, this claims to support iOS: https://github.com/wasm3/wasm3 (I have never used this, this is not an endorsement).

We certainly do hope you try to use a WKWebView + callbacks though.

Above all, the key takeaway is this: 

***Opt out of hardened runtime on macOS to continue JITTIng. If that doesn't fix your problem, then this is a bug on our end that we need to fix. ***

If wasm was ever running on iOS outside of a WKWebView, that certainly surprises everyone on our end.

Cheers!
Comment 18 Ivan Enderlin 2023-11-23 02:48:46 PST
> Simulator acts mostly like macOS, so it is super important to test on real hardware.

It was using a simulator, which likely explains why it was working.

> You totally can, you just can't use JIT. For example, this claims to support iOS: https://github.com/wasm3/wasm3 (I have never used this, this is not an endorsement).


Yeah, I was trying to use `wasm3` or any other interpreters out there.

You should consider allowing Wasm to run with JavaScriptCore. That could be awesome :-).
Comment 19 Mark Lam 2023-11-23 13:48:46 PST
Resolving as WONTFIX because the code is behaving as intended.