From 82b38fd4c862c55dc2e76e9ea68502036790e789 Mon Sep 17 00:00:00 2001 From: ledsun Date: Sun, 23 Jul 2023 19:52:23 +0900 Subject: [PATCH] Implement the JS::Object#to_b method. We can treat the return value of a JavaScript function as a condition for a Ruby if expression as follows:. `if searchParams.has('phrase').to_b`. --- ext/js/bindgen/rb-js-abi-host.c | 6 ++++++ ext/js/bindgen/rb-js-abi-host.h | 1 + ext/js/bindgen/rb-js-abi-host.wit | 2 ++ ext/js/js-core.c | 12 ++++++++++++ .../ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts | 1 + .../ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js | 4 ++++ packages/npm-packages/ruby-wasm-wasi/src/index.ts | 3 +++ .../ruby-wasm-wasi/test/unit/test_object.rb | 10 ++++++++++ 8 files changed, 39 insertions(+) diff --git a/ext/js/bindgen/rb-js-abi-host.c b/ext/js/bindgen/rb-js-abi-host.c index 44c3745bb3..7e0e1e08e3 100644 --- a/ext/js/bindgen/rb-js-abi-host.c +++ b/ext/js/bindgen/rb-js-abi-host.c @@ -151,6 +151,12 @@ rb_js_abi_host_js_abi_value_t rb_js_abi_host_rb_object_to_js_rb_value(uint32_t r 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 }; } +__attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-bool: func(value: handle) -> bool"))) +int32_t __wasm_import_rb_js_abi_host_js_value_to_bool(int32_t); +bool rb_js_abi_host_js_value_to_bool(rb_js_abi_host_js_abi_value_t value) { + int32_t ret = __wasm_import_rb_js_abi_host_js_value_to_bool((value).idx); + return ret; +} __attribute__((import_module("rb-js-abi-host"), import_name("js-value-to-string: func(value: handle) -> 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) { diff --git a/ext/js/bindgen/rb-js-abi-host.h b/ext/js/bindgen/rb-js-abi-host.h index 25ba556d00..44dfd0dad5 100644 --- a/ext/js/bindgen/rb-js-abi-host.h +++ b/ext/js/bindgen/rb-js-abi-host.h @@ -57,6 +57,7 @@ extern "C" rb_js_abi_host_js_abi_value_t rb_js_abi_host_bool_to_js_bool(bool value); rb_js_abi_host_js_abi_value_t rb_js_abi_host_proc_to_js_function(uint32_t value); rb_js_abi_host_js_abi_value_t rb_js_abi_host_rb_object_to_js_rb_value(uint32_t raw_rb_abi_value); + bool rb_js_abi_host_js_value_to_bool(rb_js_abi_host_js_abi_value_t value); 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); 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); void rb_js_abi_host_export_js_value_to_host(rb_js_abi_host_js_abi_value_t value); diff --git a/ext/js/bindgen/rb-js-abi-host.wit b/ext/js/bindgen/rb-js-abi-host.wit index 8d8a116ec7..7c807f382e 100644 --- a/ext/js/bindgen/rb-js-abi-host.wit +++ b/ext/js/bindgen/rb-js-abi-host.wit @@ -16,6 +16,8 @@ bool-to-js-bool: func(value: bool) -> js-abi-value proc-to-js-function: func(value: u32) -> js-abi-value rb-object-to-js-rb-value: func(raw-rb-abi-value: u32) -> js-abi-value +js-value-to-bool: func(value: js-abi-value) -> bool + js-value-to-string: func(value: js-abi-value) -> string variant raw-integer { diff --git a/ext/js/js-core.c b/ext/js/js-core.c index fa1e0308c8..fada1bfa4a 100644 --- a/ext/js/js-core.c +++ b/ext/js/js-core.c @@ -324,6 +324,17 @@ static VALUE _rb_js_obj_typeof(VALUE obj) { return rb_str_new(ret0.ptr, ret0.len); } +/* + * call-seq: + * to_b -> boolean + * + */ +static VALUE _rb_js_obj_to_b(VALUE obj) { + struct jsvalue *p = check_jsvalue(obj); + bool ret0 = rb_js_abi_host_js_value_to_bool(p->abi); + return RBOOL(ret0); +} + /* * call-seq: * to_s -> string @@ -560,6 +571,7 @@ void Init_js() { 0); rb_define_private_method(rb_cJS_singleton, "__import_from_js", _rb_js_import_from_js, 0); + rb_define_method(rb_cJS_Object, "to_b", _rb_js_obj_to_b, 0); rb_define_method(rb_cJS_Object, "to_s", _rb_js_obj_to_s, 0); rb_define_alias(rb_cJS_Object, "inspect", "to_s"); rb_define_method(rb_cJS_Object, "to_i", _rb_js_obj_to_i, 0); 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 f914c0e9e8..931795303d 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 @@ -28,6 +28,7 @@ export interface RbJsAbiHost { boolToJsBool(value: boolean): JsAbiValue; procToJsFunction(value: number): JsAbiValue; rbObjectToJsRbValue(rawRbAbiValue: number): JsAbiValue; + jsValueToBool(value: JsAbiValue): boolean; jsValueToString(value: JsAbiValue): string; jsValueToInteger(value: JsAbiValue): RawInteger; exportJsValueToHost(value: JsAbiValue): void; 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 02aa2fb469..79d6d45a93 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 @@ -66,6 +66,10 @@ export function addRbJsAbiHostToImports(imports, obj, get_export) { const ret0 = obj.rbObjectToJsRbValue(arg0 >>> 0); return resources0.insert(ret0); }; + imports["rb-js-abi-host"]["js-value-to-bool: func(value: handle) -> bool"] = function(arg0) { + const ret0 = obj.jsValueToBool(resources0.get(arg0)); + return ret0 ? 1 : 0; + }; imports["rb-js-abi-host"]["js-value-to-string: func(value: handle) -> string"] = function(arg0, arg1) { const memory = get_export("memory"); const realloc = get_export("cabi_realloc"); diff --git a/packages/npm-packages/ruby-wasm-wasi/src/index.ts b/packages/npm-packages/ruby-wasm-wasi/src/index.ts index dbbb2e9aa0..07ecfb41be 100644 --- a/packages/npm-packages/ruby-wasm-wasi/src/index.ts +++ b/packages/npm-packages/ruby-wasm-wasi/src/index.ts @@ -213,6 +213,9 @@ export class RubyVM { rbObjectToJsRbValue: (rawRbAbiValue) => { return this.rbValueOfPointer(rawRbAbiValue); }, + jsValueToBool: (value) => { + return Boolean(value); + }, 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. diff --git a/packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb b/packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb index c2587136c4..a57e72b9a5 100644 --- a/packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb +++ b/packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb @@ -56,6 +56,16 @@ def test_strictly_eql? JS.eval("return undefined;") end + def test_to_b + assert_true JS.eval("return true;").to_b + assert_false JS.eval("return false;").to_b + assert_false JS.eval("return 0;").to_b + assert_false JS.eval("return -0;").to_b + assert_false JS.eval("return NaN;").to_b + assert_false JS.eval("return null;").to_b + assert_false JS.eval("return undefined;").to_b + end + def test_to_s assert_equal "str", JS.eval("return 'str';").to_s assert_equal "24", JS.eval("return 24;").to_s