mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Declare the WebAssembly W5 and stream-slot entry points in the runtime headers
The backend can emit scr_wasm_memory_construct, scr_wasm_table_construct, scr_wasm_global_construct, scr_wasm_construct_without_new, scr_wasm_module_imports, scr_wasm_module_exports, scr_wasm_module_custom_sections and scr_wasm_value_of (#1410), and scr_stream_dyn_native, scr_stream_pipe_dyn and scr_stream_unpipe_dyn (#1524). Their prototypes were in scr_wasm.c or nowhere, so the runtime ABI guard failed. They are now in scr_wasm.h and scr_stream.h, and scr_wasm.c no longer repeats the header's declarations. The speculative-hoisting test relied on `v instanceof Num` in a JavaScript function failing, which constructor-function instanceof now compiles (#1512). Its hoisted function reads the prototype through Reflect.getPrototypeOf instead, which still fences.
This commit is contained in:
@@ -9,7 +9,9 @@ import type { IrModule } from "../src/ir/ir.js";
|
||||
// list above the constructor. The initializer lowers speculatively first,
|
||||
// which hoists the constructor and the helper it calls. Those bodies are
|
||||
// kept, so their failing statements must keep runtime fences; dropping
|
||||
// them left `isNum` without its return (an SC9002 trap at load).
|
||||
// them left `isNum` without its return (an SC9002 trap at load). isNum's
|
||||
// return reads the prototype through Reflect.getPrototypeOf, which has no
|
||||
// lowering, so it fences.
|
||||
const source = `
|
||||
function clone(config) {
|
||||
var P = (Num.prototype = { constructor: Num, toString: null }),
|
||||
@@ -20,7 +22,7 @@ function clone(config) {
|
||||
x.v = isNum(v) ? 0 : v * unit;
|
||||
}
|
||||
function isNum(v) {
|
||||
return v instanceof Num || (!!v && v._isNum === true);
|
||||
return Reflect.getPrototypeOf(v) === P || (!!v && v._isNum === true);
|
||||
}
|
||||
P._isNum = true;
|
||||
return Num;
|
||||
@@ -59,6 +61,6 @@ test("speculatively hoisted JavaScript functions keep their statement fences", a
|
||||
const mod = await lower();
|
||||
const isNum = mod.functions.find((fn) => fn.name.endsWith("_isNum"));
|
||||
expect(isNum).toBeDefined();
|
||||
expect(fenceCodes(isNum!.body)).toEqual(["SC1090"]);
|
||||
expect(fenceCodes(isNum!.body)).toEqual(["SC2020"]);
|
||||
expect(mod.functions.flatMap((fn) => fenceCodes(fn.body))).not.toContain("SC9002");
|
||||
});
|
||||
|
||||
@@ -136,6 +136,13 @@ ScrStream *scr_stream_pipe_general(ScrStream *src, ScrStream *dst, bool end);
|
||||
/* A boxed native stream out of a checked-dynamic pipeline stage (+1), or
|
||||
* NULL with `message` thrown as the not-supported Error. */
|
||||
ScrStream *scr_stream_unbox_dyn(const struct ScrDyn *value, const ScrStr *message);
|
||||
/* Checked-dynamic stream slots (scr_stream_dyn.c): the native stream a
|
||||
* value boxes with the requested side (1 readable, 2 writable; +1, or
|
||||
* NULL), and readable.pipe()/unpipe() for a destination that is not a
|
||||
* native stream. */
|
||||
ScrStream *scr_stream_dyn_native(const struct ScrDyn *value, double side);
|
||||
void scr_stream_pipe_dyn(ScrStream *src, struct ScrDyn *src_box, struct ScrDyn *dest, bool end);
|
||||
void scr_stream_unpipe_dyn(ScrStream *src, struct ScrDyn *dest);
|
||||
ScrStream *scr_stream_new_duplex_dyn(struct ScrDyn *opts);
|
||||
ScrStream *scr_stream_new_transform_dyn(struct ScrDyn *opts);
|
||||
ScrStream *scr_stream_new_passthrough_dyn(struct ScrDyn *opts);
|
||||
|
||||
@@ -90,25 +90,6 @@
|
||||
#define SCR_WASM_ASAN 1
|
||||
#endif
|
||||
|
||||
ScrPromise *scr_wasm_compile(ScrDyn *bytes);
|
||||
bool scr_wasm_validate(ScrDyn *bytes);
|
||||
ScrPromise *scr_wasm_instantiate(ScrDyn *source, ScrDyn *imports);
|
||||
ScrDyn *scr_wasm_module_new(ScrDyn *bytes);
|
||||
ScrDyn *scr_wasm_instance_new(ScrDyn *module, ScrDyn *imports);
|
||||
bool scr_wasm_is(const ScrDyn *value, double kind);
|
||||
ScrDyn *scr_wasm_error_new(double kind, ScrDyn *message, ScrDyn *options);
|
||||
ScrDyn *scr_wasm_function(double kind);
|
||||
ScrDyn *scr_wasm_namespace(void);
|
||||
ScrDyn *scr_wasm_global_view(void);
|
||||
ScrDyn *scr_wasm_memory_construct(ScrDyn *descriptor);
|
||||
ScrDyn *scr_wasm_table_construct(ScrDyn *descriptor, ScrDyn *value);
|
||||
ScrDyn *scr_wasm_global_construct(ScrDyn *descriptor, ScrDyn *value);
|
||||
ScrDyn *scr_wasm_construct_without_new(double kind, ScrDyn *arg0, ScrDyn *arg1);
|
||||
ScrDyn *scr_wasm_module_imports(ScrDyn *module);
|
||||
ScrDyn *scr_wasm_module_exports(ScrDyn *module);
|
||||
ScrDyn *scr_wasm_module_custom_sections(ScrDyn *module, ScrDyn *name);
|
||||
ScrDyn *scr_wasm_value_of(ScrDyn *value);
|
||||
|
||||
/* Entry points of translated code. */
|
||||
/* Sanitized builds do not declare it noreturn: AddressSanitizer would
|
||||
* call __asan_handle_no_return before every call, which warns on the
|
||||
|
||||
@@ -19,5 +19,13 @@ ScrDyn *scr_wasm_error_new(double kind, ScrDyn *message, ScrDyn *options);
|
||||
ScrDyn *scr_wasm_function(double kind);
|
||||
ScrDyn *scr_wasm_namespace(void);
|
||||
ScrDyn *scr_wasm_global_view(void);
|
||||
ScrDyn *scr_wasm_memory_construct(ScrDyn *descriptor);
|
||||
ScrDyn *scr_wasm_table_construct(ScrDyn *descriptor, ScrDyn *value);
|
||||
ScrDyn *scr_wasm_global_construct(ScrDyn *descriptor, ScrDyn *value);
|
||||
ScrDyn *scr_wasm_construct_without_new(double kind, ScrDyn *arg0, ScrDyn *arg1);
|
||||
ScrDyn *scr_wasm_module_imports(ScrDyn *module);
|
||||
ScrDyn *scr_wasm_module_exports(ScrDyn *module);
|
||||
ScrDyn *scr_wasm_module_custom_sections(ScrDyn *module, ScrDyn *name);
|
||||
ScrDyn *scr_wasm_value_of(ScrDyn *value);
|
||||
|
||||
#endif /* SCR_WASM_H */
|
||||
|
||||
Reference in New Issue
Block a user