Repository navigation
Conversation
|
|
|
Ok, this one should "just work" (except for the cwd issue above), but var Binaryen = ...;
// can test if already ready
console.log(Binaryen.isReady);
// or just use a promise and wait for it, no matter if already ready
Binaryen.ready.then(function() {
...
}, function(err) { throw err; });
// or if you like it rather fancy
(async function() {
await Binaryen.ready;
...
})(); |
|
Actually I figured that Remains the cwd issue. |
last CI run failed with 'process out of memory'?!
|
For the cwd, you can use |
|
Maybe we could use How about disabling async compilation, does that work in node? (I know it would fail in chrome, but maybe v8 in node.js is more tolerant of sync compilation?) |
|
Hmm, I really thought Module['locateFile'] = function(file) {
throw "locateFile called: " + file;
};
Object.defineProperty(Module, 'filePackagePrefixURL', {
get: function() {
throw "filePackagePrefixURL accessed";
}
});Any ideas? |
|
The place where it should call |
|
Seems |
|
That.. would be very odd if true :) the pre-js goes before the "prelude" file which is where the integrate method is. Is the pre-js queuing code to happen asynchronously later perhaps? |
|
Scratch that, I have two |
… in build-js.sh for Windows compatibility
| -s MODULARIZE_INSTANCE=1 \ | ||
| -s 'EXPORT_NAME="Binaryen"' \ | ||
| --post-js $BINARYEN_SRC/js/binaryen.js-post.js | ||
| -s NO_EXIT_RUNTIME=0 \ |
There was a problem hiding this comment.
Without, there is a warning when running binaryen-wasm.js. Is that correct?
There was a problem hiding this comment.
Something about atexits? That's expected when assertions are on, but not in an optimized build. So we shouldn't see it here, I don't think. Or was it something else?
There was a problem hiding this comment.
Let me double check
There was a problem hiding this comment.
You are right, this must have been caused by something else.
| @@ -0,0 +1,12 @@ | |||
| // Make sure node is able to find the .wasm next to the .js file. Only relevant | |||
| // when building binaryen-wasm.js (not used for binaryen.js currently). | |||
| if ( | |||
There was a problem hiding this comment.
as this is a pre-js, you can actually just check the ENVIRONMENT_IS_NODE variable
There was a problem hiding this comment.
I tried, but it wasn't defined already at this point.
There was a problem hiding this comment.
Just checked again without a minifier. Appears pre-js goes right after if (!Module) Module = typeof Binaryen !== 'undefined' ? Binaryen : {}; (starts at line 21) while ENVIRONMENT_IS_NODE is defined a bit later (line 63).
var Binaryen = function(Binaryen) {
Binaryen = Binaryen || {};
// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) { ..generated code.. }
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to check if Module already exists (e.g. case 3 above).
// Substitution will be replaced with actual code on later stage of the build,
// this way Closure Compiler will not mangle it (e.g. case 4. above).
// Note that if you want to run closure, and also to use Module
// after the generated code, you will need to define var Module = {};
// before the code. Then that object will be used in the code, and you
// can continue to use Module afterwards as well.
// if (!Module)` is crucial for Closure Compiler here as it will otherwise replace every `Module` occurrence with a string
var Module;
if (!Module) Module = typeof Binaryen !== 'undefined' ? Binaryen : {};
// --pre-jses are emitted after the Module integration code, so that they can
// refer to Module (if they choose; they can also define Module)
// Make sure node is able to find the .wasm next to the .js file. Only relevant
// when building binaryen-wasm.js (not used for binaryen.js currently).
if (
typeof process === 'object' && typeof require === 'function' && // IS_NODE
typeof window !== 'object' && // !IS_WEB
typeof importScripts !== 'function' // !IS_WORKER
) {
Module['locateFile'] = function(file) {
var nodePath = require('path');
return nodePath.join(__dirname, file);
};
}
// Sometimes an existing Module object exists with properties
// meant to overwrite the default module functionality. Here
// we collect those properties and reapply _after_ we configure
// the current environment's defaults to avoid having to be so
// defensive during initialization.
var moduleOverrides = {};
var key;
for (key in Module) {
if (Module.hasOwnProperty(key)) {
moduleOverrides[key] = Module[key];
}
}
Module['arguments'] = [];
Module['thisProgram'] = './this.program';
Module['quit'] = function(status, toThrow) {
throw toThrow;
};
Module['preRun'] = [];
Module['postRun'] = [];
// The environment setup code below is customized to use Module.
// *** Environment setup code ***
var ENVIRONMENT_IS_WEB = false;
var ENVIRONMENT_IS_WORKER = false;
var ENVIRONMENT_IS_NODE = false;
var ENVIRONMENT_IS_SHELL = false;
...There was a problem hiding this comment.
Oh right, the pre-js goes before everything...
There was a problem hiding this comment.
Would it make sense to move just the ENVIRONMENT_IS_XY definitions up so pre-js can use/modify them? Could create a PR for this if it makes sense.
There was a problem hiding this comment.
|
Just figured that |
| cmd = [engine, 'a.js'] | ||
| def test(engine, runner): | ||
| print runner + ": " + s | ||
| f = open(os.path.join(options.binaryen_bin, 'a.js'), 'w') |
There was a problem hiding this comment.
adding files to bin/ should be avoided. one option is to clean up those files, but then there's a risk of not reaching the cleanup code. how about copying the js and wasm files into the current dir? if we forget them there, that's less bad than leaving them in the bin dir. Even better would be to do this in a new subdir just for testing, perhaps, like test/temp/.
There was a problem hiding this comment.
The current dir is the project's base directory, where a.js was generated before, which wasn't that great either. Hence, a temp directory sounds ideal, will take a look.
|
About the synchronous/asynchronous issues,
|
I know that node.js supports
Binaryen.ready.then(() => {
... use it ...
});
If I understood correctly, there is no way to do synchronous loading in browsers anyway if one wants to use an additional .wasm file (not embedded as base64 or something), is this right? If so, the default case should be asynchronous anyway because there's at least one important target that doesn't support synchronous instantiation. From Or, in other words: Switching synchronous |
|
Yeah, makes sense overall. About I see that Parcel allows synchronous syntax for loading wasm, by translating it to async at bundling time. We probably don't want to depend on a specific bundler, though, but that would have been nice... |
|
Currently it looks like this: import { Binaryen } from "./binaryen-wasm.js";
Binaryen.ready.then(...);or import { Binaryen } from "./binaryen-wasm.js";
await Binaryen.ready;
...
import { Binaryen } from "./binaryen-wasm.js";
Binaryen.then(...);or import { Binaryen } from "./binaryen-wasm.js";
await Binaryen;
...
I don't think that we can hook to |
|
Looked this up pretty quick: It seems we can actually do that import thing. The only thing necessary is to return a promise as the module's export. Does this already work with just |
|
I think the Modularize Anyhow, I don't want to block this PR on all these larger issues. But picking the API (with |
|
I've worked something out here, which essentially makes every module a valid promise by means of Btw, if we stuff PromisedModule into pre-js for now, it sould already work that way in binaryen.js/binaryen-wasm.js. Might be useful as a testing ground for this functionality, and if it turns out to be good enough, could translate to Emscripten. Edit: Tweaked it a bit so it behaves correctly in chaining scenarios. |
|
The obvious alternative here is to simply provide a common
In any case, the result of .ready would be a ready to use module. In MODULARIZE it is a unique one, with its own memory etc., while in MODULARIZE_INSTANCE it's always the same one. In this case, binaryen.js in its current state could be used as a test case, without changes, as it implemements the second. Btw, libwabt.js uses such a ready promise. |
|
I think I'd favor the |
|
Interesting about wabt using |
Not that I'm aware of. I guess it just makes sense to use a Promise, and to use |
|
I see. Well, I don't really have strong thoughts on the API one way or another, just trying to keep us consistent with other stuff... :) I'm ok to merge this in unless you think there's more to discuss. I am somewhat worried about us already having a non- |
|
Superseded by #2503 |
This PR enables compiling Binaryen to WebAssembly when building binaryen.js. Since WebAssembly is best compiled and instantiated asynchronously in browsers, it also adds a new mechanism to tell if respectively when the module is ready by means of one of the following:
// Using a promise
const binaryen = require("binaryen");
binaryen.ready.then(() => {
... use normally ...
});
// Using await
const binaryen = require("binaryen");
(async () => {
await binaryen.ready;
... use normally ...
})();
// Where top-level await is available
const binaryen = await require("binaryen").ready;
... use normally ...
One can also tell if Binaryen is already ready (for example when assuming it in follow-up code) by:
if (/* we already know that */ binaryen.isReady) {
... use normally ...
} else {
throw Error("Binaryen is supposed to be ready here but isn't");
}
The JS test cases have been updated accordingly by wrapping everything in a test function and invoking it once ready. Documentation will have to be updated as well to cover this of course. New file size is about 2.5mb, even though the Wasm becomes inlined into the JS file which makes distribution across different environments a lot easier.
Also makes building binaryen (to either js or wasm) emit binaryen.js, and not binaryen_js.js etc.
Supersedes and thus fixes #1381
With .ready it also fixes #2452
This PR enables compiling Binaryen to WebAssembly when building binaryen.js. Since WebAssembly is best compiled and instantiated asynchronously in browsers, it also adds a new mechanism to tell if respectively when the module is ready by means of one of the following:
// Using a promise
const binaryen = require("binaryen");
binaryen.ready.then(() => {
... use normally ...
});
// Using await
const binaryen = require("binaryen");
(async () => {
await binaryen.ready;
... use normally ...
})();
// Where top-level await is available
const binaryen = await require("binaryen").ready;
... use normally ...
One can also tell if Binaryen is already ready (for example when assuming it in follow-up code) by:
if (/* we already know that */ binaryen.isReady) {
... use normally ...
} else {
throw Error("Binaryen is supposed to be ready here but isn't");
}
The JS test cases have been updated accordingly by wrapping everything in a test function and invoking it once ready. Documentation will have to be updated as well to cover this of course. New file size is about 2.5mb, even though the Wasm becomes inlined into the JS file which makes distribution across different environments a lot easier.
Also makes building binaryen (to either js or wasm) emit binaryen.js, and not binaryen_js.js etc.
Supersedes and thus fixes #1381
With .ready it also fixes #2452
This PR adds another build target to
build-js.shbuilding a WebAssembly version using the JS wrapper asbinaryen-wasm.js.It already works (can run the kitchen-sink.js test) under the following conditions:
binaryen-wasm.jsmust be required from the./bindirectory because it otherwise can't findbinaryen-wasm.wasmnext to it (looks in the current working directory instead?).When not using node.js (which seems to synchronously instantiate the module working around this issue), there is no mechanism yet to tell when the module is ready.Opening this PR so we can figure something out :)
See also: #1380