Skip to content

Commit e9c306e

Browse files
Merge pull request #27 from ruby/pr-b04fc4ce8c73d0790e5c40b952b1d3c83a9001ea
Add JS::Object#typeof method to test object type
2 parents 176a0b0 + ded8983 commit e9c306e

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

ext/js/bindgen/rb-js-abi-host.wit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ js-value-to-string: function(value: js-abi-value) -> string
1414
export-js-value-to-host: function(value: js-abi-value)
1515
import-js-value-from-host: function() -> js-abi-value
1616

17+
js-value-typeof: function(value: js-abi-value) -> string
18+
1719
reflect-apply: function(target: js-abi-value, this-argument: js-abi-value, arguments: list<js-abi-value>) -> js-abi-value
1820
reflect-construct: function(target: js-abi-value, arguments: list<js-abi-value>) -> js-abi-value
1921
reflect-delete-property: function(target: js-abi-value, property-key: string) -> bool

ext/js/js-core.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,25 @@ static VALUE _rb_js_obj_call(int argc, VALUE *argv, VALUE obj) {
218218
rb_js_abi_host_reflect_apply(abi_method->abi, p->abi, &abi_args));
219219
}
220220

221+
/*
222+
* call-seq:
223+
* js_value.typeof -> String
224+
*
225+
* Returns the result string of JavaScript 'typeof' operator.
226+
* See also JS.is_a? for 'instanceof' operator.
227+
* p JS.global.typeof # => "object"
228+
* p JS.eval("return 1").typeof # => "number"
229+
* p JS.eval("return 'str'").typeof # => "string"
230+
* p JS.eval("return undefined").typeof # => "undefined"
231+
* p JS.eval("return null").typeof # => "object"
232+
*/
233+
static VALUE _rb_js_obj_typeof(VALUE obj) {
234+
struct jsvalue *p = check_jsvalue(obj);
235+
rb_js_abi_host_string_t ret0;
236+
rb_js_abi_host_js_value_typeof(p->abi, &ret0);
237+
return rb_str_new(ret0.ptr, ret0.len);
238+
}
239+
221240
/*
222241
* call-seq:
223242
* inspect -> string
@@ -319,6 +338,7 @@ void Init_js() {
319338
rb_define_method(rb_cJS_Object, "[]", _rb_js_obj_aref, 1);
320339
rb_define_method(rb_cJS_Object, "[]=", _rb_js_obj_aset, 2);
321340
rb_define_method(rb_cJS_Object, "call", _rb_js_obj_call, -1);
341+
rb_define_method(rb_cJS_Object, "typeof", _rb_js_obj_typeof, 0);
322342
rb_define_method(rb_cJS_Object, "__export_to_js", _rb_js_export_to_js, 0);
323343
rb_define_singleton_method(rb_cJS_Object, "__import_from_js", _rb_js_import_from_js, 0);
324344
rb_define_method(rb_cJS_Object, "inspect", _rb_js_obj_inspect, 0);

packages/npm-packages/ruby-wasm-wasi/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ export class RubyVM {
120120
return false;
121121
}
122122
},
123+
jsValueTypeof(value) {
124+
return typeof value;
125+
},
123126
reflectApply: function (target, thisArgument, args) {
124127
return Reflect.apply(target as any, thisArgument, args);
125128
},

packages/npm-packages/ruby-wasm-wasi/test/js_from_rb.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ describe("Manipulation of JS from Ruby", () => {
2424
expect(vm.eval(code).toString()).toBe(String(props.result));
2525
});
2626

27+
test.each([
28+
{ object: `JS.eval('return 1')`, result: "number" },
29+
{ object: `JS.eval('return "x"')`, result: "string" },
30+
{ object: `JS.eval('return null')`, result: "object" },
31+
{ object: `JS.eval('return undefined')`, result: "undefined" },
32+
{ object: `JS.global`, result: "object" },
33+
])("JS::Object#typeof (%s)", async (props) => {
34+
const vm = await initRubyVM();
35+
const code = `require "js"; (${props.object}).typeof`;
36+
expect(vm.eval(code).toString()).toBe(String(props.result));
37+
});
38+
2739
test.each([
2840
{ expr: "JS.global[:Object]", result: Object },
2941
{ expr: "JS.global[:Object][:keys]", result: Object.keys },

0 commit comments

Comments
 (0)