From 39fb2960a0017208eecc441fe6f223716fe9f076 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 15:43:45 +0000 Subject: [PATCH 01/10] Stop using WIT's resource because handles and resources support were already removed in the main branch of wit-bindgen https://github.com/bytecodealliance/wit-bindgen/pull/346 --- ext/js/bindgen/rb-js-abi-host.c | 165 +++++++--------- ext/js/bindgen/rb-js-abi-host.h | 11 +- ext/js/bindgen/rb-js-abi-host.wit | 5 +- ext/witapi/bindgen/rb-abi-guest.c | 98 ++-------- ext/witapi/bindgen/rb-abi-guest.h | 28 +-- ext/witapi/bindgen/rb-abi-guest.wit | 8 +- ext/witapi/witapi-core.c | 27 ++- .../ruby-wasm-wasi/src/bindgen/intrinsics.js | 40 ---- .../src/bindgen/rb-abi-guest.d.ts | 63 +------ .../src/bindgen/rb-abi-guest.js | 137 ++------------ .../src/bindgen/rb-js-abi-host.d.ts | 15 +- .../src/bindgen/rb-js-abi-host.js | 176 ++++++++---------- 12 files changed, 226 insertions(+), 547 deletions(-) diff --git a/ext/js/bindgen/rb-js-abi-host.c b/ext/js/bindgen/rb-js-abi-host.c index 44c3745bb..1379e7fbd 100644 --- a/ext/js/bindgen/rb-js-abi-host.c +++ b/ext/js/bindgen/rb-js-abi-host.c @@ -13,20 +13,6 @@ size_t new_size abort(); return ret; } - -__attribute__((import_module("canonical_abi"), import_name("resource_drop_js-abi-value"))) -void __resource_js_abi_value_drop(uint32_t idx); - -void rb_js_abi_host_js_abi_value_free(rb_js_abi_host_js_abi_value_t *ptr) { - __resource_js_abi_value_drop(ptr->idx); -} - -__attribute__((import_module("canonical_abi"), import_name("resource_clone_js-abi-value"))) -uint32_t __resource_js_abi_value_clone(uint32_t idx); - -rb_js_abi_host_js_abi_value_t rb_js_abi_host_js_abi_value_clone(rb_js_abi_host_js_abi_value_t *ptr) { - return (rb_js_abi_host_js_abi_value_t){__resource_js_abi_value_clone(ptr->idx)}; -} #include void rb_js_abi_host_string_set(rb_js_abi_host_string_t *ret, const char *s) { @@ -47,18 +33,6 @@ void rb_js_abi_host_string_free(rb_js_abi_host_string_t *ret) { ret->ptr = NULL; ret->len = 0; } -void rb_js_abi_host_js_abi_result_free(rb_js_abi_host_js_abi_result_t *ptr) { - switch ((int32_t) ptr->tag) { - case 0: { - rb_js_abi_host_js_abi_value_free(&ptr->val.success); - break; - } - case 1: { - rb_js_abi_host_js_abi_value_free(&ptr->val.failure); - break; - } - } -} void rb_js_abi_host_raw_integer_free(rb_js_abi_host_raw_integer_t *ptr) { switch ((int32_t) ptr->tag) { case 1: { @@ -68,14 +42,11 @@ void rb_js_abi_host_raw_integer_free(rb_js_abi_host_raw_integer_t *ptr) { } } void rb_js_abi_host_list_js_abi_value_free(rb_js_abi_host_list_js_abi_value_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - rb_js_abi_host_js_abi_value_free(&ptr->ptr[i]); - } if (ptr->len > 0) { free(ptr->ptr); } } -__attribute__((import_module("rb-js-abi-host"), import_name("eval-js: func(code: string) -> variant { success(handle), failure(handle) }"))) +__attribute__((import_module("rb-js-abi-host"), import_name("eval-js: func(code: string) -> variant { success(u32), failure(u32) }"))) void __wasm_import_rb_js_abi_host_eval_js(int32_t, int32_t, int32_t); void rb_js_abi_host_eval_js(rb_js_abi_host_string_t *code, rb_js_abi_host_js_abi_result_t *ret0) { @@ -87,88 +58,88 @@ void rb_js_abi_host_eval_js(rb_js_abi_host_string_t *code, rb_js_abi_host_js_abi variant.tag = (int32_t) (*((uint8_t*) (ptr + 0))); switch ((int32_t) variant.tag) { case 0: { - variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.success = (uint32_t) (*((int32_t*) (ptr + 4))); break; } case 1: { - variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.failure = (uint32_t) (*((int32_t*) (ptr + 4))); break; } } *ret0 = variant; } -__attribute__((import_module("rb-js-abi-host"), import_name("is-js: func(value: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("is-js: func(value: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_is_js(int32_t); bool rb_js_abi_host_is_js(rb_js_abi_host_js_abi_value_t value) { - int32_t ret = __wasm_import_rb_js_abi_host_is_js((value).idx); + int32_t ret = __wasm_import_rb_js_abi_host_is_js((int32_t) (value)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("instance-of: func(value: handle, klass: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("instance-of: func(value: u32, klass: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_instance_of(int32_t, int32_t); bool rb_js_abi_host_instance_of(rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_js_abi_value_t klass) { - int32_t ret = __wasm_import_rb_js_abi_host_instance_of((value).idx, (klass).idx); + int32_t ret = __wasm_import_rb_js_abi_host_instance_of((int32_t) (value), (int32_t) (klass)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("global-this: func() -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("global-this: func() -> u32"))) int32_t __wasm_import_rb_js_abi_host_global_this(void); rb_js_abi_host_js_abi_value_t rb_js_abi_host_global_this(void) { int32_t ret = __wasm_import_rb_js_abi_host_global_this(); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("int-to-js-number: func(value: s32) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("int-to-js-number: func(value: s32) -> u32"))) int32_t __wasm_import_rb_js_abi_host_int_to_js_number(int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_int_to_js_number(int32_t value) { int32_t ret = __wasm_import_rb_js_abi_host_int_to_js_number(value); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("float-to-js-number: func(value: float64) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("float-to-js-number: func(value: float64) -> u32"))) int32_t __wasm_import_rb_js_abi_host_float_to_js_number(double); rb_js_abi_host_js_abi_value_t rb_js_abi_host_float_to_js_number(double value) { int32_t ret = __wasm_import_rb_js_abi_host_float_to_js_number(value); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("string-to-js-string: func(value: string) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("string-to-js-string: func(value: string) -> u32"))) int32_t __wasm_import_rb_js_abi_host_string_to_js_string(int32_t, int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_string_to_js_string(rb_js_abi_host_string_t *value) { int32_t ret = __wasm_import_rb_js_abi_host_string_to_js_string((int32_t) (*value).ptr, (int32_t) (*value).len); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("bool-to-js-bool: func(value: bool) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("bool-to-js-bool: func(value: bool) -> u32"))) int32_t __wasm_import_rb_js_abi_host_bool_to_js_bool(int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_bool_to_js_bool(bool value) { int32_t ret = __wasm_import_rb_js_abi_host_bool_to_js_bool(value); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("proc-to-js-function: func(value: u32) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("proc-to-js-function: func(value: u32) -> u32"))) int32_t __wasm_import_rb_js_abi_host_proc_to_js_function(int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_proc_to_js_function(uint32_t value) { int32_t ret = __wasm_import_rb_js_abi_host_proc_to_js_function((int32_t) (value)); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> u32"))) int32_t __wasm_import_rb_js_abi_host_rb_object_to_js_rb_value(int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_rb_object_to_js_rb_value(uint32_t raw_rb_abi_value) { int32_t ret = __wasm_import_rb_js_abi_host_rb_object_to_js_rb_value((int32_t) (raw_rb_abi_value)); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-string: func(value: handle) -> string"))) +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-string: func(value: u32) -> string"))) void __wasm_import_rb_js_abi_host_js_value_to_string(int32_t, int32_t); void rb_js_abi_host_js_value_to_string(rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_string_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_js_value_to_string((value).idx, ptr); + __wasm_import_rb_js_abi_host_js_value_to_string((int32_t) (value), ptr); *ret0 = (rb_js_abi_host_string_t) { (char*)(*((int32_t*) (ptr + 0))), (size_t)(*((int32_t*) (ptr + 4))) }; } -__attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-integer: func(value: handle) -> variant { f64(float64), bignum(string) }"))) +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-integer: func(value: u32) -> variant { f64(float64), bignum(string) }"))) void __wasm_import_rb_js_abi_host_js_value_to_integer(int32_t, int32_t); void rb_js_abi_host_js_value_to_integer(rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_raw_integer_t *ret0) { __attribute__((aligned(8))) uint8_t ret_area[16]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_js_value_to_integer((value).idx, ptr); + __wasm_import_rb_js_abi_host_js_value_to_integer((int32_t) (value), ptr); rb_js_abi_host_raw_integer_t variant; variant.tag = (int32_t) (*((uint8_t*) (ptr + 0))); switch ((int32_t) variant.tag) { @@ -183,160 +154,160 @@ void rb_js_abi_host_js_value_to_integer(rb_js_abi_host_js_abi_value_t value, rb_ } *ret0 = variant; } -__attribute__((import_module("rb-js-abi-host"), import_name("export-js-value-to-host: func(value: handle) -> ()"))) +__attribute__((import_module("rb-js-abi-host"), import_name("export-js-value-to-host: func(value: u32) -> ()"))) void __wasm_import_rb_js_abi_host_export_js_value_to_host(int32_t); void rb_js_abi_host_export_js_value_to_host(rb_js_abi_host_js_abi_value_t value) { - __wasm_import_rb_js_abi_host_export_js_value_to_host((value).idx); + __wasm_import_rb_js_abi_host_export_js_value_to_host((int32_t) (value)); } -__attribute__((import_module("rb-js-abi-host"), import_name("import-js-value-from-host: func() -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("import-js-value-from-host: func() -> u32"))) int32_t __wasm_import_rb_js_abi_host_import_js_value_from_host(void); rb_js_abi_host_js_abi_value_t rb_js_abi_host_import_js_value_from_host(void) { int32_t ret = __wasm_import_rb_js_abi_host_import_js_value_from_host(); - return (rb_js_abi_host_js_abi_value_t){ ret }; + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("js-value-typeof: func(value: handle) -> string"))) +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-typeof: func(value: u32) -> string"))) void __wasm_import_rb_js_abi_host_js_value_typeof(int32_t, int32_t); void rb_js_abi_host_js_value_typeof(rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_string_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_js_value_typeof((value).idx, ptr); + __wasm_import_rb_js_abi_host_js_value_typeof((int32_t) (value), ptr); *ret0 = (rb_js_abi_host_string_t) { (char*)(*((int32_t*) (ptr + 0))), (size_t)(*((int32_t*) (ptr + 4))) }; } -__attribute__((import_module("rb-js-abi-host"), import_name("js-value-equal: func(lhs: handle, rhs: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-equal: func(lhs: u32, rhs: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_js_value_equal(int32_t, int32_t); bool rb_js_abi_host_js_value_equal(rb_js_abi_host_js_abi_value_t lhs, rb_js_abi_host_js_abi_value_t rhs) { - int32_t ret = __wasm_import_rb_js_abi_host_js_value_equal((lhs).idx, (rhs).idx); + int32_t ret = __wasm_import_rb_js_abi_host_js_value_equal((int32_t) (lhs), (int32_t) (rhs)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("js-value-strictly-equal: func(lhs: handle, rhs: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-strictly-equal: func(lhs: u32, rhs: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_js_value_strictly_equal(int32_t, int32_t); bool rb_js_abi_host_js_value_strictly_equal(rb_js_abi_host_js_abi_value_t lhs, rb_js_abi_host_js_abi_value_t rhs) { - int32_t ret = __wasm_import_rb_js_abi_host_js_value_strictly_equal((lhs).idx, (rhs).idx); + int32_t ret = __wasm_import_rb_js_abi_host_js_value_strictly_equal((int32_t) (lhs), (int32_t) (rhs)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-apply: func(target: handle, this-argument: handle, arguments: list>) -> variant { success(handle), failure(handle) }"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-apply: func(target: u32, this-argument: u32, arguments: list) -> variant { success(u32), failure(u32) }"))) void __wasm_import_rb_js_abi_host_reflect_apply(int32_t, int32_t, int32_t, int32_t, int32_t); void rb_js_abi_host_reflect_apply(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_js_abi_value_t this_argument, rb_js_abi_host_list_js_abi_value_t *arguments, rb_js_abi_host_js_abi_result_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_reflect_apply((target).idx, (this_argument).idx, (int32_t) (*arguments).ptr, (int32_t) (*arguments).len, ptr); + __wasm_import_rb_js_abi_host_reflect_apply((int32_t) (target), (int32_t) (this_argument), (int32_t) (*arguments).ptr, (int32_t) (*arguments).len, ptr); rb_js_abi_host_js_abi_result_t variant; variant.tag = (int32_t) (*((uint8_t*) (ptr + 0))); switch ((int32_t) variant.tag) { case 0: { - variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.success = (uint32_t) (*((int32_t*) (ptr + 4))); break; } case 1: { - variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.failure = (uint32_t) (*((int32_t*) (ptr + 4))); break; } } *ret0 = variant; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-construct: func(target: handle, arguments: list>) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-construct: func(target: u32, arguments: list) -> u32"))) int32_t __wasm_import_rb_js_abi_host_reflect_construct(int32_t, int32_t, int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_reflect_construct(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_list_js_abi_value_t *arguments) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_construct((target).idx, (int32_t) (*arguments).ptr, (int32_t) (*arguments).len); - return (rb_js_abi_host_js_abi_value_t){ ret }; + int32_t ret = __wasm_import_rb_js_abi_host_reflect_construct((int32_t) (target), (int32_t) (*arguments).ptr, (int32_t) (*arguments).len); + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-delete-property: func(target: handle, property-key: string) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-delete-property: func(target: u32, property-key: string) -> bool"))) int32_t __wasm_import_rb_js_abi_host_reflect_delete_property(int32_t, int32_t, int32_t); bool rb_js_abi_host_reflect_delete_property(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_delete_property((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); + int32_t ret = __wasm_import_rb_js_abi_host_reflect_delete_property((int32_t) (target), (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get: func(target: handle, property-key: string) -> variant { success(handle), failure(handle) }"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get: func(target: u32, property-key: string) -> variant { success(u32), failure(u32) }"))) void __wasm_import_rb_js_abi_host_reflect_get(int32_t, int32_t, int32_t, int32_t); void rb_js_abi_host_reflect_get(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key, rb_js_abi_host_js_abi_result_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_reflect_get((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, ptr); + __wasm_import_rb_js_abi_host_reflect_get((int32_t) (target), (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, ptr); rb_js_abi_host_js_abi_result_t variant; variant.tag = (int32_t) (*((uint8_t*) (ptr + 0))); switch ((int32_t) variant.tag) { case 0: { - variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.success = (uint32_t) (*((int32_t*) (ptr + 4))); break; } case 1: { - variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.failure = (uint32_t) (*((int32_t*) (ptr + 4))); break; } } *ret0 = variant; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get-own-property-descriptor: func(target: handle, property-key: string) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get-own-property-descriptor: func(target: u32, property-key: string) -> u32"))) int32_t __wasm_import_rb_js_abi_host_reflect_get_own_property_descriptor(int32_t, int32_t, int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_reflect_get_own_property_descriptor(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_get_own_property_descriptor((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); - return (rb_js_abi_host_js_abi_value_t){ ret }; + int32_t ret = __wasm_import_rb_js_abi_host_reflect_get_own_property_descriptor((int32_t) (target), (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get-prototype-of: func(target: handle) -> handle"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get-prototype-of: func(target: u32) -> u32"))) int32_t __wasm_import_rb_js_abi_host_reflect_get_prototype_of(int32_t); rb_js_abi_host_js_abi_value_t rb_js_abi_host_reflect_get_prototype_of(rb_js_abi_host_js_abi_value_t target) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_get_prototype_of((target).idx); - return (rb_js_abi_host_js_abi_value_t){ ret }; + int32_t ret = __wasm_import_rb_js_abi_host_reflect_get_prototype_of((int32_t) (target)); + return (uint32_t) (ret); } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-has: func(target: handle, property-key: string) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-has: func(target: u32, property-key: string) -> bool"))) int32_t __wasm_import_rb_js_abi_host_reflect_has(int32_t, int32_t, int32_t); bool rb_js_abi_host_reflect_has(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_has((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); + int32_t ret = __wasm_import_rb_js_abi_host_reflect_has((int32_t) (target), (int32_t) (*property_key).ptr, (int32_t) (*property_key).len); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-is-extensible: func(target: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-is-extensible: func(target: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_reflect_is_extensible(int32_t); bool rb_js_abi_host_reflect_is_extensible(rb_js_abi_host_js_abi_value_t target) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_is_extensible((target).idx); + int32_t ret = __wasm_import_rb_js_abi_host_reflect_is_extensible((int32_t) (target)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-own-keys: func(target: handle) -> list>"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-own-keys: func(target: u32) -> list"))) void __wasm_import_rb_js_abi_host_reflect_own_keys(int32_t, int32_t); void rb_js_abi_host_reflect_own_keys(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_list_js_abi_value_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_reflect_own_keys((target).idx, ptr); + __wasm_import_rb_js_abi_host_reflect_own_keys((int32_t) (target), ptr); *ret0 = (rb_js_abi_host_list_js_abi_value_t) { (rb_js_abi_host_js_abi_value_t*)(*((int32_t*) (ptr + 0))), (size_t)(*((int32_t*) (ptr + 4))) }; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-prevent-extensions: func(target: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-prevent-extensions: func(target: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_reflect_prevent_extensions(int32_t); bool rb_js_abi_host_reflect_prevent_extensions(rb_js_abi_host_js_abi_value_t target) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_prevent_extensions((target).idx); + int32_t ret = __wasm_import_rb_js_abi_host_reflect_prevent_extensions((int32_t) (target)); return ret; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set: func(target: handle, property-key: string, value: handle) -> variant { success(handle), failure(handle) }"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set: func(target: u32, property-key: string, value: u32) -> variant { success(u32), failure(u32) }"))) void __wasm_import_rb_js_abi_host_reflect_set(int32_t, int32_t, int32_t, int32_t, int32_t); void rb_js_abi_host_reflect_set(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key, rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_js_abi_result_t *ret0) { __attribute__((aligned(4))) uint8_t ret_area[8]; int32_t ptr = (int32_t) &ret_area; - __wasm_import_rb_js_abi_host_reflect_set((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, (value).idx, ptr); + __wasm_import_rb_js_abi_host_reflect_set((int32_t) (target), (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, (int32_t) (value), ptr); rb_js_abi_host_js_abi_result_t variant; variant.tag = (int32_t) (*((uint8_t*) (ptr + 0))); switch ((int32_t) variant.tag) { case 0: { - variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.success = (uint32_t) (*((int32_t*) (ptr + 4))); break; } case 1: { - variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) }; + variant.val.failure = (uint32_t) (*((int32_t*) (ptr + 4))); break; } } *ret0 = variant; } -__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set-prototype-of: func(target: handle, prototype: handle) -> bool"))) +__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set-prototype-of: func(target: u32, prototype: u32) -> bool"))) int32_t __wasm_import_rb_js_abi_host_reflect_set_prototype_of(int32_t, int32_t); bool rb_js_abi_host_reflect_set_prototype_of(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_js_abi_value_t prototype) { - int32_t ret = __wasm_import_rb_js_abi_host_reflect_set_prototype_of((target).idx, (prototype).idx); + int32_t ret = __wasm_import_rb_js_abi_host_reflect_set_prototype_of((int32_t) (target), (int32_t) (prototype)); return ret; } diff --git a/ext/js/bindgen/rb-js-abi-host.h b/ext/js/bindgen/rb-js-abi-host.h index 25ba556d0..1b58fddf1 100644 --- a/ext/js/bindgen/rb-js-abi-host.h +++ b/ext/js/bindgen/rb-js-abi-host.h @@ -8,12 +8,6 @@ extern "C" #include #include - typedef struct { - uint32_t idx; - } rb_js_abi_host_js_abi_value_t; - void rb_js_abi_host_js_abi_value_free(rb_js_abi_host_js_abi_value_t *ptr); - rb_js_abi_host_js_abi_value_t rb_js_abi_host_js_abi_value_clone(rb_js_abi_host_js_abi_value_t *ptr); - typedef struct { char *ptr; size_t len; @@ -22,6 +16,10 @@ extern "C" void rb_js_abi_host_string_set(rb_js_abi_host_string_t *ret, const char *s); void rb_js_abi_host_string_dup(rb_js_abi_host_string_t *ret, const char *s); void rb_js_abi_host_string_free(rb_js_abi_host_string_t *ret); + // A JavaScript value. In the future, this will be replaced by handle types. + // The underlying value should be owned by the JavaScript host environment + // and should live at least until all handles to it are dropped. + typedef uint32_t rb_js_abi_host_js_abi_value_t; typedef struct { uint8_t tag; union { @@ -31,7 +29,6 @@ extern "C" } rb_js_abi_host_js_abi_result_t; #define RB_JS_ABI_HOST_JS_ABI_RESULT_SUCCESS 0 #define RB_JS_ABI_HOST_JS_ABI_RESULT_FAILURE 1 - void rb_js_abi_host_js_abi_result_free(rb_js_abi_host_js_abi_result_t *ptr); typedef struct { uint8_t tag; union { diff --git a/ext/js/bindgen/rb-js-abi-host.wit b/ext/js/bindgen/rb-js-abi-host.wit index 8d8a116ec..70ae06c24 100644 --- a/ext/js/bindgen/rb-js-abi-host.wit +++ b/ext/js/bindgen/rb-js-abi-host.wit @@ -1,4 +1,7 @@ -resource js-abi-value +/// A JavaScript value. In the future, this will be replaced by handle types. +/// The underlying value should be owned by the JavaScript host environment +/// and should live at least until all handles to it are dropped. +type js-abi-value = u32 variant js-abi-result { success(js-abi-value), diff --git a/ext/witapi/bindgen/rb-abi-guest.c b/ext/witapi/bindgen/rb-abi-guest.c index ec95070cc..d5b2b6984 100644 --- a/ext/witapi/bindgen/rb-abi-guest.c +++ b/ext/witapi/bindgen/rb-abi-guest.c @@ -13,74 +13,6 @@ size_t new_size abort(); return ret; } - -__attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-iseq"))) -void __resource_rb_iseq_drop(uint32_t idx); - -void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr) { - __resource_rb_iseq_drop(ptr->idx); -} - -__attribute__((import_module("canonical_abi"), import_name("resource_clone_rb-iseq"))) -uint32_t __resource_rb_iseq_clone(uint32_t idx); - -rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr) { - return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_clone(ptr->idx)}; -} - -__attribute__((import_module("canonical_abi"), import_name("resource_new_rb-iseq"))) -uint32_t __resource_rb_iseq_new(uint32_t val); - -rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data) { - return (rb_abi_guest_rb_iseq_t){__resource_rb_iseq_new((uint32_t) data)}; -} - -__attribute__((import_module("canonical_abi"), import_name("resource_get_rb-iseq"))) -uint32_t __resource_rb_iseq_get(uint32_t idx); - -void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr) { - return (void*) __resource_rb_iseq_get(ptr->idx); -} - -__attribute__((export_name("canonical_abi_drop_rb-iseq"))) -void __resource_rb_iseq_dtor(uint32_t val) { - if (rb_abi_guest_rb_iseq_dtor) - rb_abi_guest_rb_iseq_dtor((void*) val); -} - -__attribute__((import_module("canonical_abi"), import_name("resource_drop_rb-abi-value"))) -void __resource_rb_abi_value_drop(uint32_t idx); - -void rb_abi_guest_rb_abi_value_free(rb_abi_guest_rb_abi_value_t *ptr) { - __resource_rb_abi_value_drop(ptr->idx); -} - -__attribute__((import_module("canonical_abi"), import_name("resource_clone_rb-abi-value"))) -uint32_t __resource_rb_abi_value_clone(uint32_t idx); - -rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_clone(rb_abi_guest_rb_abi_value_t *ptr) { - return (rb_abi_guest_rb_abi_value_t){__resource_rb_abi_value_clone(ptr->idx)}; -} - -__attribute__((import_module("canonical_abi"), import_name("resource_new_rb-abi-value"))) -uint32_t __resource_rb_abi_value_new(uint32_t val); - -rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(void *data) { - return (rb_abi_guest_rb_abi_value_t){__resource_rb_abi_value_new((uint32_t) data)}; -} - -__attribute__((import_module("canonical_abi"), import_name("resource_get_rb-abi-value"))) -uint32_t __resource_rb_abi_value_get(uint32_t idx); - -void* rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *ptr) { - return (void*) __resource_rb_abi_value_get(ptr->idx); -} - -__attribute__((export_name("canonical_abi_drop_rb-abi-value"))) -void __resource_rb_abi_value_dtor(uint32_t val) { - if (rb_abi_guest_rb_abi_value_dtor) - rb_abi_guest_rb_abi_value_dtor((void*) val); -} #include void rb_abi_guest_string_set(rb_abi_guest_string_t *ret, const char *s) { @@ -109,13 +41,7 @@ void rb_abi_guest_list_string_free(rb_abi_guest_list_string_t *ptr) { free(ptr->ptr); } } -void rb_abi_guest_tuple2_rb_abi_value_s32_free(rb_abi_guest_tuple2_rb_abi_value_s32_t *ptr) { - rb_abi_guest_rb_abi_value_free(&ptr->f0); -} void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr) { - for (size_t i = 0; i < ptr->len; i++) { - rb_abi_guest_rb_abi_value_free(&ptr->ptr[i]); - } if (ptr->len > 0) { free(ptr->ptr); } @@ -136,11 +62,11 @@ void __wasm_export_rb_abi_guest_ruby_sysinit(int32_t arg, int32_t arg0) { rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) }; rb_abi_guest_ruby_sysinit(&arg1); } -__attribute__((export_name("ruby-options: func(args: list) -> handle"))) +__attribute__((export_name("ruby-options: func(args: list) -> u32"))) int32_t __wasm_export_rb_abi_guest_ruby_options(int32_t arg, int32_t arg0) { rb_abi_guest_list_string_t arg1 = (rb_abi_guest_list_string_t) { (rb_abi_guest_string_t*)(arg), (size_t)(arg0) }; - rb_abi_guest_rb_iseq_t ret = rb_abi_guest_ruby_options(&arg1); - return (ret).idx; + rb_abi_guest_rb_abi_value_t ret = rb_abi_guest_ruby_options(&arg1); + return (int32_t) (ret); } __attribute__((export_name("ruby-script: func(name: string) -> ()"))) void __wasm_export_rb_abi_guest_ruby_script(int32_t arg, int32_t arg0) { @@ -151,23 +77,23 @@ __attribute__((export_name("ruby-init-loadpath: func() -> ()"))) void __wasm_export_rb_abi_guest_ruby_init_loadpath(void) { rb_abi_guest_ruby_init_loadpath(); } -__attribute__((export_name("rb-eval-string-protect: func(str: string) -> tuple, s32>"))) +__attribute__((export_name("rb-eval-string-protect: func(str: string) -> tuple"))) int32_t __wasm_export_rb_abi_guest_rb_eval_string_protect(int32_t arg, int32_t arg0) { rb_abi_guest_string_t arg1 = (rb_abi_guest_string_t) { (char*)(arg), (size_t)(arg0) }; rb_abi_guest_tuple2_rb_abi_value_s32_t ret; rb_abi_guest_rb_eval_string_protect(&arg1, &ret); int32_t ptr = (int32_t) &RET_AREA; - *((int32_t*)(ptr + 0)) = ((ret).f0).idx; + *((int32_t*)(ptr + 0)) = (int32_t) ((ret).f0); *((int32_t*)(ptr + 4)) = (ret).f1; return ptr; } -__attribute__((export_name("rb-funcallv-protect: func(recv: handle, mid: u32, args: list>) -> tuple, s32>"))) +__attribute__((export_name("rb-funcallv-protect: func(recv: u32, mid: u32, args: list) -> tuple"))) int32_t __wasm_export_rb_abi_guest_rb_funcallv_protect(int32_t arg, int32_t arg0, int32_t arg1, int32_t arg2) { rb_abi_guest_list_rb_abi_value_t arg3 = (rb_abi_guest_list_rb_abi_value_t) { (rb_abi_guest_rb_abi_value_t*)(arg1), (size_t)(arg2) }; rb_abi_guest_tuple2_rb_abi_value_s32_t ret; - rb_abi_guest_rb_funcallv_protect((rb_abi_guest_rb_abi_value_t){ arg }, (uint32_t) (arg0), &arg3, &ret); + rb_abi_guest_rb_funcallv_protect((uint32_t) (arg), (uint32_t) (arg0), &arg3, &ret); int32_t ptr = (int32_t) &RET_AREA; - *((int32_t*)(ptr + 0)) = ((ret).f0).idx; + *((int32_t*)(ptr + 0)) = (int32_t) ((ret).f0); *((int32_t*)(ptr + 4)) = (ret).f1; return ptr; } @@ -177,19 +103,19 @@ int32_t __wasm_export_rb_abi_guest_rb_intern(int32_t arg, int32_t arg0) { rb_abi_guest_rb_id_t ret = rb_abi_guest_rb_intern(&arg1); return (int32_t) (ret); } -__attribute__((export_name("rb-errinfo: func() -> handle"))) +__attribute__((export_name("rb-errinfo: func() -> u32"))) int32_t __wasm_export_rb_abi_guest_rb_errinfo(void) { rb_abi_guest_rb_abi_value_t ret = rb_abi_guest_rb_errinfo(); - return (ret).idx; + return (int32_t) (ret); } __attribute__((export_name("rb-clear-errinfo: func() -> ()"))) void __wasm_export_rb_abi_guest_rb_clear_errinfo(void) { rb_abi_guest_rb_clear_errinfo(); } -__attribute__((export_name("rstring-ptr: func(value: handle) -> string"))) +__attribute__((export_name("rstring-ptr: func(value: u32) -> string"))) int32_t __wasm_export_rb_abi_guest_rstring_ptr(int32_t arg) { rb_abi_guest_string_t ret; - rb_abi_guest_rstring_ptr((rb_abi_guest_rb_abi_value_t){ arg }, &ret); + rb_abi_guest_rstring_ptr((uint32_t) (arg), &ret); int32_t ptr = (int32_t) &RET_AREA; *((int32_t*)(ptr + 4)) = (int32_t) (ret).len; *((int32_t*)(ptr + 0)) = (int32_t) (ret).ptr; diff --git a/ext/witapi/bindgen/rb-abi-guest.h b/ext/witapi/bindgen/rb-abi-guest.h index 99b6149f7..551568bb3 100644 --- a/ext/witapi/bindgen/rb-abi-guest.h +++ b/ext/witapi/bindgen/rb-abi-guest.h @@ -8,28 +8,6 @@ extern "C" #include #include - typedef struct { - uint32_t idx; - } rb_abi_guest_rb_iseq_t; - void rb_abi_guest_rb_iseq_free(rb_abi_guest_rb_iseq_t *ptr); - rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_clone(rb_abi_guest_rb_iseq_t *ptr); - rb_abi_guest_rb_iseq_t rb_abi_guest_rb_iseq_new(void *data); - void* rb_abi_guest_rb_iseq_get(rb_abi_guest_rb_iseq_t *ptr); - - __attribute__((weak)) - void rb_abi_guest_rb_iseq_dtor(void *data); - - typedef struct { - uint32_t idx; - } rb_abi_guest_rb_abi_value_t; - void rb_abi_guest_rb_abi_value_free(rb_abi_guest_rb_abi_value_t *ptr); - rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_clone(rb_abi_guest_rb_abi_value_t *ptr); - rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(void *data); - void* rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *ptr); - - __attribute__((weak)) - void rb_abi_guest_rb_abi_value_dtor(void *data); - typedef struct { char *ptr; size_t len; @@ -38,6 +16,9 @@ extern "C" void rb_abi_guest_string_set(rb_abi_guest_string_t *ret, const char *s); void rb_abi_guest_string_dup(rb_abi_guest_string_t *ret, const char *s); void rb_abi_guest_string_free(rb_abi_guest_string_t *ret); + // A Ruby value, which is as known as a VALUE in the Ruby C API. + // This represents a handle owned by the Ruby guest environment. + typedef uint32_t rb_abi_guest_rb_abi_value_t; typedef int32_t rb_abi_guest_rb_errno_t; typedef uint32_t rb_abi_guest_rb_id_t; typedef struct { @@ -49,7 +30,6 @@ extern "C" rb_abi_guest_rb_abi_value_t f0; int32_t f1; } rb_abi_guest_tuple2_rb_abi_value_s32_t; - void rb_abi_guest_tuple2_rb_abi_value_s32_free(rb_abi_guest_tuple2_rb_abi_value_s32_t *ptr); typedef struct { rb_abi_guest_rb_abi_value_t *ptr; size_t len; @@ -58,7 +38,7 @@ extern "C" void rb_abi_guest_ruby_show_version(void); void rb_abi_guest_ruby_init(void); void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args); - rb_abi_guest_rb_iseq_t rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args); + rb_abi_guest_rb_abi_value_t rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args); void rb_abi_guest_ruby_script(rb_abi_guest_string_t *name); void rb_abi_guest_ruby_init_loadpath(void); void rb_abi_guest_rb_eval_string_protect(rb_abi_guest_string_t *str, rb_abi_guest_tuple2_rb_abi_value_s32_t *ret0); diff --git a/ext/witapi/bindgen/rb-abi-guest.wit b/ext/witapi/bindgen/rb-abi-guest.wit index 8b8fa9cf7..bb235bcae 100644 --- a/ext/witapi/bindgen/rb-abi-guest.wit +++ b/ext/witapi/bindgen/rb-abi-guest.wit @@ -1,12 +1,14 @@ -resource rb-iseq -resource rb-abi-value +/// A Ruby value, which is as known as a VALUE in the Ruby C API. +/// This represents a handle owned by the Ruby guest environment. +type rb-abi-value = u32 + type rb-errno = s32 type rb-id = u32 ruby-show-version: func() ruby-init: func() ruby-sysinit: func(args: list) -ruby-options: func(args: list) -> rb-iseq +ruby-options: func(args: list) -> rb-abi-value ruby-script: func(name: string) ruby-init-loadpath: func() rb-eval-string-protect: func(str: string) -> tuple diff --git a/ext/witapi/witapi-core.c b/ext/witapi/witapi-core.c index 85b2361dd..26086d1de 100644 --- a/ext/witapi/witapi-core.c +++ b/ext/witapi/witapi-core.c @@ -172,6 +172,13 @@ void rb_abi_lend_object(VALUE obj) { assert(state == TAG_NONE && "rb_abi_lend_object_internal failed"); } +static inline rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(VALUE obj) { + return (rb_abi_guest_rb_abi_value_t)(obj); +} +static inline VALUE rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *self) { + return (VALUE)(*self); +} + static VALUE rb_abi_guest_rb_abi_value_dtor_internal(VALUE obj) { VALUE object_id = rb_obj_id(obj); VALUE ref_count = rb_hash_lookup(rb_abi_guest_refcount_hash, object_id); @@ -223,20 +230,20 @@ void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args) { RB_WASM_LIB_RT(ruby_sysinit(&argc, &c_args)) } -rb_abi_guest_rb_iseq_t +rb_abi_guest_rb_abi_value_t rb_abi_guest_ruby_options(rb_abi_guest_list_string_t *args) { - void *result; + VALUE result; char **c_args; c_strings_from_abi(args, c_args); - RB_WASM_LIB_RT(result = ruby_options(args->len, c_args)) - return rb_abi_guest_rb_iseq_new(result); + RB_WASM_LIB_RT(result = (VALUE)ruby_options(args->len, c_args)) + return rb_abi_guest_rb_abi_value_new(result); } rb_abi_guest_rb_errno_t -rb_abi_guest_ruby_run_node(rb_abi_guest_rb_iseq_t node) { +rb_abi_guest_ruby_run_node(rb_abi_guest_rb_abi_value_t node) { int result; - void *iseq = rb_abi_guest_rb_iseq_get(&node); - RB_WASM_LIB_RT(ruby_run_node(iseq)) + VALUE iseq = rb_abi_guest_rb_abi_value_get(&node); + RB_WASM_LIB_RT(ruby_run_node((void *)iseq)) return result; } @@ -260,7 +267,7 @@ void rb_abi_guest_rb_eval_string_protect( if (ret0->f1 == TAG_NONE) { rb_abi_lend_object(retval); } - ret0->f0 = rb_abi_guest_rb_abi_value_new((void *)retval); + ret0->f0 = rb_abi_guest_rb_abi_value_new(retval); } struct rb_funcallv_thunk_ctx { @@ -294,7 +301,7 @@ void rb_abi_guest_rb_funcallv_protect( if (ret0->f1 == TAG_NONE) { rb_abi_lend_object(retval); } - ret0->f0 = rb_abi_guest_rb_abi_value_new((void *)retval); + ret0->f0 = rb_abi_guest_rb_abi_value_new(retval); } rb_abi_guest_rb_id_t rb_abi_guest_rb_intern(rb_abi_guest_string_t *name) { @@ -305,7 +312,7 @@ rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_errinfo(void) { VALUE retval; RB_WASM_LIB_RT(retval = rb_errinfo()); rb_abi_lend_object(retval); - return rb_abi_guest_rb_abi_value_new((void *)retval); + return rb_abi_guest_rb_abi_value_new(retval); } void rb_abi_guest_rb_clear_errinfo(void) { rb_set_errinfo(Qnil); } diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/intrinsics.js b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/intrinsics.js index 0e181b883..e342e6ebf 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/intrinsics.js +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/intrinsics.js @@ -41,46 +41,6 @@ export function utf8_encode(s, realloc, memory) { } export let UTF8_ENCODED_LEN = 0; -export class Slab { - constructor() { - this.list = []; - this.head = 0; - } - - insert(val) { - if (this.head >= this.list.length) { - this.list.push({ - next: this.list.length + 1, - val: undefined, - }); - } - const ret = this.head; - const slot = this.list[ret]; - this.head = slot.next; - slot.next = -1; - slot.val = val; - return ret; - } - - get(idx) { - if (idx >= this.list.length) - throw new RangeError('handle index not valid'); - const slot = this.list[idx]; - if (slot.next === -1) - return slot.val; - throw new RangeError('handle index not valid'); - } - - remove(idx) { - const ret = this.get(idx); // validate the slot - const slot = this.list[idx]; - slot.val = undefined; - slot.next = this.head; - this.head = idx; - return ret; - } -} - export function throw_invalid_bool() { throw new RangeError("invalid variant discriminant for bool"); } diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts index 926831271..dd6bc2c53 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts @@ -1,3 +1,8 @@ +/** +* A Ruby value, which is as known as a VALUE in the Ruby C API. +* This represents a handle owned by the Ruby guest environment. +*/ +export type RbAbiValue = number; export type RbErrno = number; export type RbId = number; export class RbAbiGuest { @@ -70,11 +75,11 @@ export class RbAbiGuest { rubyShowVersion(): void; rubyInit(): void; rubySysinit(args: string[]): void; - rubyOptions(args: string[]): RbIseq; + rubyOptions(args: string[]): RbAbiValue; rubyScript(name: string): void; rubyInitLoadpath(): void; rbEvalStringProtect(str: string): [RbAbiValue, number]; - rbFuncallvProtect(recv: RbAbiValue, mid: RbId, args: RbAbiValue[]): [RbAbiValue, number]; + rbFuncallvProtect(recv: RbAbiValue, mid: RbId, args: Uint32Array): [RbAbiValue, number]; rbIntern(name: string): RbId; rbErrinfo(): RbAbiValue; rbClearErrinfo(): void; @@ -84,57 +89,3 @@ export class RbAbiGuest { rbGcDisable(): boolean; rbSetShouldProhibitRewind(newValue: boolean): boolean; } - -export class RbIseq { - // Creates a new strong reference count as a new - // object. This is only required if you're also - // calling `drop` below and want to manually manage - // the reference count from JS. - // - // If you don't call `drop`, you don't need to call - // this and can simply use the object from JS. - clone(): RbIseq; - - // Explicitly indicate that this JS object will no - // longer be used. If the internal reference count - // reaches zero then this will deterministically - // destroy the underlying wasm object. - // - // This is not required to be called from JS. Wasm - // destructors will be automatically called for you - // if this is not called using the JS - // `FinalizationRegistry`. - // - // Calling this method does not guarantee that the - // underlying wasm object is deallocated. Something - // else (including wasm) may be holding onto a - // strong reference count. - drop(): void; -} - -export class RbAbiValue { - // Creates a new strong reference count as a new - // object. This is only required if you're also - // calling `drop` below and want to manually manage - // the reference count from JS. - // - // If you don't call `drop`, you don't need to call - // this and can simply use the object from JS. - clone(): RbAbiValue; - - // Explicitly indicate that this JS object will no - // longer be used. If the internal reference count - // reaches zero then this will deterministically - // destroy the underlying wasm object. - // - // This is not required to be called from JS. Wasm - // destructors will be automatically called for you - // if this is not called using the JS - // `FinalizationRegistry`. - // - // Calling this method does not guarantee that the - // underlying wasm object is deallocated. Something - // else (including wasm) may be holding onto a - // strong reference count. - drop(): void; -} diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js index 5919b716c..e14f9af50 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js @@ -1,41 +1,6 @@ -import { data_view, to_uint32, UTF8_DECODER, utf8_encode, UTF8_ENCODED_LEN, Slab, throw_invalid_bool } from './intrinsics.js'; +import { data_view, to_uint32, UTF8_DECODER, utf8_encode, UTF8_ENCODED_LEN, throw_invalid_bool } from './intrinsics.js'; export class RbAbiGuest { - constructor() { - this._resource0_slab = new Slab(); - this._resource1_slab = new Slab(); - } addToImports(imports) { - if (!("canonical_abi" in imports)) imports["canonical_abi"] = {}; - - imports.canonical_abi['resource_drop_rb-iseq'] = i => { - this._resource0_slab.remove(i).drop(); - }; - imports.canonical_abi['resource_clone_rb-iseq'] = i => { - const obj = this._resource0_slab.get(i); - return this._resource0_slab.insert(obj.clone()) - }; - imports.canonical_abi['resource_get_rb-iseq'] = i => { - return this._resource0_slab.get(i)._wasm_val; - }; - imports.canonical_abi['resource_new_rb-iseq'] = i => { - const registry = this._registry0; - return this._resource0_slab.insert(new RbIseq(i, this)); - }; - - imports.canonical_abi['resource_drop_rb-abi-value'] = i => { - this._resource1_slab.remove(i).drop(); - }; - imports.canonical_abi['resource_clone_rb-abi-value'] = i => { - const obj = this._resource1_slab.get(i); - return this._resource1_slab.insert(obj.clone()) - }; - imports.canonical_abi['resource_get_rb-abi-value'] = i => { - return this._resource1_slab.get(i)._wasm_val; - }; - imports.canonical_abi['resource_new_rb-abi-value'] = i => { - const registry = this._registry1; - return this._resource1_slab.insert(new RbAbiValue(i, this)); - }; } async instantiate(module, imports) { @@ -54,8 +19,6 @@ export class RbAbiGuest { this.instance = instance; } this._exports = this.instance.exports; - this._registry0 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-iseq']); - this._registry1 = new FinalizationRegistry(this._exports['canonical_abi_drop_rb-abi-value']); } rubyShowVersion() { this._exports['ruby-show-version: func() -> ()'](); @@ -93,8 +56,8 @@ export class RbAbiGuest { data_view(memory).setInt32(base + 4, len0, true); data_view(memory).setInt32(base + 0, ptr0, true); } - const ret = this._exports['ruby-options: func(args: list) -> handle'](result1, len1); - return this._resource0_slab.remove(ret); + const ret = this._exports['ruby-options: func(args: list) -> u32'](result1, len1); + return ret >>> 0; } rubyScript(arg0) { const memory = this._exports.memory; @@ -111,26 +74,18 @@ export class RbAbiGuest { const realloc = this._exports["cabi_realloc"]; const ptr0 = utf8_encode(arg0, realloc, memory); const len0 = UTF8_ENCODED_LEN; - const ret = this._exports['rb-eval-string-protect: func(str: string) -> tuple, s32>'](ptr0, len0); - return [this._resource1_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)]; + const ret = this._exports['rb-eval-string-protect: func(str: string) -> tuple'](ptr0, len0); + return [data_view(memory).getInt32(ret + 0, true) >>> 0, data_view(memory).getInt32(ret + 4, true)]; } rbFuncallvProtect(arg0, arg1, arg2) { const memory = this._exports.memory; const realloc = this._exports["cabi_realloc"]; - const obj0 = arg0; - if (!(obj0 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue'); - const vec2 = arg2; - const len2 = vec2.length; - const result2 = realloc(0, 0, 4, len2 * 4); - for (let i = 0; i < vec2.length; i++) { - const e = vec2[i]; - const base = result2 + i * 4; - const obj1 = e; - if (!(obj1 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue'); - data_view(memory).setInt32(base + 0, this._resource1_slab.insert(obj1.clone()), true); - } - const ret = this._exports['rb-funcallv-protect: func(recv: handle, mid: u32, args: list>) -> tuple, s32>'](this._resource1_slab.insert(obj0.clone()), to_uint32(arg1), result2, len2); - return [this._resource1_slab.remove(data_view(memory).getInt32(ret + 0, true)), data_view(memory).getInt32(ret + 4, true)]; + const val0 = arg2; + const len0 = val0.length; + const ptr0 = realloc(0, 0, 4, len0 * 4); + (new Uint8Array(memory.buffer, ptr0, len0 * 4)).set(new Uint8Array(val0.buffer, val0.byteOffset, len0 * 4)); + const ret = this._exports['rb-funcallv-protect: func(recv: u32, mid: u32, args: list) -> tuple'](to_uint32(arg0), to_uint32(arg1), ptr0, len0); + return [data_view(memory).getInt32(ret + 0, true) >>> 0, data_view(memory).getInt32(ret + 4, true)]; } rbIntern(arg0) { const memory = this._exports.memory; @@ -141,22 +96,20 @@ export class RbAbiGuest { return ret >>> 0; } rbErrinfo() { - const ret = this._exports['rb-errinfo: func() -> handle'](); - return this._resource1_slab.remove(ret); + const ret = this._exports['rb-errinfo: func() -> u32'](); + return ret >>> 0; } rbClearErrinfo() { this._exports['rb-clear-errinfo: func() -> ()'](); } rstringPtr(arg0) { const memory = this._exports.memory; - const obj0 = arg0; - if (!(obj0 instanceof RbAbiValue)) throw new TypeError('expected instance of RbAbiValue'); - const ret = this._exports['rstring-ptr: func(value: handle) -> string'](this._resource1_slab.insert(obj0.clone())); - const ptr1 = data_view(memory).getInt32(ret + 0, true); - const len1 = data_view(memory).getInt32(ret + 4, true); - const result1 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr1, len1)); + const ret = this._exports['rstring-ptr: func(value: u32) -> string'](to_uint32(arg0)); + const ptr0 = data_view(memory).getInt32(ret + 0, true); + const len0 = data_view(memory).getInt32(ret + 4, true); + const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); this._exports["cabi_post_rstring-ptr"](ret); - return result1; + return result0; } rbVmBugreport() { this._exports['rb-vm-bugreport: func() -> ()'](); @@ -177,57 +130,3 @@ export class RbAbiGuest { return bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool()); } } - -export class RbIseq { - constructor(wasm_val, obj) { - this._wasm_val = wasm_val; - this._obj = obj; - this._refcnt = 1; - obj._registry0.register(this, wasm_val, this); - } - - clone() { - this._refcnt += 1; - return this; - } - - drop() { - this._refcnt -= 1; - if (this._refcnt !== 0) - return; - this._obj._registry0.unregister(this); - const dtor = this._obj._exports['canonical_abi_drop_rb-iseq']; - const wasm_val = this._wasm_val; - delete this._obj; - delete this._refcnt; - delete this._wasm_val; - dtor(wasm_val); - } -} - -export class RbAbiValue { - constructor(wasm_val, obj) { - this._wasm_val = wasm_val; - this._obj = obj; - this._refcnt = 1; - obj._registry1.register(this, wasm_val, this); - } - - clone() { - this._refcnt += 1; - return this; - } - - drop() { - this._refcnt -= 1; - if (this._refcnt !== 0) - return; - this._obj._registry1.unregister(this); - const dtor = this._obj._exports['canonical_abi_drop_rb-abi-value']; - const wasm_val = this._wasm_val; - delete this._obj; - delete this._refcnt; - delete this._wasm_val; - dtor(wasm_val); - } -} diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts index f914c0e9e..826318829 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts @@ -1,3 +1,9 @@ +/** +* A JavaScript value. In the future, this will be replaced by handle types. +* The underlying value should be owned by the JavaScript host environment +* and should live at least until all handles to it are dropped. +*/ +export type JsAbiValue = number; export type JsAbiResult = JsAbiResultSuccess | JsAbiResultFailure; export interface JsAbiResultSuccess { tag: "success", @@ -35,19 +41,16 @@ export interface RbJsAbiHost { jsValueTypeof(value: JsAbiValue): string; jsValueEqual(lhs: JsAbiValue, rhs: JsAbiValue): boolean; jsValueStrictlyEqual(lhs: JsAbiValue, rhs: JsAbiValue): boolean; - reflectApply(target: JsAbiValue, thisArgument: JsAbiValue, arguments: JsAbiValue[]): JsAbiResult; - reflectConstruct(target: JsAbiValue, arguments: JsAbiValue[]): JsAbiValue; + reflectApply(target: JsAbiValue, thisArgument: JsAbiValue, arguments: Uint32Array): JsAbiResult; + reflectConstruct(target: JsAbiValue, arguments: Uint32Array): JsAbiValue; reflectDeleteProperty(target: JsAbiValue, propertyKey: string): boolean; reflectGet(target: JsAbiValue, propertyKey: string): JsAbiResult; reflectGetOwnPropertyDescriptor(target: JsAbiValue, propertyKey: string): JsAbiValue; reflectGetPrototypeOf(target: JsAbiValue): JsAbiValue; reflectHas(target: JsAbiValue, propertyKey: string): boolean; reflectIsExtensible(target: JsAbiValue): boolean; - reflectOwnKeys(target: JsAbiValue): JsAbiValue[]; + reflectOwnKeys(target: JsAbiValue): Uint32Array; reflectPreventExtensions(target: JsAbiValue): boolean; reflectSet(target: JsAbiValue, propertyKey: string, value: JsAbiValue): JsAbiResult; reflectSetPrototypeOf(target: JsAbiValue, prototype: JsAbiValue): boolean; - dropJsAbiValue?: (val: JsAbiValue) => void; -} -export interface JsAbiValue { } diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js index 02aa2fb46..ece59bb54 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js @@ -1,7 +1,7 @@ -import { data_view, UTF8_DECODER, utf8_encode, UTF8_ENCODED_LEN, Slab, throw_invalid_bool } from './intrinsics.js'; +import { data_view, to_uint32, UTF8_DECODER, utf8_encode, UTF8_ENCODED_LEN, throw_invalid_bool } from './intrinsics.js'; export function addRbJsAbiHostToImports(imports, obj, get_export) { if (!("rb-js-abi-host" in imports)) imports["rb-js-abi-host"] = {}; - imports["rb-js-abi-host"]["eval-js: func(code: string) -> variant { success(handle), failure(handle) }"] = function(arg0, arg1, arg2) { + imports["rb-js-abi-host"]["eval-js: func(code: string) -> variant { success(u32), failure(u32) }"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); const ptr0 = arg0; const len0 = arg1; @@ -12,73 +12,73 @@ export function addRbJsAbiHostToImports(imports, obj, get_export) { case "success": { const e = variant1.val; data_view(memory).setInt8(arg2 + 0, 0, true); - data_view(memory).setInt32(arg2 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg2 + 4, to_uint32(e), true); break; } case "failure": { const e = variant1.val; data_view(memory).setInt8(arg2 + 0, 1, true); - data_view(memory).setInt32(arg2 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg2 + 4, to_uint32(e), true); break; } default: throw new RangeError("invalid variant specified for JsAbiResult"); } }; - imports["rb-js-abi-host"]["is-js: func(value: handle) -> bool"] = function(arg0) { - const ret0 = obj.isJs(resources0.get(arg0)); + imports["rb-js-abi-host"]["is-js: func(value: u32) -> bool"] = function(arg0) { + const ret0 = obj.isJs(arg0 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["instance-of: func(value: handle, klass: handle) -> bool"] = function(arg0, arg1) { - const ret0 = obj.instanceOf(resources0.get(arg0), resources0.get(arg1)); + imports["rb-js-abi-host"]["instance-of: func(value: u32, klass: u32) -> bool"] = function(arg0, arg1) { + const ret0 = obj.instanceOf(arg0 >>> 0, arg1 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["global-this: func() -> handle"] = function() { + imports["rb-js-abi-host"]["global-this: func() -> u32"] = function() { const ret0 = obj.globalThis(); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["int-to-js-number: func(value: s32) -> handle"] = function(arg0) { + imports["rb-js-abi-host"]["int-to-js-number: func(value: s32) -> u32"] = function(arg0) { const ret0 = obj.intToJsNumber(arg0); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["float-to-js-number: func(value: float64) -> handle"] = function(arg0) { + imports["rb-js-abi-host"]["float-to-js-number: func(value: float64) -> u32"] = function(arg0) { const ret0 = obj.floatToJsNumber(arg0); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["string-to-js-string: func(value: string) -> handle"] = function(arg0, arg1) { + imports["rb-js-abi-host"]["string-to-js-string: func(value: string) -> u32"] = function(arg0, arg1) { const memory = get_export("memory"); const ptr0 = arg0; const len0 = arg1; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); const ret0 = obj.stringToJsString(result0); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["bool-to-js-bool: func(value: bool) -> handle"] = function(arg0) { + imports["rb-js-abi-host"]["bool-to-js-bool: func(value: bool) -> u32"] = function(arg0) { const bool0 = arg0; const ret0 = obj.boolToJsBool(bool0 == 0 ? false : (bool0 == 1 ? true : throw_invalid_bool())); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["proc-to-js-function: func(value: u32) -> handle"] = function(arg0) { + imports["rb-js-abi-host"]["proc-to-js-function: func(value: u32) -> u32"] = function(arg0) { const ret0 = obj.procToJsFunction(arg0 >>> 0); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> handle"] = function(arg0) { + imports["rb-js-abi-host"]["rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> u32"] = function(arg0) { const ret0 = obj.rbObjectToJsRbValue(arg0 >>> 0); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["js-value-to-string: func(value: handle) -> string"] = function(arg0, arg1) { + imports["rb-js-abi-host"]["js-value-to-string: func(value: u32) -> string"] = function(arg0, arg1) { const memory = get_export("memory"); const realloc = get_export("cabi_realloc"); - const ret0 = obj.jsValueToString(resources0.get(arg0)); + const ret0 = obj.jsValueToString(arg0 >>> 0); const ptr0 = utf8_encode(ret0, realloc, memory); const len0 = UTF8_ENCODED_LEN; data_view(memory).setInt32(arg1 + 4, len0, true); data_view(memory).setInt32(arg1 + 0, ptr0, true); }; - imports["rb-js-abi-host"]["js-value-to-integer: func(value: handle) -> variant { f64(float64), bignum(string) }"] = function(arg0, arg1) { + imports["rb-js-abi-host"]["js-value-to-integer: func(value: u32) -> variant { f64(float64), bignum(string) }"] = function(arg0, arg1) { const memory = get_export("memory"); const realloc = get_export("cabi_realloc"); - const ret0 = obj.jsValueToInteger(resources0.get(arg0)); + const ret0 = obj.jsValueToInteger(arg0 >>> 0); const variant1 = ret0; switch (variant1.tag) { case "f64": { @@ -100,179 +100,159 @@ export function addRbJsAbiHostToImports(imports, obj, get_export) { throw new RangeError("invalid variant specified for RawInteger"); } }; - imports["rb-js-abi-host"]["export-js-value-to-host: func(value: handle) -> ()"] = function(arg0) { - obj.exportJsValueToHost(resources0.get(arg0)); + imports["rb-js-abi-host"]["export-js-value-to-host: func(value: u32) -> ()"] = function(arg0) { + obj.exportJsValueToHost(arg0 >>> 0); }; - imports["rb-js-abi-host"]["import-js-value-from-host: func() -> handle"] = function() { + imports["rb-js-abi-host"]["import-js-value-from-host: func() -> u32"] = function() { const ret0 = obj.importJsValueFromHost(); - return resources0.insert(ret0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["js-value-typeof: func(value: handle) -> string"] = function(arg0, arg1) { + imports["rb-js-abi-host"]["js-value-typeof: func(value: u32) -> string"] = function(arg0, arg1) { const memory = get_export("memory"); const realloc = get_export("cabi_realloc"); - const ret0 = obj.jsValueTypeof(resources0.get(arg0)); + const ret0 = obj.jsValueTypeof(arg0 >>> 0); const ptr0 = utf8_encode(ret0, realloc, memory); const len0 = UTF8_ENCODED_LEN; data_view(memory).setInt32(arg1 + 4, len0, true); data_view(memory).setInt32(arg1 + 0, ptr0, true); }; - imports["rb-js-abi-host"]["js-value-equal: func(lhs: handle, rhs: handle) -> bool"] = function(arg0, arg1) { - const ret0 = obj.jsValueEqual(resources0.get(arg0), resources0.get(arg1)); + imports["rb-js-abi-host"]["js-value-equal: func(lhs: u32, rhs: u32) -> bool"] = function(arg0, arg1) { + const ret0 = obj.jsValueEqual(arg0 >>> 0, arg1 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["js-value-strictly-equal: func(lhs: handle, rhs: handle) -> bool"] = function(arg0, arg1) { - const ret0 = obj.jsValueStrictlyEqual(resources0.get(arg0), resources0.get(arg1)); + imports["rb-js-abi-host"]["js-value-strictly-equal: func(lhs: u32, rhs: u32) -> bool"] = function(arg0, arg1) { + const ret0 = obj.jsValueStrictlyEqual(arg0 >>> 0, arg1 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["reflect-apply: func(target: handle, this-argument: handle, arguments: list>) -> variant { success(handle), failure(handle) }"] = function(arg0, arg1, arg2, arg3, arg4) { + imports["rb-js-abi-host"]["reflect-apply: func(target: u32, this-argument: u32, arguments: list) -> variant { success(u32), failure(u32) }"] = function(arg0, arg1, arg2, arg3, arg4) { const memory = get_export("memory"); + const ptr0 = arg2; const len0 = arg3; - const base0 = arg2; - const result0 = []; - for (let i = 0; i < len0; i++) { - const base = base0 + i * 4; - result0.push(resources0.get(data_view(memory).getInt32(base + 0, true))); - } - const ret0 = obj.reflectApply(resources0.get(arg0), resources0.get(arg1), result0); + const result0 = new Uint32Array(memory.buffer.slice(ptr0, ptr0 + len0 * 4)); + const ret0 = obj.reflectApply(arg0 >>> 0, arg1 >>> 0, result0); const variant1 = ret0; switch (variant1.tag) { case "success": { const e = variant1.val; data_view(memory).setInt8(arg4 + 0, 0, true); - data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg4 + 4, to_uint32(e), true); break; } case "failure": { const e = variant1.val; data_view(memory).setInt8(arg4 + 0, 1, true); - data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg4 + 4, to_uint32(e), true); break; } default: throw new RangeError("invalid variant specified for JsAbiResult"); } }; - imports["rb-js-abi-host"]["reflect-construct: func(target: handle, arguments: list>) -> handle"] = function(arg0, arg1, arg2) { + imports["rb-js-abi-host"]["reflect-construct: func(target: u32, arguments: list) -> u32"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); + const ptr0 = arg1; const len0 = arg2; - const base0 = arg1; - const result0 = []; - for (let i = 0; i < len0; i++) { - const base = base0 + i * 4; - result0.push(resources0.get(data_view(memory).getInt32(base + 0, true))); - } - const ret0 = obj.reflectConstruct(resources0.get(arg0), result0); - return resources0.insert(ret0); + const result0 = new Uint32Array(memory.buffer.slice(ptr0, ptr0 + len0 * 4)); + const ret0 = obj.reflectConstruct(arg0 >>> 0, result0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["reflect-delete-property: func(target: handle, property-key: string) -> bool"] = function(arg0, arg1, arg2) { + imports["rb-js-abi-host"]["reflect-delete-property: func(target: u32, property-key: string) -> bool"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); const ptr0 = arg1; const len0 = arg2; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); - const ret0 = obj.reflectDeleteProperty(resources0.get(arg0), result0); + const ret0 = obj.reflectDeleteProperty(arg0 >>> 0, result0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["reflect-get: func(target: handle, property-key: string) -> variant { success(handle), failure(handle) }"] = function(arg0, arg1, arg2, arg3) { + imports["rb-js-abi-host"]["reflect-get: func(target: u32, property-key: string) -> variant { success(u32), failure(u32) }"] = function(arg0, arg1, arg2, arg3) { const memory = get_export("memory"); const ptr0 = arg1; const len0 = arg2; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); - const ret0 = obj.reflectGet(resources0.get(arg0), result0); + const ret0 = obj.reflectGet(arg0 >>> 0, result0); const variant1 = ret0; switch (variant1.tag) { case "success": { const e = variant1.val; data_view(memory).setInt8(arg3 + 0, 0, true); - data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg3 + 4, to_uint32(e), true); break; } case "failure": { const e = variant1.val; data_view(memory).setInt8(arg3 + 0, 1, true); - data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg3 + 4, to_uint32(e), true); break; } default: throw new RangeError("invalid variant specified for JsAbiResult"); } }; - imports["rb-js-abi-host"]["reflect-get-own-property-descriptor: func(target: handle, property-key: string) -> handle"] = function(arg0, arg1, arg2) { + imports["rb-js-abi-host"]["reflect-get-own-property-descriptor: func(target: u32, property-key: string) -> u32"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); const ptr0 = arg1; const len0 = arg2; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); - const ret0 = obj.reflectGetOwnPropertyDescriptor(resources0.get(arg0), result0); - return resources0.insert(ret0); + const ret0 = obj.reflectGetOwnPropertyDescriptor(arg0 >>> 0, result0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["reflect-get-prototype-of: func(target: handle) -> handle"] = function(arg0) { - const ret0 = obj.reflectGetPrototypeOf(resources0.get(arg0)); - return resources0.insert(ret0); + imports["rb-js-abi-host"]["reflect-get-prototype-of: func(target: u32) -> u32"] = function(arg0) { + const ret0 = obj.reflectGetPrototypeOf(arg0 >>> 0); + return to_uint32(ret0); }; - imports["rb-js-abi-host"]["reflect-has: func(target: handle, property-key: string) -> bool"] = function(arg0, arg1, arg2) { + imports["rb-js-abi-host"]["reflect-has: func(target: u32, property-key: string) -> bool"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); const ptr0 = arg1; const len0 = arg2; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); - const ret0 = obj.reflectHas(resources0.get(arg0), result0); + const ret0 = obj.reflectHas(arg0 >>> 0, result0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["reflect-is-extensible: func(target: handle) -> bool"] = function(arg0) { - const ret0 = obj.reflectIsExtensible(resources0.get(arg0)); + imports["rb-js-abi-host"]["reflect-is-extensible: func(target: u32) -> bool"] = function(arg0) { + const ret0 = obj.reflectIsExtensible(arg0 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["reflect-own-keys: func(target: handle) -> list>"] = function(arg0, arg1) { + imports["rb-js-abi-host"]["reflect-own-keys: func(target: u32) -> list"] = function(arg0, arg1) { const memory = get_export("memory"); const realloc = get_export("cabi_realloc"); - const ret0 = obj.reflectOwnKeys(resources0.get(arg0)); - const vec0 = ret0; - const len0 = vec0.length; - const result0 = realloc(0, 0, 4, len0 * 4); - for (let i = 0; i < vec0.length; i++) { - const e = vec0[i]; - const base = result0 + i * 4; - data_view(memory).setInt32(base + 0, resources0.insert(e), true); - } + const ret0 = obj.reflectOwnKeys(arg0 >>> 0); + const val0 = ret0; + const len0 = val0.length; + const ptr0 = realloc(0, 0, 4, len0 * 4); + (new Uint8Array(memory.buffer, ptr0, len0 * 4)).set(new Uint8Array(val0.buffer, val0.byteOffset, len0 * 4)); data_view(memory).setInt32(arg1 + 4, len0, true); - data_view(memory).setInt32(arg1 + 0, result0, true); + data_view(memory).setInt32(arg1 + 0, ptr0, true); }; - imports["rb-js-abi-host"]["reflect-prevent-extensions: func(target: handle) -> bool"] = function(arg0) { - const ret0 = obj.reflectPreventExtensions(resources0.get(arg0)); + imports["rb-js-abi-host"]["reflect-prevent-extensions: func(target: u32) -> bool"] = function(arg0) { + const ret0 = obj.reflectPreventExtensions(arg0 >>> 0); return ret0 ? 1 : 0; }; - imports["rb-js-abi-host"]["reflect-set: func(target: handle, property-key: string, value: handle) -> variant { success(handle), failure(handle) }"] = function(arg0, arg1, arg2, arg3, arg4) { + imports["rb-js-abi-host"]["reflect-set: func(target: u32, property-key: string, value: u32) -> variant { success(u32), failure(u32) }"] = function(arg0, arg1, arg2, arg3, arg4) { const memory = get_export("memory"); const ptr0 = arg1; const len0 = arg2; const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0)); - const ret0 = obj.reflectSet(resources0.get(arg0), result0, resources0.get(arg3)); + const ret0 = obj.reflectSet(arg0 >>> 0, result0, arg3 >>> 0); const variant1 = ret0; switch (variant1.tag) { case "success": { const e = variant1.val; data_view(memory).setInt8(arg4 + 0, 0, true); - data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg4 + 4, to_uint32(e), true); break; } case "failure": { const e = variant1.val; data_view(memory).setInt8(arg4 + 0, 1, true); - data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true); + data_view(memory).setInt32(arg4 + 4, to_uint32(e), true); break; } default: throw new RangeError("invalid variant specified for JsAbiResult"); } }; - imports["rb-js-abi-host"]["reflect-set-prototype-of: func(target: handle, prototype: handle) -> bool"] = function(arg0, arg1) { - const ret0 = obj.reflectSetPrototypeOf(resources0.get(arg0), resources0.get(arg1)); + imports["rb-js-abi-host"]["reflect-set-prototype-of: func(target: u32, prototype: u32) -> bool"] = function(arg0, arg1) { + const ret0 = obj.reflectSetPrototypeOf(arg0 >>> 0, arg1 >>> 0); return ret0 ? 1 : 0; }; - if (!("canonical_abi" in imports)) imports["canonical_abi"] = {}; - - const resources0 = new Slab(); - imports.canonical_abi["resource_drop_js-abi-value"] = (i) => { - const val = resources0.remove(i); - if (obj.dropJsAbiValue) - obj.dropJsAbiValue(val); - }; } \ No newline at end of file From a0a903102b83086ddb11829668becc840fe29495 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 16:13:15 +0000 Subject: [PATCH 02/10] Fix missing assignment for the result of ruby_run_node --- ext/witapi/witapi-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/witapi/witapi-core.c b/ext/witapi/witapi-core.c index 26086d1de..67aa872eb 100644 --- a/ext/witapi/witapi-core.c +++ b/ext/witapi/witapi-core.c @@ -243,7 +243,7 @@ rb_abi_guest_rb_errno_t rb_abi_guest_ruby_run_node(rb_abi_guest_rb_abi_value_t node) { int result; VALUE iseq = rb_abi_guest_rb_abi_value_get(&node); - RB_WASM_LIB_RT(ruby_run_node((void *)iseq)) + RB_WASM_LIB_RT(result = ruby_run_node((void *)iseq)) return result; } From 6c40e650668b34c99d90e1395ba604afe3a4d6a2 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 16:27:47 +0000 Subject: [PATCH 03/10] Use manually defined lifetime management function --- ext/js/bindgen/rb-js-abi-host.c | 5 +++++ ext/js/bindgen/rb-js-abi-host.h | 1 + ext/js/bindgen/rb-js-abi-host.wit | 4 ++++ ext/js/js-core.c | 4 ++-- .../ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts | 5 +++++ .../ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js | 3 +++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ext/js/bindgen/rb-js-abi-host.c b/ext/js/bindgen/rb-js-abi-host.c index 1379e7fbd..d1a9529d2 100644 --- a/ext/js/bindgen/rb-js-abi-host.c +++ b/ext/js/bindgen/rb-js-abi-host.c @@ -46,6 +46,11 @@ void rb_js_abi_host_list_js_abi_value_free(rb_js_abi_host_list_js_abi_value_t *p free(ptr->ptr); } } +__attribute__((import_module("rb-js-abi-host"), import_name("drop-js-value: func(value: u32) -> ()"))) +void __wasm_import_rb_js_abi_host_drop_js_value(int32_t); +void rb_js_abi_host_drop_js_value(rb_js_abi_host_js_abi_value_t value) { + __wasm_import_rb_js_abi_host_drop_js_value((int32_t) (value)); +} __attribute__((import_module("rb-js-abi-host"), import_name("eval-js: func(code: string) -> variant { success(u32), failure(u32) }"))) void __wasm_import_rb_js_abi_host_eval_js(int32_t, int32_t, int32_t); void rb_js_abi_host_eval_js(rb_js_abi_host_string_t *code, rb_js_abi_host_js_abi_result_t *ret0) { diff --git a/ext/js/bindgen/rb-js-abi-host.h b/ext/js/bindgen/rb-js-abi-host.h index 1b58fddf1..098461d39 100644 --- a/ext/js/bindgen/rb-js-abi-host.h +++ b/ext/js/bindgen/rb-js-abi-host.h @@ -44,6 +44,7 @@ extern "C" size_t len; } rb_js_abi_host_list_js_abi_value_t; void rb_js_abi_host_list_js_abi_value_free(rb_js_abi_host_list_js_abi_value_t *ptr); + void rb_js_abi_host_drop_js_value(rb_js_abi_host_js_abi_value_t value); void rb_js_abi_host_eval_js(rb_js_abi_host_string_t *code, rb_js_abi_host_js_abi_result_t *ret0); bool rb_js_abi_host_is_js(rb_js_abi_host_js_abi_value_t value); bool rb_js_abi_host_instance_of(rb_js_abi_host_js_abi_value_t value, rb_js_abi_host_js_abi_value_t klass); diff --git a/ext/js/bindgen/rb-js-abi-host.wit b/ext/js/bindgen/rb-js-abi-host.wit index 70ae06c24..87d7f3832 100644 --- a/ext/js/bindgen/rb-js-abi-host.wit +++ b/ext/js/bindgen/rb-js-abi-host.wit @@ -3,6 +3,10 @@ /// and should live at least until all handles to it are dropped. type js-abi-value = u32 +/// Dispose of a JavaScript value. This should be called when a handle to a +/// JavaScript value is no longer needed by the Ruby program. +drop-js-value: func(value: js-abi-value) + variant js-abi-result { success(js-abi-value), failure(js-abi-value), diff --git a/ext/js/js-core.c b/ext/js/js-core.c index fa1e0308c..623e6e37c 100644 --- a/ext/js/js-core.c +++ b/ext/js/js-core.c @@ -35,7 +35,7 @@ static void jsvalue_mark(void *p) {} static void jsvalue_free(void *p) { struct jsvalue *ptr = p; - rb_js_abi_host_js_abi_value_free(&ptr->abi); + rb_js_abi_host_drop_js_value(ptr->abi); ruby_xfree(ptr); } @@ -207,7 +207,7 @@ static VALUE _rb_js_obj_aset(VALUE obj, VALUE key, VALUE val) { rb_js_abi_host_js_abi_result_t ret; rb_js_abi_host_reflect_set(p->abi, &key_abi_str, v->abi, &ret); raise_js_error_if_failure(&ret); - rb_js_abi_host_js_abi_value_free(&ret.val.success); + rb_js_abi_host_drop_js_value(ret.val.success); RB_GC_GUARD(rv); return val; } diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts index 826318829..9e758bf84 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts @@ -24,6 +24,11 @@ export interface RawIntegerBignum { } export function addRbJsAbiHostToImports(imports: any, obj: RbJsAbiHost, get_export: (name: string) => WebAssembly.ExportValue): void; export interface RbJsAbiHost { + /** + * Dispose of a JavaScript value. This should be called when a handle to a + * JavaScript value is no longer needed by the Ruby program. + */ + dropJsValue(value: JsAbiValue): void; evalJs(code: string): JsAbiResult; isJs(value: JsAbiValue): boolean; instanceOf(value: JsAbiValue, klass: JsAbiValue): boolean; diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js index ece59bb54..b7420f2f4 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js @@ -1,6 +1,9 @@ import { data_view, to_uint32, UTF8_DECODER, utf8_encode, UTF8_ENCODED_LEN, throw_invalid_bool } from './intrinsics.js'; export function addRbJsAbiHostToImports(imports, obj, get_export) { if (!("rb-js-abi-host" in imports)) imports["rb-js-abi-host"] = {}; + imports["rb-js-abi-host"]["drop-js-value: func(value: u32) -> ()"] = function(arg0) { + obj.dropJsValue(arg0 >>> 0); + }; imports["rb-js-abi-host"]["eval-js: func(code: string) -> variant { success(u32), failure(u32) }"] = function(arg0, arg1, arg2) { const memory = get_export("memory"); const ptr0 = arg0; From 06a9da264b298640f3a4955807848f59ccc05d27 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 18:02:05 +0000 Subject: [PATCH 04/10] Add interface to drop handle to rb value --- ext/witapi/bindgen/rb-abi-guest.c | 4 ++++ ext/witapi/bindgen/rb-abi-guest.h | 1 + ext/witapi/bindgen/rb-abi-guest.wit | 4 ++++ ext/witapi/witapi-core.c | 4 ++-- .../ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts | 5 +++++ .../npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js | 3 +++ 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ext/witapi/bindgen/rb-abi-guest.c b/ext/witapi/bindgen/rb-abi-guest.c index d5b2b6984..66f1d8350 100644 --- a/ext/witapi/bindgen/rb-abi-guest.c +++ b/ext/witapi/bindgen/rb-abi-guest.c @@ -49,6 +49,10 @@ void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr) __attribute__((aligned(4))) static uint8_t RET_AREA[8]; +__attribute__((export_name("drop-rb-value: func(value: u32) -> ()"))) +void __wasm_export_rb_abi_guest_drop_rb_value(int32_t arg) { + rb_abi_guest_drop_rb_value((uint32_t) (arg)); +} __attribute__((export_name("ruby-show-version: func() -> ()"))) void __wasm_export_rb_abi_guest_ruby_show_version(void) { rb_abi_guest_ruby_show_version(); diff --git a/ext/witapi/bindgen/rb-abi-guest.h b/ext/witapi/bindgen/rb-abi-guest.h index 551568bb3..978daa5af 100644 --- a/ext/witapi/bindgen/rb-abi-guest.h +++ b/ext/witapi/bindgen/rb-abi-guest.h @@ -35,6 +35,7 @@ extern "C" size_t len; } rb_abi_guest_list_rb_abi_value_t; void rb_abi_guest_list_rb_abi_value_free(rb_abi_guest_list_rb_abi_value_t *ptr); + void rb_abi_guest_drop_rb_value(rb_abi_guest_rb_abi_value_t value); void rb_abi_guest_ruby_show_version(void); void rb_abi_guest_ruby_init(void); void rb_abi_guest_ruby_sysinit(rb_abi_guest_list_string_t *args); diff --git a/ext/witapi/bindgen/rb-abi-guest.wit b/ext/witapi/bindgen/rb-abi-guest.wit index bb235bcae..b59818f3e 100644 --- a/ext/witapi/bindgen/rb-abi-guest.wit +++ b/ext/witapi/bindgen/rb-abi-guest.wit @@ -2,6 +2,10 @@ /// This represents a handle owned by the Ruby guest environment. type rb-abi-value = u32 +/// Dispose of a Ruby value. This should be called when a handle to a +/// Ruby value is no longer needed by the host environment. +drop-rb-value: func(value: rb-abi-value) + type rb-errno = s32 type rb-id = u32 diff --git a/ext/witapi/witapi-core.c b/ext/witapi/witapi-core.c index 67aa872eb..05d9a842d 100644 --- a/ext/witapi/witapi-core.c +++ b/ext/witapi/witapi-core.c @@ -199,8 +199,8 @@ static VALUE rb_abi_guest_rb_abi_value_dtor_internal(VALUE obj) { return Qundef; } -void rb_abi_guest_rb_abi_value_dtor(void *data) { - RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: data = %p\n", data); +void rb_abi_guest_drop_rb_value(rb_abi_guest_rb_abi_value_t data) { + RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: data = %p\n", (void *)data); int state; RB_WASM_LIB_RT( rb_protect(rb_abi_guest_rb_abi_value_dtor_internal, (VALUE)data, &state)); diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts index dd6bc2c53..0d07e0c8e 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.d.ts @@ -72,6 +72,11 @@ export class RbAbiGuest { module: WebAssembly.Module | BufferSource | Promise | Response | WebAssembly.Instance, imports?: any, ): Promise; + /** + * Dispose of a Ruby value. This should be called when a handle to a + * Ruby value is no longer needed by the host environment. + */ + dropRbValue(value: RbAbiValue): void; rubyShowVersion(): void; rubyInit(): void; rubySysinit(args: string[]): void; diff --git a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js index e14f9af50..e1e1d0f89 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js +++ b/packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-abi-guest.js @@ -20,6 +20,9 @@ export class RbAbiGuest { } this._exports = this.instance.exports; } + dropRbValue(arg0) { + this._exports['drop-rb-value: func(value: u32) -> ()'](to_uint32(arg0)); + } rubyShowVersion() { this._exports['ruby-show-version: func() -> ()'](); } From 5dce0ae473bcdb610e0ba3a3957d2a1cb0838230 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 21:10:23 +0000 Subject: [PATCH 05/10] WIP --- .../npm-packages/ruby-wasm-wasi/src/index.ts | 178 +++++++++++++----- .../tools/shim-wit-resource.mjs | 141 ++++++++++++++ .../npm-packages/ruby-wasm-wasi/tsconfig.json | 1 + 3 files changed, 276 insertions(+), 44 deletions(-) create mode 100644 packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index dbbb2e9aa..b5f5401ad 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -30,6 +30,8 @@ export class RubyVM { private instance: WebAssembly.Instance | null = null; private transport: JsValueTransport; private exceptionFormatter: RbExceptionFormatter; + private guestObjectTracker: RbValueLifetimeTracker | null = null; + private hostObjectTracker: JsValueLifetimeTracker = new JsValueLifetimeTracker(); private interfaceState: RbAbiInterfaceState = { hasJSFrameAfterRbFrame: false, }; @@ -105,6 +107,9 @@ export class RubyVM { */ async setInstance(instance: WebAssembly.Instance) { this.instance = instance; + this.guestObjectTracker = new RbValueLifetimeTracker((rbAbiValue) => { + this.guest.dropRbValue(rbAbiValue); + }); await this.guest.instantiate(instance); } @@ -115,17 +120,17 @@ export class RubyVM { */ addToImports(imports: WebAssembly.Imports) { this.guest.addToImports(imports); - function wrapTry(f: (...args: any[]) => JsAbiValue): () => JsAbiResult { - return (...args) => { + const wrapTry = (f: (...args: any[]) => any): (...args: any[]) => JsAbiResult => { + return (...args: any[]) => { try { - return { tag: "success", val: f(...args) }; + return { tag: "success", val: this.hostObjectTracker.insert(f(...args)) }; } catch (e) { if (e instanceof RbFatalError) { // RbFatalError should not be caught by Ruby because it Ruby VM // can be already in an inconsistent state. throw e; } - return { tag: "failure", val: e }; + return { tag: "failure", val: this.hostObjectTracker.insert(e) }; } }; } @@ -175,6 +180,9 @@ export class RubyVM { addRbJsAbiHostToImports( imports, proxyImports({ + dropJsValue: (value) => { + this.hostObjectTracker.remove(value); + }, evalJs: wrapTry((code) => { return Function(code)(); }), @@ -183,42 +191,46 @@ export class RubyVM { return true; }, globalThis: () => { + let result: any; if (typeof globalThis !== "undefined") { - return globalThis; + result = globalThis; } else if (typeof global !== "undefined") { - return global; + result = global; } else if (typeof window !== "undefined") { - return window; + result = window; + } else { + throw new Error("unable to locate global object"); } - throw new Error("unable to locate global object"); + return this.hostObjectTracker.insert(result); }, intToJsNumber: (value) => { - return value; + return this.hostObjectTracker.insert(value); }, floatToJsNumber: (value) => { - return value; + return this.hostObjectTracker.insert(value); }, stringToJsString: (value) => { - return value; + return this.hostObjectTracker.insert(value); }, boolToJsBool: (value) => { - return value; + return this.hostObjectTracker.insert(value); }, procToJsFunction: (rawRbAbiValue) => { - const rbValue = this.rbValueOfPointer(rawRbAbiValue); - return (...args) => { - rbValue.call("call", ...args.map((arg) => this.wrap(arg))); - }; + const rbProcValue = this.rbValueOfPointer(rawRbAbiValue); + return this.hostObjectTracker.insert((...args: any[]) => { + rbProcValue.call("call", ...args.map((arg) => this.wrap(arg))); + }); }, rbObjectToJsRbValue: (rawRbAbiValue) => { - return this.rbValueOfPointer(rawRbAbiValue); + return this.hostObjectTracker.insert(this.rbValueOfPointer(rawRbAbiValue)); }, jsValueToString: (value) => { // According to the [spec](https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value) // `String(value)` always returns a string. - return String(value); + return String(this.hostObjectTracker.get(value)); }, - jsValueToInteger(value) { + jsValueToInteger(v) { + const value = this.hostObjectTracker.get(v); if (typeof value === "number") { return { tag: "f64", val: value }; } else if (typeof value === "bigint") { @@ -231,30 +243,36 @@ export class RubyVM { return { tag: "f64", val: Number(value) }; } }, - exportJsValueToHost: (value) => { + exportJsValueToHost: (v) => { // See `JsValueExporter` for the reason why we need to do this + const value = this.hostObjectTracker.get(v); this.transport.takeJsValue(value); }, importJsValueFromHost: () => { return this.transport.consumeJsValue(); }, - instanceOf: (value, klass) => { + instanceOf: (rawValue, rawKlass) => { + const value = this.hostObjectTracker.get(rawValue); + const klass = this.hostObjectTracker.get(rawKlass); if (typeof klass === "function") { return value instanceof klass; } else { return false; } }, - jsValueTypeof(value) { - return typeof value; + jsValueTypeof: (value) => { + return typeof this.hostObjectTracker.get(value); }, - jsValueEqual(lhs, rhs) { - return lhs == rhs; + jsValueEqual: (lhs, rhs) => { + return this.hostObjectTracker.get(lhs) == this.hostObjectTracker.get(rhs); }, - jsValueStrictlyEqual(lhs, rhs) { - return lhs === rhs; + jsValueStrictlyEqual: (lhs, rhs) => { + return this.hostObjectTracker.get(lhs) === this.hostObjectTracker.get(rhs); }, - reflectApply: wrapTry((target, thisArgument, args) => { + reflectApply: wrapTry((rawTarget, rawThisArgument, rawArgs: Uint32Array) => { + const target = this.hostObjectTracker.get(rawTarget); + const thisArgument = this.hostObjectTracker.get(rawThisArgument); + const args = rawArgs.map((arg) => this.hostObjectTracker.get(arg)); return Reflect.apply(target as any, thisArgument, args); }), reflectConstruct: function (target, args) { @@ -263,7 +281,8 @@ export class RubyVM { reflectDeleteProperty: function (target, propertyKey): boolean { throw new Error("Function not implemented."); }, - reflectGet: wrapTry((target, propertyKey) => { + reflectGet: wrapTry((rawTarget, propertyKey) => { + const target = this.hostObjectTracker.get(rawTarget); return target[propertyKey]; }), reflectGetOwnPropertyDescriptor: function ( @@ -287,7 +306,10 @@ export class RubyVM { reflectPreventExtensions: function (target): boolean { throw new Error("Function not implemented."); }, - reflectSet: wrapTry((target, propertyKey, value) => { + reflectSet: wrapTry((rawTarget, rawPropertyKey, rawValue) => { + const target = this.hostObjectTracker.get(rawTarget); + const propertyKey = this.hostObjectTracker.get(rawPropertyKey); + const value = this.hostObjectTracker.get(rawValue); return Reflect.set(target, propertyKey, value); }), reflectSetPrototypeOf: function (target, prototype): boolean { @@ -370,19 +392,20 @@ export class RubyVM { * hash.call("store", vm.eval(`"key1"`), vm.wrap(new Object())); */ wrap(value: any): RbValue { - return this.transport.importJsValue(value, this); + return this.transport.importJsValue(this.hostObjectTracker.insert(value), this); } private privateObject(): RubyVMPrivate { return { transport: this.transport, + guestObjectTracker: this.guestObjectTracker, + hostObjectTracker: this.hostObjectTracker, exceptionFormatter: this.exceptionFormatter, }; } - private rbValueOfPointer(pointer: number): RbValue { - const abiValue = new (RbAbi.RbAbiValue as any)(pointer, this.guest); - return new RbValue(abiValue, this, this.privateObject()); + private rbValueOfPointer(pointer: RbAbi.RbAbiValue): RbValue { + return new RbValue(pointer, this, this.privateObject()); } } @@ -446,7 +469,9 @@ export class RbValue { private inner: RbAbi.RbAbiValue, private vm: RubyVM, private privateObject: RubyVMPrivate - ) {} + ) { + this.privateObject.guestObjectTracker.track(inner); + } /** * Call a given method with given arguments @@ -462,11 +487,7 @@ export class RbValue { */ call(callee: string, ...args: RbValue[]): RbValue { const innerArgs = args.map((arg) => arg.inner); - return new RbValue( - callRbMethod(this.vm, this.privateObject, this.inner, callee, innerArgs), - this.vm, - this.privateObject - ); + return callRbMethod(this.vm, this.privateObject, this.inner, callee, innerArgs); } /** @@ -493,7 +514,7 @@ export class RbValue { "to_s", [] ); - return this.vm.guest.rstringPtr(rbString); + return this.vm.guest.rstringPtr(rbString.inner); } /** @@ -508,7 +529,8 @@ export class RbValue { if (jsValue.call("nil?").toString() === "true") { return null; } - return this.privateObject.transport.exportJsValue(jsValue); + const rawValue = this.privateObject.transport.exportJsValue(jsValue); + return this.privateObject.hostObjectTracker.get(rawValue); } } @@ -527,6 +549,8 @@ enum ruby_tag_type { type RubyVMPrivate = { transport: JsValueTransport; + hostObjectTracker: JsValueLifetimeTracker; + guestObjectTracker: RbValueLifetimeTracker; exceptionFormatter: RbExceptionFormatter; }; @@ -643,9 +667,10 @@ const callRbMethod = ( ) => { const mid = vm.guest.rbIntern(callee + "\0"); return wrapRbOperation(vm, () => { - const [value, status] = vm.guest.rbFuncallvProtect(recv, mid, args); + const rawArgs = Uint32Array.from(args); + const [value, status] = vm.guest.rbFuncallvProtect(recv, mid, rawArgs); checkStatusTag(status, vm, privateObject); - return value; + return new RbValue(value, vm, privateObject); }); }; const evalRbCode = (vm: RubyVM, privateObject: RubyVMPrivate, code: string) => { @@ -656,6 +681,71 @@ const evalRbCode = (vm: RubyVM, privateObject: RubyVMPrivate, code: string) => { }); }; +class LifetimeTracked { + constructor(public value: Value) {} +} + +class RbValueLifetimeTracker { + private registry: FinalizationRegistry + constructor(drop: (value: Value) => void) { + this.registry = new FinalizationRegistry((value) => { + drop(value); + }); + } + + track(value: Value) { + this.registry.register(new LifetimeTracked(value), value); + } +} + +type JsValueLifetimeSlot = { + next: number; + value: Value; +} + +class JsValueLifetimeTracker { + private list: JsValueLifetimeSlot[]; + private head: number; + + constructor() { + this.list = []; + this.head = 0; + } + + insert(value: Value): JsAbiValue { + if (this.head >= this.list.length) { + this.list.push({ + next: this.list.length + 1, + value: undefined, + }); + } + const ret = this.head; + const slot = this.list[ret]; + this.head = slot.next; + slot.next = -1; + slot.value = value; + return ret; + } + + get(idx: JsAbiValue) { + if (idx >= this.list.length) + throw new RangeError('handle index not valid'); + const slot = this.list[idx]; + if (slot.next === -1) + return slot.value; + throw new RangeError('handle index not valid'); + } + + remove(idx: JsAbiValue) { + const ret = this.get(idx); // validate the slot + const slot = this.list[idx]; + slot.value = undefined; + slot.next = this.head; + this.head = idx; + return ret; + } +} + /** * Error class thrown by Ruby execution */ diff --git a/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs b/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs new file mode 100644 index 000000000..1ae81bd9d --- /dev/null +++ b/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs @@ -0,0 +1,141 @@ +import ts from "typescript" +import path from "path" + +const findTopLevelStatement = (options) => { + const DEFAULT_COMPILER_OPTIONS = { + noEmit: true, + noEmitOnError: true, + noImplicitAny: true, + target: ts.ScriptTarget.ES5, + module: ts.ModuleKind.CommonJS + }; + const program = ts.createProgram([options.sourceFile], DEFAULT_COMPILER_OPTIONS) + for (const sourceFile of program.getSourceFiles()) { + if (options.sourceFile != sourceFile.fileName) continue + for (const statement of sourceFile.statements) { + if (options.condition(statement)) { + return [statement, sourceFile]; + } + } + } +} + +class Parameter { + /** + * @param {string} name + * @param {string} type + */ + constructor(name, type) { + this.name = name + this.type = type + } +} + + +class Method { + /** + * @param {string} name + * @param {Parameter[]} parameters + * @param {string} returnType + */ + constructor(name, parameters, returnType) { + this.name = name + this.parameters = parameters + this.returnType = returnType + } + + hasTypeInSignature(targetType) { + for (const parameter of this.parameters) { + if (parameter.type == targetType) { + return true + } + } + return this.returnType == targetType + } +} + +/** + * @param {ts.ClassDeclaration} classDecl + * @param {ts.SourceFile} sourceFile + * @returns {Method[]} + */ +const findMethodDecls = (classDecl, sourceFile) => { + const result = [] + for (const member of classDecl.members) { + if (member.kind != ts.SyntaxKind.MethodDeclaration) { + continue + } + /** + * @type {ts.MethodDeclaration} + */ + const method = member + const name = method.name.getText(sourceFile) + const parameters = method.parameters.map((parameter) => { + return new Parameter(parameter.name.getText(sourceFile), parameter.type.getText(sourceFile)) + }) + const returnType = method.type?.getText(sourceFile) ?? "void" + result.push(new Method(name, parameters, returnType)) + } + return result +} + +class CodeGenerator { + + /** + * @param {Method[]} methods + */ + emit(methods) { + let result = ` + export function shimExports( + liftUp: (result: number) => Wrapper, + liftDown: (wrapper: Wrapper) => number, + imports: Imports + ): Imports { + const newImports = Object.assign({}, imports) + ` + for (const method of methods) { + if (!method.hasTypeInSignature("RbAbiValue")) { + continue + } + result += ` + newImports.${method.name} = (...args: [${method.parameters.map((parameter) => parameter.type).join(", ")}]): ${method.returnType} => { + const result = liftDown(imports.${method.name}(${method.parameters.map((parameter) => parameter.name).join(", ")})) + return liftUp(result) + } + ` + } + + result += ` + return newImports + } + ` + return result + } +} + +const main = async () => { + const dirname = path.dirname(new URL(import.meta.url).pathname); + const guest = path.resolve(dirname, "../src/bindgen/rb-abi-guest.d.ts") + /** + * @type {[ts.ClassDeclaration, ts.SourceFile]} + */ + const [RbAbiGuest, sourceFile] = findTopLevelStatement( + { + sourceFile: guest, + condition: (statement) => { + return statement.kind == ts.SyntaxKind.ClassDeclaration && statement.name.text == "RbAbiGuest" + } + } + ) + + if (RbAbiGuest == null) { + console.log("RbAbiGuest not found") + return + } + + const methods = findMethodDecls(RbAbiGuest, sourceFile) + const generator = new CodeGenerator() + console.log(generator.emit(methods)) +} + +main() diff --git a/packages/npm-packages/ruby-wasm-wasi/tsconfig.json b/packages/npm-packages/ruby-wasm-wasi/tsconfig.json index cd3bb0d99..2712ff1e1 100644 --- a/packages/npm-packages/ruby-wasm-wasi/tsconfig.json +++ b/packages/npm-packages/ruby-wasm-wasi/tsconfig.json @@ -6,6 +6,7 @@ "module": "ES2015", "outDir": "./dist", "target": "es2017", + "lib": ["DOM", "ESNext.WeakRef"], "esModuleInterop": true, "moduleResolution": "node", "resolveJsonModule": true From f78615bfa05edc777690eff4fb8803aa2a9113f0 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 22:24:49 +0000 Subject: [PATCH 06/10] Fix regressions for the resource migration --- packages/npm-packages/ruby-wasm-wasi/src/index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index b5f5401ad..57435ae49 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -243,9 +243,8 @@ export class RubyVM { return { tag: "f64", val: Number(value) }; } }, - exportJsValueToHost: (v) => { + exportJsValueToHost: (value) => { // See `JsValueExporter` for the reason why we need to do this - const value = this.hostObjectTracker.get(v); this.transport.takeJsValue(value); }, importJsValueFromHost: () => { @@ -272,7 +271,10 @@ export class RubyVM { reflectApply: wrapTry((rawTarget, rawThisArgument, rawArgs: Uint32Array) => { const target = this.hostObjectTracker.get(rawTarget); const thisArgument = this.hostObjectTracker.get(rawThisArgument); - const args = rawArgs.map((arg) => this.hostObjectTracker.get(arg)); + const args: any[] = [] + for (const arg of rawArgs) { + args.push(this.hostObjectTracker.get(arg)); + } return Reflect.apply(target as any, thisArgument, args); }), reflectConstruct: function (target, args) { From b24a93805e0a46ef694529003397062f40bcf391 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 22:25:18 +0000 Subject: [PATCH 07/10] Repair failing test depending on internal object shape --- packages/npm-packages/ruby-wasm-wasi/src/index.ts | 4 ++-- packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index 57435ae49..8c5bac4b7 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -689,9 +689,9 @@ class LifetimeTracked { class RbValueLifetimeTracker { private registry: FinalizationRegistry - constructor(drop: (value: Value) => void) { + constructor(private drop: (value: Value) => void) { this.registry = new FinalizationRegistry((value) => { - drop(value); + this.drop(value); }); } diff --git a/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts b/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts index 0afee7b38..79d9c61d0 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts @@ -28,7 +28,8 @@ describe("GC integration", () => { test("protect exported Ruby objects", async () => { function dropRbValue(value: RbValue) { - (value as any).inner.drop(); + const internal = (value as any) + internal.privateObject.guestObjectTracker.drop(internal.inner); } const vm = await initRubyVM(); const initialGCCount = Number(vm.eval("GC.count").toString()); From eff89527008635e45300dc39061099624c46ac24 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 22:26:52 +0000 Subject: [PATCH 08/10] Remove poc shim generator --- .../tools/shim-wit-resource.mjs | 141 ------------------ 1 file changed, 141 deletions(-) delete mode 100644 packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs diff --git a/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs b/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs deleted file mode 100644 index 1ae81bd9d..000000000 --- a/packages/npm-packages/ruby-wasm-wasi/tools/shim-wit-resource.mjs +++ /dev/null @@ -1,141 +0,0 @@ -import ts from "typescript" -import path from "path" - -const findTopLevelStatement = (options) => { - const DEFAULT_COMPILER_OPTIONS = { - noEmit: true, - noEmitOnError: true, - noImplicitAny: true, - target: ts.ScriptTarget.ES5, - module: ts.ModuleKind.CommonJS - }; - const program = ts.createProgram([options.sourceFile], DEFAULT_COMPILER_OPTIONS) - for (const sourceFile of program.getSourceFiles()) { - if (options.sourceFile != sourceFile.fileName) continue - for (const statement of sourceFile.statements) { - if (options.condition(statement)) { - return [statement, sourceFile]; - } - } - } -} - -class Parameter { - /** - * @param {string} name - * @param {string} type - */ - constructor(name, type) { - this.name = name - this.type = type - } -} - - -class Method { - /** - * @param {string} name - * @param {Parameter[]} parameters - * @param {string} returnType - */ - constructor(name, parameters, returnType) { - this.name = name - this.parameters = parameters - this.returnType = returnType - } - - hasTypeInSignature(targetType) { - for (const parameter of this.parameters) { - if (parameter.type == targetType) { - return true - } - } - return this.returnType == targetType - } -} - -/** - * @param {ts.ClassDeclaration} classDecl - * @param {ts.SourceFile} sourceFile - * @returns {Method[]} - */ -const findMethodDecls = (classDecl, sourceFile) => { - const result = [] - for (const member of classDecl.members) { - if (member.kind != ts.SyntaxKind.MethodDeclaration) { - continue - } - /** - * @type {ts.MethodDeclaration} - */ - const method = member - const name = method.name.getText(sourceFile) - const parameters = method.parameters.map((parameter) => { - return new Parameter(parameter.name.getText(sourceFile), parameter.type.getText(sourceFile)) - }) - const returnType = method.type?.getText(sourceFile) ?? "void" - result.push(new Method(name, parameters, returnType)) - } - return result -} - -class CodeGenerator { - - /** - * @param {Method[]} methods - */ - emit(methods) { - let result = ` - export function shimExports( - liftUp: (result: number) => Wrapper, - liftDown: (wrapper: Wrapper) => number, - imports: Imports - ): Imports { - const newImports = Object.assign({}, imports) - ` - for (const method of methods) { - if (!method.hasTypeInSignature("RbAbiValue")) { - continue - } - result += ` - newImports.${method.name} = (...args: [${method.parameters.map((parameter) => parameter.type).join(", ")}]): ${method.returnType} => { - const result = liftDown(imports.${method.name}(${method.parameters.map((parameter) => parameter.name).join(", ")})) - return liftUp(result) - } - ` - } - - result += ` - return newImports - } - ` - return result - } -} - -const main = async () => { - const dirname = path.dirname(new URL(import.meta.url).pathname); - const guest = path.resolve(dirname, "../src/bindgen/rb-abi-guest.d.ts") - /** - * @type {[ts.ClassDeclaration, ts.SourceFile]} - */ - const [RbAbiGuest, sourceFile] = findTopLevelStatement( - { - sourceFile: guest, - condition: (statement) => { - return statement.kind == ts.SyntaxKind.ClassDeclaration && statement.name.text == "RbAbiGuest" - } - } - ) - - if (RbAbiGuest == null) { - console.log("RbAbiGuest not found") - return - } - - const methods = findMethodDecls(RbAbiGuest, sourceFile) - const generator = new CodeGenerator() - console.log(generator.emit(methods)) -} - -main() From 4ce4fed7479219fdbb56d3f2d036bf506671b63b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 22:34:05 +0000 Subject: [PATCH 09/10] rake format --- ext/js/lib/js.rb | 11 +-- ext/witapi/witapi-core.c | 9 ++- .../ruby-wasm-wasi/jest.config.js | 2 +- .../ruby-wasm-wasi/src/browser.script.ts | 8 ++- .../ruby-wasm-wasi/src/browser.ts | 4 +- .../npm-packages/ruby-wasm-wasi/src/index.ts | 72 ++++++++++++------- .../npm-packages/ruby-wasm-wasi/src/node.ts | 4 +- .../test-e2e/examples/examples.spec.ts | 48 ++++++------- .../integrations/browser-script.spec.ts | 34 ++++----- .../test-e2e/playwright.examples.config.ts | 12 ++-- .../playwright.integrations.config.ts | 6 +- .../ruby-wasm-wasi/test-e2e/support.ts | 38 +++++----- .../ruby-wasm-wasi/test/eval_async.test.ts | 4 +- .../ruby-wasm-wasi/test/gc.test.ts | 2 +- .../ruby-wasm-wasi/test/package.test.ts | 2 +- .../ruby-wasm-wasi/tools/pack-compat-shim.mjs | 72 ++++++++++--------- tasks/packaging.rake | 3 +- 17 files changed, 189 insertions(+), 142 deletions(-) diff --git a/ext/js/lib/js.rb b/ext/js/lib/js.rb index 4dc65ec43..ec1643bce 100644 --- a/ext/js/lib/js.rb +++ b/ext/js/lib/js.rb @@ -51,11 +51,12 @@ def await(promise) ->(value) { current.transfer(value, :failure) } ) if @loop == current - raise ("JS::Object#await can be called only from RubyVM#evalAsync JS API\n" + - "If you are using browser.script.iife.js, please ensure that you specify `data-eval=\"async\"` in your script tag\n" + - "e.g. \n" + - "Or ") - + raise ( + "JS::Object#await can be called only from RubyVM#evalAsync JS API\n" + + "If you are using browser.script.iife.js, please ensure that you specify `data-eval=\"async\"` in your script tag\n" + + "e.g. \n" + + "Or " + ) end value, status = @loop.transfer raise JS::Error.new(value) if status == :failure diff --git a/ext/witapi/witapi-core.c b/ext/witapi/witapi-core.c index 05d9a842d..8e0ff41b0 100644 --- a/ext/witapi/witapi-core.c +++ b/ext/witapi/witapi-core.c @@ -172,10 +172,12 @@ void rb_abi_lend_object(VALUE obj) { assert(state == TAG_NONE && "rb_abi_lend_object_internal failed"); } -static inline rb_abi_guest_rb_abi_value_t rb_abi_guest_rb_abi_value_new(VALUE obj) { +static inline rb_abi_guest_rb_abi_value_t +rb_abi_guest_rb_abi_value_new(VALUE obj) { return (rb_abi_guest_rb_abi_value_t)(obj); } -static inline VALUE rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *self) { +static inline VALUE +rb_abi_guest_rb_abi_value_get(rb_abi_guest_rb_abi_value_t *self) { return (VALUE)(*self); } @@ -200,7 +202,8 @@ static VALUE rb_abi_guest_rb_abi_value_dtor_internal(VALUE obj) { } void rb_abi_guest_drop_rb_value(rb_abi_guest_rb_abi_value_t data) { - RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: data = %p\n", (void *)data); + RB_WASM_DEBUG_LOG("rb_abi_guest_rb_abi_value_dtor: data = %p\n", + (void *)data); int state; RB_WASM_LIB_RT( rb_protect(rb_abi_guest_rb_abi_value_dtor_internal, (VALUE)data, &state)); diff --git a/packages/npm-packages/ruby-wasm-wasi/jest.config.js b/packages/npm-packages/ruby-wasm-wasi/jest.config.js index 30e761d79..93e356d20 100644 --- a/packages/npm-packages/ruby-wasm-wasi/jest.config.js +++ b/packages/npm-packages/ruby-wasm-wasi/jest.config.js @@ -1,4 +1,4 @@ module.exports = { testEnvironment: "node", - testPathIgnorePatterns: ["/node_modules/", "/test-e2e/"] + testPathIgnorePatterns: ["/node_modules/", "/test-e2e/"], }; diff --git a/packages/npm-packages/ruby-wasm-wasi/src/browser.script.ts b/packages/npm-packages/ruby-wasm-wasi/src/browser.script.ts index 52bc3800f..4d202a1bb 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/browser.script.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/browser.script.ts @@ -51,13 +51,17 @@ const runRubyScriptsInHtml = async (vm) => { const deriveEvalStyle = (tag: Element): "async" | "sync" => { const rawEvalStyle = tag.getAttribute("data-eval") || "sync"; if (rawEvalStyle !== "async" && rawEvalStyle !== "sync") { - console.warn(`data-eval attribute of script tag must be "async" or "sync". ${rawEvalStyle} is ignored and "sync" is used instead.`); + console.warn( + `data-eval attribute of script tag must be "async" or "sync". ${rawEvalStyle} is ignored and "sync" is used instead.` + ); return "sync"; } return rawEvalStyle; }; -const loadScriptAsync = async (tag: Element): Promise<{ scriptContent: string, evalStyle: "async" | "sync" } | null> => { +const loadScriptAsync = async ( + tag: Element +): Promise<{ scriptContent: string; evalStyle: "async" | "sync" } | null> => { const evalStyle = deriveEvalStyle(tag); // Inline comments can be written with the src attribute of the script tag. // The presence of the src attribute is checked before the presence of the inline. diff --git a/packages/npm-packages/ruby-wasm-wasi/src/browser.ts b/packages/npm-packages/ruby-wasm-wasi/src/browser.ts index eaf90cd45..c773d5f8c 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/browser.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/browser.ts @@ -76,8 +76,8 @@ export const DefaultRubyVM = async ( // default Fiber stack size as well as main stack size allocated // by wasm-ld's --stack-size. The ideal solution is to reduce // stack consumption in setjmp. - "RUBY_FIBER_MACHINE_STACK_SIZE": "16777216" - } + RUBY_FIBER_MACHINE_STACK_SIZE: "16777216", + }, }); const vm = new RubyVM(); diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index 8c5bac4b7..988519361 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -30,8 +30,10 @@ export class RubyVM { private instance: WebAssembly.Instance | null = null; private transport: JsValueTransport; private exceptionFormatter: RbExceptionFormatter; - private guestObjectTracker: RbValueLifetimeTracker | null = null; - private hostObjectTracker: JsValueLifetimeTracker = new JsValueLifetimeTracker(); + private guestObjectTracker: RbValueLifetimeTracker | null = + null; + private hostObjectTracker: JsValueLifetimeTracker = + new JsValueLifetimeTracker(); private interfaceState: RbAbiInterfaceState = { hasJSFrameAfterRbFrame: false, }; @@ -120,10 +122,15 @@ export class RubyVM { */ addToImports(imports: WebAssembly.Imports) { this.guest.addToImports(imports); - const wrapTry = (f: (...args: any[]) => any): (...args: any[]) => JsAbiResult => { + const wrapTry = ( + f: (...args: any[]) => any + ): ((...args: any[]) => JsAbiResult) => { return (...args: any[]) => { try { - return { tag: "success", val: this.hostObjectTracker.insert(f(...args)) }; + return { + tag: "success", + val: this.hostObjectTracker.insert(f(...args)), + }; } catch (e) { if (e instanceof RbFatalError) { // RbFatalError should not be caught by Ruby because it Ruby VM @@ -133,7 +140,7 @@ export class RubyVM { return { tag: "failure", val: this.hostObjectTracker.insert(e) }; } }; - } + }; imports["rb-js-abi-host"] = { rb_wasm_throw_prohibit_rewind_exception: ( messagePtr: number, @@ -222,7 +229,9 @@ export class RubyVM { }); }, rbObjectToJsRbValue: (rawRbAbiValue) => { - return this.hostObjectTracker.insert(this.rbValueOfPointer(rawRbAbiValue)); + return this.hostObjectTracker.insert( + this.rbValueOfPointer(rawRbAbiValue) + ); }, jsValueToString: (value) => { // According to the [spec](https://tc39.es/ecma262/multipage/text-processing.html#sec-string-constructor-string-value) @@ -263,20 +272,26 @@ export class RubyVM { return typeof this.hostObjectTracker.get(value); }, jsValueEqual: (lhs, rhs) => { - return this.hostObjectTracker.get(lhs) == this.hostObjectTracker.get(rhs); + return ( + this.hostObjectTracker.get(lhs) == this.hostObjectTracker.get(rhs) + ); }, jsValueStrictlyEqual: (lhs, rhs) => { - return this.hostObjectTracker.get(lhs) === this.hostObjectTracker.get(rhs); + return ( + this.hostObjectTracker.get(lhs) === this.hostObjectTracker.get(rhs) + ); }, - reflectApply: wrapTry((rawTarget, rawThisArgument, rawArgs: Uint32Array) => { - const target = this.hostObjectTracker.get(rawTarget); - const thisArgument = this.hostObjectTracker.get(rawThisArgument); - const args: any[] = [] - for (const arg of rawArgs) { - args.push(this.hostObjectTracker.get(arg)); + reflectApply: wrapTry( + (rawTarget, rawThisArgument, rawArgs: Uint32Array) => { + const target = this.hostObjectTracker.get(rawTarget); + const thisArgument = this.hostObjectTracker.get(rawThisArgument); + const args: any[] = []; + for (const arg of rawArgs) { + args.push(this.hostObjectTracker.get(arg)); + } + return Reflect.apply(target as any, thisArgument, args); } - return Reflect.apply(target as any, thisArgument, args); - }), + ), reflectConstruct: function (target, args) { throw new Error("Function not implemented."); }, @@ -394,7 +409,10 @@ export class RubyVM { * hash.call("store", vm.eval(`"key1"`), vm.wrap(new Object())); */ wrap(value: any): RbValue { - return this.transport.importJsValue(this.hostObjectTracker.insert(value), this); + return this.transport.importJsValue( + this.hostObjectTracker.insert(value), + this + ); } private privateObject(): RubyVMPrivate { @@ -489,7 +507,13 @@ export class RbValue { */ call(callee: string, ...args: RbValue[]): RbValue { const innerArgs = args.map((arg) => arg.inner); - return callRbMethod(this.vm, this.privateObject, this.inner, callee, innerArgs); + return callRbMethod( + this.vm, + this.privateObject, + this.inner, + callee, + innerArgs + ); } /** @@ -688,7 +712,7 @@ class LifetimeTracked { } class RbValueLifetimeTracker { - private registry: FinalizationRegistry + private registry: FinalizationRegistry; constructor(private drop: (value: Value) => void) { this.registry = new FinalizationRegistry((value) => { this.drop(value); @@ -703,7 +727,7 @@ class RbValueLifetimeTracker { type JsValueLifetimeSlot = { next: number; value: Value; -} +}; class JsValueLifetimeTracker { private list: JsValueLifetimeSlot[]; @@ -730,12 +754,10 @@ class JsValueLifetimeTracker { } get(idx: JsAbiValue) { - if (idx >= this.list.length) - throw new RangeError('handle index not valid'); + if (idx >= this.list.length) throw new RangeError("handle index not valid"); const slot = this.list[idx]; - if (slot.next === -1) - return slot.value; - throw new RangeError('handle index not valid'); + if (slot.next === -1) return slot.value; + throw new RangeError("handle index not valid"); } remove(idx: JsAbiValue) { diff --git a/packages/npm-packages/ruby-wasm-wasi/src/node.ts b/packages/npm-packages/ruby-wasm-wasi/src/node.ts index 245ec4d4e..f997ff6aa 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/node.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/node.ts @@ -8,8 +8,8 @@ export const DefaultRubyVM = async (rubyModule: WebAssembly.Module) => { // default Fiber stack size as well as main stack size allocated // by wasm-ld's --stack-size. The ideal solution is to reduce // stack consumption in setjmp. - "RUBY_FIBER_MACHINE_STACK_SIZE": "16777216" - } + RUBY_FIBER_MACHINE_STACK_SIZE: "16777216", + }, }); const vm = new RubyVM(); const imports = { diff --git a/packages/npm-packages/ruby-wasm-wasi/test-e2e/examples/examples.spec.ts b/packages/npm-packages/ruby-wasm-wasi/test-e2e/examples/examples.spec.ts index 8d613999f..7db88ce05 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test-e2e/examples/examples.spec.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test-e2e/examples/examples.spec.ts @@ -1,42 +1,42 @@ -import { test, expect, Page } from '@playwright/test'; -import path from "path" -import { waitForRubyVM, setupDebugLog, setupProxy } from "../support" +import { test, expect, Page } from "@playwright/test"; +import path from "path"; +import { waitForRubyVM, setupDebugLog, setupProxy } from "../support"; test.beforeEach(async ({ context }) => { setupDebugLog(context); if (process.env.RUBY_NPM_PACKAGE_ROOT) { setupProxy(context); } else { - console.info("Testing against CDN deployed files") + console.info("Testing against CDN deployed files"); } -}) +}); -test('hello.html is healthy', async ({ page }) => { - const messages = [] - page.on("console", msg => messages.push(msg.text())) - await page.goto('/hello.html'); +test("hello.html is healthy", async ({ page }) => { + const messages = []; + page.on("console", (msg) => messages.push(msg.text())); + await page.goto("/hello.html"); - await waitForRubyVM(page) - expect(messages[messages.length - 1]).toEqual("Hello, world!\n") + await waitForRubyVM(page); + expect(messages[messages.length - 1]).toEqual("Hello, world!\n"); }); -test('lucky.html is healthy', async ({ page }) => { - await page.goto('/lucky.html'); - await waitForRubyVM(page) - await page.getByRole('button', { name: 'Draw Omikuji' }).click() - const result = await page.locator("#result").textContent() +test("lucky.html is healthy", async ({ page }) => { + await page.goto("/lucky.html"); + await waitForRubyVM(page); + await page.getByRole("button", { name: "Draw Omikuji" }).click(); + const result = await page.locator("#result").textContent(); - expect(result).toMatch(/(Lucky|Unlucky)/) + expect(result).toMatch(/(Lucky|Unlucky)/); }); -test('script-src/index.html is healthy', async ({ page }) => { - const messages = [] - page.on("console", msg => messages.push(msg.text())) - await page.goto('/script-src/index.html'); +test("script-src/index.html is healthy", async ({ page }) => { + const messages = []; + page.on("console", (msg) => messages.push(msg.text())); + await page.goto("/script-src/index.html"); - await waitForRubyVM(page) - const expected = "Hello, world!\n" + await waitForRubyVM(page); + const expected = "Hello, world!\n"; while (messages[messages.length - 1] != expected) { - await page.waitForEvent("console") + await page.waitForEvent("console"); } }); diff --git a/packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts b/packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts index 89e723412..d1428769b 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test-e2e/integrations/browser-script.spec.ts @@ -1,25 +1,25 @@ -import { test, expect, Page } from '@playwright/test'; +import { test, expect, Page } from "@playwright/test"; -import { setupDebugLog, setupProxy, waitForRubyVM } from "../support" +import { setupDebugLog, setupProxy, waitForRubyVM } from "../support"; if (!process.env.RUBY_NPM_PACKAGE_ROOT) { - test.skip('skip', () => {}) + test.skip("skip", () => {}); } else { test.beforeEach(async ({ context }) => { setupDebugLog(context); setupProxy(context); - }) + }); const resolveBinding = async (page: Page, name: string) => { let checkResolved; const resolvedValue = new Promise((resolve) => { checkResolved = resolve; - }) + }); await page.exposeBinding(name, async (source, v) => { checkResolved(v); }); - return async () => await resolvedValue - } + return async () => await resolvedValue; + }; test.describe('data-eval="async"', () => { test("JS::Object#await returns value", async ({ page }) => { @@ -30,9 +30,9 @@ if (!process.env.RUBY_NPM_PACKAGE_ROOT) { require "js" JS.global.checkResolved JS.global[:Promise].resolve(42).await - `) + `); expect(await resolve()).toBe(42); - }) + }); test("JS::Object#await throws error on default attr", async ({ page }) => { await page.setContent(` @@ -41,10 +41,12 @@ if (!process.env.RUBY_NPM_PACKAGE_ROOT) { require "js" JS.global[:Promise].resolve(42).await - `) - const error = await page.waitForEvent("pageerror") - expect(error.message).toMatch(/please ensure that you specify `data-eval="async"`/) - }) + `); + const error = await page.waitForEvent("pageerror"); + expect(error.message).toMatch( + /please ensure that you specify `data-eval="async"`/ + ); + }); test("default stack size is enough to require 'json'", async ({ page }) => { const resolve = await resolveBinding(page, "checkResolved"); @@ -54,8 +56,8 @@ if (!process.env.RUBY_NPM_PACKAGE_ROOT) { require 'json' JS.global.checkResolved "ok" - `) + `); expect(await resolve()).toBe("ok"); - }) - }) + }); + }); } diff --git a/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.examples.config.ts b/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.examples.config.ts index 9cec45e80..64f6cbb86 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.examples.config.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.examples.config.ts @@ -1,15 +1,15 @@ -import { defineConfig } from '@playwright/test'; -import base from "./playwright.base.config" +import { defineConfig } from "@playwright/test"; +import base from "./playwright.base.config"; export default defineConfig({ ...base, - testDir: 'examples', + testDir: "examples", use: { - baseURL: 'http://127.0.0.1:8085', + baseURL: "http://127.0.0.1:8085", }, webServer: { - command: 'npm run serve:example', - url: 'http://127.0.0.1:8085', + command: "npm run serve:example", + url: "http://127.0.0.1:8085", reuseExistingServer: !process.env.CI, }, }); diff --git a/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.integrations.config.ts b/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.integrations.config.ts index 2fafed8bc..a8fba5d9b 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.integrations.config.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test-e2e/playwright.integrations.config.ts @@ -1,7 +1,7 @@ -import { defineConfig } from '@playwright/test'; -import base from "./playwright.base.config" +import { defineConfig } from "@playwright/test"; +import base from "./playwright.base.config"; export default defineConfig({ ...base, - testDir: 'integrations', + testDir: "integrations", }); diff --git a/packages/npm-packages/ruby-wasm-wasi/test-e2e/support.ts b/packages/npm-packages/ruby-wasm-wasi/test-e2e/support.ts index 2aa58994a..7c59c6329 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test-e2e/support.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test-e2e/support.ts @@ -1,24 +1,30 @@ -import { BrowserContext, Page } from '@playwright/test'; -import path from "path" +import { BrowserContext, Page } from "@playwright/test"; +import path from "path"; export const waitForRubyVM = async (page: Page) => { - await page.waitForFunction(() => window["rubyVM"]) -} + await page.waitForFunction(() => window["rubyVM"]); +}; export const setupDebugLog = (context: BrowserContext) => { if (process.env.DEBUG) { - context.on('request', request => console.log('>>', request.method(), request.url())); - context.on('response', response => console.log('<<', response.status(), response.url())); - context.on("console", msg => console.log("LOG:", msg.text())) + context.on("request", (request) => + console.log(">>", request.method(), request.url()) + ); + context.on("response", (response) => + console.log("<<", response.status(), response.url()) + ); + context.on("console", (msg) => console.log("LOG:", msg.text())); } -} +}; export const setupProxy = (context: BrowserContext) => { - const cdnPattern = /cdn.jsdelivr.net\/npm\/ruby-.+-wasm-wasi@.+\/dist\/(.+)/ - context.route(cdnPattern, route => { - const request = route.request() - console.log(">> [MOCK]", request.method(), request.url()) - const relativePath = request.url().match(cdnPattern)[1] - route.fulfill({ path: path.join(process.env.RUBY_NPM_PACKAGE_ROOT, "dist", relativePath) }) - }) -} + const cdnPattern = /cdn.jsdelivr.net\/npm\/ruby-.+-wasm-wasi@.+\/dist\/(.+)/; + context.route(cdnPattern, (route) => { + const request = route.request(); + console.log(">> [MOCK]", request.method(), request.url()); + const relativePath = request.url().match(cdnPattern)[1]; + route.fulfill({ + path: path.join(process.env.RUBY_NPM_PACKAGE_ROOT, "dist", relativePath), + }); + }); +}; diff --git a/packages/npm-packages/ruby-wasm-wasi/test/eval_async.test.ts b/packages/npm-packages/ruby-wasm-wasi/test/eval_async.test.ts index 952158524..504875864 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test/eval_async.test.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test/eval_async.test.ts @@ -34,6 +34,8 @@ describe("Async Ruby code evaluation", () => { const vm = await initRubyVM(); expect(() => { vm.eval(`require "js"; JS.global[:Promise].resolve(42).await`); - }).toThrowError("JS::Object#await can be called only from RubyVM#evalAsync JS API"); + }).toThrowError( + "JS::Object#await can be called only from RubyVM#evalAsync JS API" + ); }); }); diff --git a/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts b/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts index 79d9c61d0..b9c54d196 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test/gc.test.ts @@ -28,7 +28,7 @@ describe("GC integration", () => { test("protect exported Ruby objects", async () => { function dropRbValue(value: RbValue) { - const internal = (value as any) + const internal = value as any; internal.privateObject.guestObjectTracker.drop(internal.inner); } const vm = await initRubyVM(); diff --git a/packages/npm-packages/ruby-wasm-wasi/test/package.test.ts b/packages/npm-packages/ruby-wasm-wasi/test/package.test.ts index 6bf9f5875..4b90675d3 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test/package.test.ts +++ b/packages/npm-packages/ruby-wasm-wasi/test/package.test.ts @@ -30,7 +30,7 @@ const initRubyVM = async (rubyModule: WebAssembly.Module, args: string[]) => { describe("Packaging validation", () => { jest.setTimeout(20 /*sec*/ * 1000); if (!process.env.RUBY_NPM_PACKAGE_ROOT) { - test.skip('skip', () => {}) + test.skip("skip", () => {}); return; } diff --git a/packages/npm-packages/ruby-wasm-wasi/tools/pack-compat-shim.mjs b/packages/npm-packages/ruby-wasm-wasi/tools/pack-compat-shim.mjs index 1b93fa77b..abe5e7043 100755 --- a/packages/npm-packages/ruby-wasm-wasi/tools/pack-compat-shim.mjs +++ b/packages/npm-packages/ruby-wasm-wasi/tools/pack-compat-shim.mjs @@ -1,53 +1,59 @@ #!/usr/bin/env node -import path from 'path'; -import fs from 'fs'; +import path from "path"; +import fs from "fs"; const parseArgs = () => { const args = process.argv.slice(2); const options = {}; args.forEach((arg) => { - const [key, value] = arg.split('='); - options[key.replace('--', '')] = value; + const [key, value] = arg.split("="); + options[key.replace("--", "")] = value; }); return options; }; const shimContent = (target, pkg) => { - const suffix = target.split('.').slice(-2).join('.'); + const suffix = target.split(".").slice(-2).join("."); const deprecationMessage = (original, replacement) => { - return `DEPRECATED(${pkg}): "${target}" will be moved to "@ruby/wasm-wasi" in the next major release.\n` - + `Please replace your \\\`${original}\\\` with \\\`${replacement}\\\``; + return ( + `DEPRECATED(${pkg}): "${target}" will be moved to "@ruby/wasm-wasi" in the next major release.\n` + + `Please replace your \\\`${original}\\\` with \\\`${replacement}\\\`` + ); }; - let originalImport = ''; - let newImport = ''; + let originalImport = ""; + let newImport = ""; switch (suffix) { - case 'cjs.js': - originalImport = `require('${pkg}/dist/${target}');`; - newImport = `require('@ruby/wasm-wasi/dist/${target}');`; - break; - case 'umd.js': - originalImport = `require('${pkg}/dist/${target}');`; - newImport = `require('@ruby/wasm-wasi/dist/${target}');`; - break; - case 'd.ts': - case 'esm.js': - originalImport = `import * from '${pkg}/dist/${target}';`; - newImport = `import * from '@ruby/wasm-wasi/dist/${target}';`; - break; - default: - throw new Error(`Unknown suffix: ${suffix} for target ${target}`); + case "cjs.js": + originalImport = `require('${pkg}/dist/${target}');`; + newImport = `require('@ruby/wasm-wasi/dist/${target}');`; + break; + case "umd.js": + originalImport = `require('${pkg}/dist/${target}');`; + newImport = `require('@ruby/wasm-wasi/dist/${target}');`; + break; + case "d.ts": + case "esm.js": + originalImport = `import * from '${pkg}/dist/${target}';`; + newImport = `import * from '@ruby/wasm-wasi/dist/${target}';`; + break; + default: + throw new Error(`Unknown suffix: ${suffix} for target ${target}`); } const dirname = path.dirname(new URL(import.meta.url).pathname); - const content = fs.readFileSync(path.join(dirname, '..', 'dist', target), 'utf-8'); - if (suffix === 'd.ts') { - return content + const content = fs.readFileSync( + path.join(dirname, "..", "dist", target), + "utf-8" + ); + if (suffix === "d.ts") { + return content; } - const deprecation = "\x1b[33m" + deprecationMessage(originalImport, newImport) + "\x1b[0m"; + const deprecation = + "\x1b[33m" + deprecationMessage(originalImport, newImport) + "\x1b[0m"; return `console.warn(\`${deprecation}\`);\n\n${content}`; -} +}; const main = () => { const targets = [ @@ -68,13 +74,13 @@ const main = () => { "node.cjs.js", "node.d.ts", "node.esm.js", - ] + ]; const options = parseArgs(); if (!options.dist || !options.pkg) { - throw new Error('--dist=path and --pkg=name is required'); + throw new Error("--dist=path and --pkg=name is required"); } - const { dist, pkg } = options + const { dist, pkg } = options; for (const target of targets) { const shimmed = shimContent(target, pkg); @@ -82,6 +88,6 @@ const main = () => { fs.mkdirSync(path.dirname(distPath), { recursive: true }); fs.writeFileSync(distPath, shimmed); } -} +}; main(); diff --git a/tasks/packaging.rake b/tasks/packaging.rake index edb949bde..f7fad2afe 100644 --- a/tasks/packaging.rake +++ b/tasks/packaging.rake @@ -52,7 +52,8 @@ namespace :npm do package = JSON.parse(File.read(pkg_json)) (package["dependencies"] || []).each do |dep, _| next unless new_pkgs[dep] - sh *["npm", "pkg", "set", "dependencies.#{dep}=#{new_pkgs[dep]}"], chdir: pkg_dir + sh *["npm", "pkg", "set", "dependencies.#{dep}=#{new_pkgs[dep]}"], + chdir: pkg_dir end end end From 05714f6ac46bbca8f0b440a7b76f68cdcbea7d20 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sun, 21 May 2023 22:35:01 +0000 Subject: [PATCH 10/10] Run stree formattter in CI lint job --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 334cda4d2..747cc5290 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,9 +30,11 @@ jobs: with: fetch-depth: 0 - run: sudo apt-get install clang-format + - uses: ruby/setup-ruby@v1 + - run: ./bin/setup - run: ./tools/clang-format-diff.sh - run: rake check:bindgen - - run: git diff --exit-code + - run: git diff --exit-code || (echo "Please run \`rake format\` and commit the changes" && exit 1) build-builder-image: strategy: