Skip to content

Commit 5d014a9

Browse files
Catch exceptions in getter/setter
1 parent 180c6d0 commit 5d014a9

File tree

8 files changed

+104
-26
lines changed

8 files changed

+104
-26
lines changed

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

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,27 @@ bool rb_js_abi_host_reflect_delete_property(rb_js_abi_host_js_abi_value_t target
244244
int32_t ret = __wasm_import_rb_js_abi_host_reflect_delete_property((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len);
245245
return ret;
246246
}
247-
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get: func(target: handle<js-abi-value>, property-key: string) -> handle<js-abi-value>")))
248-
int32_t __wasm_import_rb_js_abi_host_reflect_get(int32_t, int32_t, int32_t);
249-
rb_js_abi_host_js_abi_value_t rb_js_abi_host_reflect_get(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key) {
250-
int32_t ret = __wasm_import_rb_js_abi_host_reflect_get((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len);
251-
return (rb_js_abi_host_js_abi_value_t){ ret };
247+
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get: func(target: handle<js-abi-value>, property-key: string) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }")))
248+
void __wasm_import_rb_js_abi_host_reflect_get(int32_t, int32_t, int32_t, int32_t);
249+
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) {
250+
251+
__attribute__((aligned(4)))
252+
uint8_t ret_area[8];
253+
int32_t ptr = (int32_t) &ret_area;
254+
__wasm_import_rb_js_abi_host_reflect_get((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, ptr);
255+
rb_js_abi_host_js_abi_result_t variant;
256+
variant.tag = (int32_t) (*((uint8_t*) (ptr + 0)));
257+
switch ((int32_t) variant.tag) {
258+
case 0: {
259+
variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) };
260+
break;
261+
}
262+
case 1: {
263+
variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) };
264+
break;
265+
}
266+
}
267+
*ret0 = variant;
252268
}
253269
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-get-own-property-descriptor: func(target: handle<js-abi-value>, property-key: string) -> handle<js-abi-value>")))
254270
int32_t __wasm_import_rb_js_abi_host_reflect_get_own_property_descriptor(int32_t, int32_t, int32_t);
@@ -290,11 +306,27 @@ bool rb_js_abi_host_reflect_prevent_extensions(rb_js_abi_host_js_abi_value_t tar
290306
int32_t ret = __wasm_import_rb_js_abi_host_reflect_prevent_extensions((target).idx);
291307
return ret;
292308
}
293-
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set: func(target: handle<js-abi-value>, property-key: string, value: handle<js-abi-value>) -> bool")))
294-
int32_t __wasm_import_rb_js_abi_host_reflect_set(int32_t, int32_t, int32_t, int32_t);
295-
bool 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) {
296-
int32_t ret = __wasm_import_rb_js_abi_host_reflect_set((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, (value).idx);
297-
return ret;
309+
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set: func(target: handle<js-abi-value>, property-key: string, value: handle<js-abi-value>) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }")))
310+
void __wasm_import_rb_js_abi_host_reflect_set(int32_t, int32_t, int32_t, int32_t, int32_t);
311+
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) {
312+
313+
__attribute__((aligned(4)))
314+
uint8_t ret_area[8];
315+
int32_t ptr = (int32_t) &ret_area;
316+
__wasm_import_rb_js_abi_host_reflect_set((target).idx, (int32_t) (*property_key).ptr, (int32_t) (*property_key).len, (value).idx, ptr);
317+
rb_js_abi_host_js_abi_result_t variant;
318+
variant.tag = (int32_t) (*((uint8_t*) (ptr + 0)));
319+
switch ((int32_t) variant.tag) {
320+
case 0: {
321+
variant.val.success = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) };
322+
break;
323+
}
324+
case 1: {
325+
variant.val.failure = (rb_js_abi_host_js_abi_value_t){ *((int32_t*) (ptr + 4)) };
326+
break;
327+
}
328+
}
329+
*ret0 = variant;
298330
}
299331
__attribute__((import_module("rb-js-abi-host"), import_name("reflect-set-prototype-of: func(target: handle<js-abi-value>, prototype: handle<js-abi-value>) -> bool")))
300332
int32_t __wasm_import_rb_js_abi_host_reflect_set_prototype_of(int32_t, int32_t);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ extern "C"
6666
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);
6767
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);
6868
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);
69-
rb_js_abi_host_js_abi_value_t rb_js_abi_host_reflect_get(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key);
69+
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);
7070
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);
7171
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);
7272
bool rb_js_abi_host_reflect_has(rb_js_abi_host_js_abi_value_t target, rb_js_abi_host_string_t *property_key);
7373
bool rb_js_abi_host_reflect_is_extensible(rb_js_abi_host_js_abi_value_t target);
7474
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);
7575
bool rb_js_abi_host_reflect_prevent_extensions(rb_js_abi_host_js_abi_value_t target);
76-
bool 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);
76+
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);
7777
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);
7878
#ifdef __cplusplus
7979
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ js-value-strictly-equal: func(lhs: js-abi-value, rhs: js-abi-value) -> bool
3535
reflect-apply: func(target: js-abi-value, this-argument: js-abi-value, arguments: list<js-abi-value>) -> js-abi-result
3636
reflect-construct: func(target: js-abi-value, arguments: list<js-abi-value>) -> js-abi-value
3737
reflect-delete-property: func(target: js-abi-value, property-key: string) -> bool
38-
reflect-get: func(target: js-abi-value, property-key: string) -> js-abi-value
38+
reflect-get: func(target: js-abi-value, property-key: string) -> js-abi-result
3939
reflect-get-own-property-descriptor: func(target: js-abi-value, property-key: string) -> js-abi-value
4040
reflect-get-prototype-of: func(target: js-abi-value) -> js-abi-value
4141
reflect-has: func(target: js-abi-value, property-key: string) -> bool
4242
reflect-is-extensible: func(target: js-abi-value) -> bool
4343
reflect-own-keys: func(target: js-abi-value) -> list<js-abi-value>
4444
reflect-prevent-extensions: func(target: js-abi-value) -> bool
45-
reflect-set: func(target: js-abi-value, property-key: string, value: js-abi-value) -> bool
45+
reflect-set: func(target: js-abi-value, property-key: string, value: js-abi-value) -> js-abi-result
4646
reflect-set-prototype-of: func(target: js-abi-value, prototype: js-abi-value) -> bool

ext/js/js-core.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ static VALUE _rb_js_obj_aref(VALUE obj, VALUE key) {
180180
rb_js_abi_host_string_t key_abi_str;
181181
key = rb_obj_as_string(key);
182182
rstring_to_abi_string(key, &key_abi_str);
183-
return jsvalue_s_new(rb_js_abi_host_reflect_get(p->abi, &key_abi_str));
183+
rb_js_abi_host_js_abi_result_t ret;
184+
rb_js_abi_host_reflect_get(p->abi, &key_abi_str, &ret);
185+
raise_js_error_if_failure(&ret);
186+
return jsvalue_s_new(ret.val.success);
184187
}
185188

186189
/*
@@ -199,7 +202,10 @@ static VALUE _rb_js_obj_aset(VALUE obj, VALUE key, VALUE val) {
199202
rb_js_abi_host_string_t key_abi_str;
200203
key = rb_obj_as_string(key);
201204
rstring_to_abi_string(key, &key_abi_str);
202-
rb_js_abi_host_reflect_set(p->abi, &key_abi_str, v->abi);
205+
rb_js_abi_host_js_abi_result_t ret;
206+
rb_js_abi_host_reflect_set(p->abi, &key_abi_str, v->abi, &ret);
207+
raise_js_error_if_failure(&ret);
208+
rb_js_abi_host_js_abi_value_free(&ret.val.success);
203209
RB_GC_GUARD(rv);
204210
return val;
205211
}

packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ export interface RbJsAbiHost {
3737
reflectApply(target: JsAbiValue, thisArgument: JsAbiValue, arguments: JsAbiValue[]): JsAbiResult;
3838
reflectConstruct(target: JsAbiValue, arguments: JsAbiValue[]): JsAbiValue;
3939
reflectDeleteProperty(target: JsAbiValue, propertyKey: string): boolean;
40-
reflectGet(target: JsAbiValue, propertyKey: string): JsAbiValue;
40+
reflectGet(target: JsAbiValue, propertyKey: string): JsAbiResult;
4141
reflectGetOwnPropertyDescriptor(target: JsAbiValue, propertyKey: string): JsAbiValue;
4242
reflectGetPrototypeOf(target: JsAbiValue): JsAbiValue;
4343
reflectHas(target: JsAbiValue, propertyKey: string): boolean;
4444
reflectIsExtensible(target: JsAbiValue): boolean;
4545
reflectOwnKeys(target: JsAbiValue): JsAbiValue[];
4646
reflectPreventExtensions(target: JsAbiValue): boolean;
47-
reflectSet(target: JsAbiValue, propertyKey: string, value: JsAbiValue): boolean;
47+
reflectSet(target: JsAbiValue, propertyKey: string, value: JsAbiValue): JsAbiResult;
4848
reflectSetPrototypeOf(target: JsAbiValue, prototype: JsAbiValue): boolean;
4949
dropJsAbiValue?: (val: JsAbiValue) => void;
5050
}

packages/npm-packages/ruby-wasm-wasi/src/bindgen/rb-js-abi-host.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,29 @@ export function addRbJsAbiHostToImports(imports, obj, get_export) {
168168
const ret0 = obj.reflectDeleteProperty(resources0.get(arg0), result0);
169169
return ret0 ? 1 : 0;
170170
};
171-
imports["rb-js-abi-host"]["reflect-get: func(target: handle<js-abi-value>, property-key: string) -> handle<js-abi-value>"] = function(arg0, arg1, arg2) {
171+
imports["rb-js-abi-host"]["reflect-get: func(target: handle<js-abi-value>, property-key: string) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2, arg3) {
172172
const memory = get_export("memory");
173173
const ptr0 = arg1;
174174
const len0 = arg2;
175175
const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
176176
const ret0 = obj.reflectGet(resources0.get(arg0), result0);
177-
return resources0.insert(ret0);
177+
const variant1 = ret0;
178+
switch (variant1.tag) {
179+
case "success": {
180+
const e = variant1.val;
181+
data_view(memory).setInt8(arg3 + 0, 0, true);
182+
data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true);
183+
break;
184+
}
185+
case "failure": {
186+
const e = variant1.val;
187+
data_view(memory).setInt8(arg3 + 0, 1, true);
188+
data_view(memory).setInt32(arg3 + 4, resources0.insert(e), true);
189+
break;
190+
}
191+
default:
192+
throw new RangeError("invalid variant specified for JsAbiResult");
193+
}
178194
};
179195
imports["rb-js-abi-host"]["reflect-get-own-property-descriptor: func(target: handle<js-abi-value>, property-key: string) -> handle<js-abi-value>"] = function(arg0, arg1, arg2) {
180196
const memory = get_export("memory");
@@ -219,13 +235,29 @@ export function addRbJsAbiHostToImports(imports, obj, get_export) {
219235
const ret0 = obj.reflectPreventExtensions(resources0.get(arg0));
220236
return ret0 ? 1 : 0;
221237
};
222-
imports["rb-js-abi-host"]["reflect-set: func(target: handle<js-abi-value>, property-key: string, value: handle<js-abi-value>) -> bool"] = function(arg0, arg1, arg2, arg3) {
238+
imports["rb-js-abi-host"]["reflect-set: func(target: handle<js-abi-value>, property-key: string, value: handle<js-abi-value>) -> variant { success(handle<js-abi-value>), failure(handle<js-abi-value>) }"] = function(arg0, arg1, arg2, arg3, arg4) {
223239
const memory = get_export("memory");
224240
const ptr0 = arg1;
225241
const len0 = arg2;
226242
const result0 = UTF8_DECODER.decode(new Uint8Array(memory.buffer, ptr0, len0));
227243
const ret0 = obj.reflectSet(resources0.get(arg0), result0, resources0.get(arg3));
228-
return ret0 ? 1 : 0;
244+
const variant1 = ret0;
245+
switch (variant1.tag) {
246+
case "success": {
247+
const e = variant1.val;
248+
data_view(memory).setInt8(arg4 + 0, 0, true);
249+
data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
250+
break;
251+
}
252+
case "failure": {
253+
const e = variant1.val;
254+
data_view(memory).setInt8(arg4 + 0, 1, true);
255+
data_view(memory).setInt32(arg4 + 4, resources0.insert(e), true);
256+
break;
257+
}
258+
default:
259+
throw new RangeError("invalid variant specified for JsAbiResult");
260+
}
229261
};
230262
imports["rb-js-abi-host"]["reflect-set-prototype-of: func(target: handle<js-abi-value>, prototype: handle<js-abi-value>) -> bool"] = function(arg0, arg1) {
231263
const ret0 = obj.reflectSetPrototypeOf(resources0.get(arg0), resources0.get(arg1));

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ export class RubyVM {
162162
reflectDeleteProperty: function (target, propertyKey): boolean {
163163
throw new Error("Function not implemented.");
164164
},
165-
reflectGet: function (target, propertyKey) {
165+
reflectGet: wrapTry((target, propertyKey) => {
166166
return target[propertyKey];
167-
},
167+
}),
168168
reflectGetOwnPropertyDescriptor: function (
169169
target,
170170
propertyKey: string
@@ -186,9 +186,9 @@ export class RubyVM {
186186
reflectPreventExtensions: function (target): boolean {
187187
throw new Error("Function not implemented.");
188188
},
189-
reflectSet: function (target, propertyKey, value): boolean {
189+
reflectSet: wrapTry((target, propertyKey, value) => {
190190
return Reflect.set(target, propertyKey, value);
191-
},
191+
}),
192192
reflectSetPrototypeOf: function (target, prototype): boolean {
193193
throw new Error("Function not implemented.");
194194
},

packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ def test_member_get
202202
JS
203203
assert_equal 42.to_s, object[:foo].to_s
204204
assert_equal 42.to_s, object["foo"].to_s
205+
206+
assert_raise(JS::Error) do
207+
JS::Undefined[:foo]
208+
end
205209
end
206210

207211
def test_member_set
@@ -212,6 +216,10 @@ def test_member_set
212216
assert_equal 24.to_s, object[:foo].to_s
213217
object["foo"] = 42
214218
assert_equal 42.to_s, object["foo"].to_s
219+
220+
assert_raise(JS::Error) do
221+
JS::Undefined[:foo] = 42
222+
end
215223
end
216224

217225
def test_member_set_with_stress_gc

0 commit comments

Comments
 (0)