feat: 支持内建函数调用并修复初始化与绑定问题
This commit is contained in:
@@ -75,6 +75,12 @@ pub struct NumberMethods {
|
|||||||
pub to_fixed: *const (),
|
pub to_fixed: *const (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FunctionMethods {
|
||||||
|
pub call: *const (),
|
||||||
|
pub apply: *const (),
|
||||||
|
pub bind: *const (),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BuiltinWorld {
|
pub struct BuiltinWorld {
|
||||||
pub object_proto: P<JsObject>,
|
pub object_proto: P<JsObject>,
|
||||||
pub array_proto: P<JsObject>,
|
pub array_proto: P<JsObject>,
|
||||||
@@ -136,6 +142,10 @@ fn make_pair(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinWorld {
|
impl BuiltinWorld {
|
||||||
|
fn fn_proto_val(&self) -> JsValue {
|
||||||
|
JsValue::from_js_object(self.function_proto.as_ptr() as *mut JsObject)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(string_forge: &StringForge, shape_forge: &ShapeForge) -> Self {
|
pub fn new(string_forge: &StringForge, shape_forge: &ShapeForge) -> Self {
|
||||||
let si_prototype = intern_label(string_forge, "prototype");
|
let si_prototype = intern_label(string_forge, "prototype");
|
||||||
let si_constructor = intern_label(string_forge, "constructor");
|
let si_constructor = intern_label(string_forge, "constructor");
|
||||||
@@ -219,6 +229,24 @@ impl BuiltinWorld {
|
|||||||
|
|
||||||
let math_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
let math_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||||
|
|
||||||
|
fn wire_ctor_proto(ctor: &P<JsObject>, proto: &P<JsObject>) {
|
||||||
|
let ctor_ptr = ctor.as_ptr() as *mut JsObject;
|
||||||
|
let ctor = unsafe { &mut *ctor_ptr };
|
||||||
|
ctor.set_inline_prop(0, JsValue::from_js_object(proto.as_ptr() as *mut JsObject));
|
||||||
|
let proto_ptr = proto.as_ptr() as *mut JsObject;
|
||||||
|
let proto = unsafe { &mut *proto_ptr };
|
||||||
|
proto.set_inline_prop(0, JsValue::from_js_object(ctor_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
wire_ctor_proto(&object_constructor, &object_proto);
|
||||||
|
wire_ctor_proto(&array_constructor, &array_proto);
|
||||||
|
wire_ctor_proto(&function_constructor, &function_proto);
|
||||||
|
wire_ctor_proto(&string_constructor, &string_proto);
|
||||||
|
wire_ctor_proto(&number_constructor, &number_proto);
|
||||||
|
wire_ctor_proto(&boolean_constructor, &boolean_proto);
|
||||||
|
wire_ctor_proto(&error_constructor, &error_proto);
|
||||||
|
wire_ctor_proto(&symbol_constructor, &symbol_proto);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
object_proto,
|
object_proto,
|
||||||
array_proto,
|
array_proto,
|
||||||
@@ -255,10 +283,10 @@ impl BuiltinWorld {
|
|||||||
let ctor_ptr = P::as_ptr(&self.object_constructor) as *mut JsObject;
|
let ctor_ptr = P::as_ptr(&self.object_constructor) as *mut JsObject;
|
||||||
let ctor = unsafe { &mut *ctor_ptr };
|
let ctor = unsafe { &mut *ctor_ptr };
|
||||||
|
|
||||||
let _ = Self::bind_method(ctor, shape_forge, string_forge, "keys", methods.keys, 1);
|
let _ = self.bind_method(ctor, shape_forge, string_forge, "keys", methods.keys, 1);
|
||||||
let _ = Self::bind_method(ctor, shape_forge, string_forge, "create", methods.create, 2);
|
let _ = self.bind_method(ctor, shape_forge, string_forge, "create", methods.create, 2);
|
||||||
let _ = Self::bind_method(ctor, shape_forge, string_forge, "assign", methods.assign, 2);
|
let _ = self.bind_method(ctor, shape_forge, string_forge, "assign", methods.assign, 2);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -266,7 +294,7 @@ impl BuiltinWorld {
|
|||||||
methods.define_property,
|
methods.define_property,
|
||||||
3,
|
3,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -285,10 +313,10 @@ impl BuiltinWorld {
|
|||||||
let proto_ptr = P::as_ptr(&self.array_proto) as *mut JsObject;
|
let proto_ptr = P::as_ptr(&self.array_proto) as *mut JsObject;
|
||||||
let proto = unsafe { &mut *proto_ptr };
|
let proto = unsafe { &mut *proto_ptr };
|
||||||
|
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "push", methods.push, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "push", methods.push, 1);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "pop", methods.pop, 0);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "pop", methods.pop, 0);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "slice", methods.slice, 2);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "slice", methods.slice, 2);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -296,7 +324,7 @@ impl BuiltinWorld {
|
|||||||
methods.splice,
|
methods.splice,
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -304,8 +332,8 @@ impl BuiltinWorld {
|
|||||||
methods.concat,
|
methods.concat,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "join", methods.join, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "join", methods.join, 1);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -313,7 +341,7 @@ impl BuiltinWorld {
|
|||||||
methods.index_of,
|
methods.index_of,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -321,7 +349,7 @@ impl BuiltinWorld {
|
|||||||
methods.includes,
|
methods.includes,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -329,7 +357,7 @@ impl BuiltinWorld {
|
|||||||
methods.reverse,
|
methods.reverse,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -337,8 +365,8 @@ impl BuiltinWorld {
|
|||||||
methods.for_each,
|
methods.for_each,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "map", methods.map, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "map", methods.map, 1);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -346,7 +374,7 @@ impl BuiltinWorld {
|
|||||||
methods.filter,
|
methods.filter,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -354,11 +382,11 @@ impl BuiltinWorld {
|
|||||||
methods.reduce,
|
methods.reduce,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "find", methods.find, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "find", methods.find, 1);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "some", methods.some, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "some", methods.some, 1);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "every", methods.every, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "every", methods.every, 1);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "flat", methods.flat, 0);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "flat", methods.flat, 0);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -377,8 +405,8 @@ impl BuiltinWorld {
|
|||||||
let ctor_ptr = P::as_ptr(&self.error_constructor) as *mut JsObject;
|
let ctor_ptr = P::as_ptr(&self.error_constructor) as *mut JsObject;
|
||||||
let ctor = unsafe { &mut *ctor_ptr };
|
let ctor = unsafe { &mut *ctor_ptr };
|
||||||
|
|
||||||
let _ = Self::bind_method(ctor, shape_forge, string_forge, "Error", methods.error, 1);
|
let _ = self.bind_method(ctor, shape_forge, string_forge, "Error", methods.error, 1);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -386,7 +414,7 @@ impl BuiltinWorld {
|
|||||||
methods.type_error,
|
methods.type_error,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -394,7 +422,7 @@ impl BuiltinWorld {
|
|||||||
methods.reference_error,
|
methods.reference_error,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -402,7 +430,7 @@ impl BuiltinWorld {
|
|||||||
methods.range_error,
|
methods.range_error,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -410,7 +438,7 @@ impl BuiltinWorld {
|
|||||||
methods.syntax_error,
|
methods.syntax_error,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -418,7 +446,7 @@ impl BuiltinWorld {
|
|||||||
methods.uri_error,
|
methods.uri_error,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -437,7 +465,7 @@ impl BuiltinWorld {
|
|||||||
let proto_ptr = P::as_ptr(&self.string_proto) as *mut JsObject;
|
let proto_ptr = P::as_ptr(&self.string_proto) as *mut JsObject;
|
||||||
let proto = unsafe { &mut *proto_ptr };
|
let proto = unsafe { &mut *proto_ptr };
|
||||||
|
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -445,7 +473,7 @@ impl BuiltinWorld {
|
|||||||
methods.index_of,
|
methods.index_of,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -453,7 +481,7 @@ impl BuiltinWorld {
|
|||||||
methods.includes,
|
methods.includes,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -461,7 +489,7 @@ impl BuiltinWorld {
|
|||||||
methods.char_at,
|
methods.char_at,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -469,7 +497,7 @@ impl BuiltinWorld {
|
|||||||
methods.char_code_at,
|
methods.char_code_at,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -477,8 +505,8 @@ impl BuiltinWorld {
|
|||||||
methods.concat,
|
methods.concat,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "slice", methods.slice, 2);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "slice", methods.slice, 2);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -486,7 +514,7 @@ impl BuiltinWorld {
|
|||||||
methods.substring,
|
methods.substring,
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -494,7 +522,7 @@ impl BuiltinWorld {
|
|||||||
methods.to_upper_case,
|
methods.to_upper_case,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -502,8 +530,8 @@ impl BuiltinWorld {
|
|||||||
methods.to_lower_case,
|
methods.to_lower_case,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "trim", methods.trim, 0);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "trim", methods.trim, 0);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -511,7 +539,7 @@ impl BuiltinWorld {
|
|||||||
methods.repeat,
|
methods.repeat,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -519,7 +547,7 @@ impl BuiltinWorld {
|
|||||||
methods.pad_start,
|
methods.pad_start,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -527,7 +555,7 @@ impl BuiltinWorld {
|
|||||||
methods.pad_end,
|
methods.pad_end,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -535,7 +563,7 @@ impl BuiltinWorld {
|
|||||||
methods.starts_with,
|
methods.starts_with,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -543,8 +571,8 @@ impl BuiltinWorld {
|
|||||||
methods.ends_with,
|
methods.ends_with,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(proto, shape_forge, string_forge, "split", methods.split, 1);
|
let _ = self.bind_method(proto, shape_forge, string_forge, "split", methods.split, 1);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -552,7 +580,7 @@ impl BuiltinWorld {
|
|||||||
methods.replace,
|
methods.replace,
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -560,7 +588,7 @@ impl BuiltinWorld {
|
|||||||
methods.match_fn,
|
methods.match_fn,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -581,8 +609,8 @@ impl BuiltinWorld {
|
|||||||
let proto_ptr = P::as_ptr(&self.number_proto) as *mut JsObject;
|
let proto_ptr = P::as_ptr(&self.number_proto) as *mut JsObject;
|
||||||
let proto = unsafe { &mut *proto_ptr };
|
let proto = unsafe { &mut *proto_ptr };
|
||||||
|
|
||||||
let _ = Self::bind_method(ctor, shape_forge, string_forge, "isNaN", methods.is_nan, 1);
|
let _ = self.bind_method(ctor, shape_forge, string_forge, "isNaN", methods.is_nan, 1);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -590,7 +618,7 @@ impl BuiltinWorld {
|
|||||||
methods.is_finite,
|
methods.is_finite,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -598,7 +626,7 @@ impl BuiltinWorld {
|
|||||||
methods.parse_int,
|
methods.parse_int,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
ctor,
|
ctor,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -607,7 +635,7 @@ impl BuiltinWorld {
|
|||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -615,7 +643,7 @@ impl BuiltinWorld {
|
|||||||
methods.to_string,
|
methods.to_string,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let _ = Self::bind_method(
|
let _ = self.bind_method(
|
||||||
proto,
|
proto,
|
||||||
shape_forge,
|
shape_forge,
|
||||||
string_forge,
|
string_forge,
|
||||||
@@ -625,16 +653,84 @@ impl BuiltinWorld {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bind_function_methods(
|
||||||
|
&self,
|
||||||
|
methods: &FunctionMethods,
|
||||||
|
string_forge: &StringForge,
|
||||||
|
shape_forge: &ShapeForge,
|
||||||
|
) {
|
||||||
|
let proto_ptr = P::as_ptr(&self.function_proto) as *mut JsObject;
|
||||||
|
let proto = unsafe { &mut *proto_ptr };
|
||||||
|
let fp = self.fn_proto_val();
|
||||||
|
|
||||||
|
let _ = Self::bind_method_static(
|
||||||
|
proto,
|
||||||
|
shape_forge,
|
||||||
|
string_forge,
|
||||||
|
"call",
|
||||||
|
methods.call,
|
||||||
|
1,
|
||||||
|
fp,
|
||||||
|
);
|
||||||
|
let _ = Self::bind_method_static(
|
||||||
|
proto,
|
||||||
|
shape_forge,
|
||||||
|
string_forge,
|
||||||
|
"apply",
|
||||||
|
methods.apply,
|
||||||
|
2,
|
||||||
|
fp,
|
||||||
|
);
|
||||||
|
let _ = Self::bind_method_static(
|
||||||
|
proto,
|
||||||
|
shape_forge,
|
||||||
|
string_forge,
|
||||||
|
"bind",
|
||||||
|
methods.bind,
|
||||||
|
1,
|
||||||
|
fp,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bind_method(
|
pub fn bind_method(
|
||||||
|
&self,
|
||||||
proto: &mut JsObject,
|
proto: &mut JsObject,
|
||||||
shape_forge: &ShapeForge,
|
shape_forge: &ShapeForge,
|
||||||
string_forge: &StringForge,
|
string_forge: &StringForge,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
native_fn_ptr: *const (),
|
native_fn_ptr: *const (),
|
||||||
arg_count: u8,
|
arg_count: u8,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
Self::bind_method_static(
|
||||||
|
proto,
|
||||||
|
shape_forge,
|
||||||
|
string_forge,
|
||||||
|
method_name,
|
||||||
|
native_fn_ptr,
|
||||||
|
arg_count,
|
||||||
|
self.fn_proto_val(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind_method_static(
|
||||||
|
proto: &mut JsObject,
|
||||||
|
shape_forge: &ShapeForge,
|
||||||
|
string_forge: &StringForge,
|
||||||
|
method_name: &str,
|
||||||
|
native_fn_ptr: *const (),
|
||||||
|
arg_count: u8,
|
||||||
|
wrapper_proto: JsValue,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let si = string_forge.intern(method_name).0;
|
let si = string_forge.intern(method_name).0;
|
||||||
|
let wrapper_proto_ptr = if wrapper_proto.is_object() {
|
||||||
|
wrapper_proto.as_js_object_ptr()
|
||||||
|
} else {
|
||||||
|
std::ptr::null_mut()
|
||||||
|
};
|
||||||
let mut wrapper = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
let mut wrapper = Box::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||||
|
if !wrapper_proto_ptr.is_null() {
|
||||||
|
wrapper.set_proto(wrapper_proto).ok();
|
||||||
|
}
|
||||||
wrapper.set_function(true);
|
wrapper.set_function(true);
|
||||||
wrapper.set_native_fn(Some(native_fn_ptr));
|
wrapper.set_native_fn(Some(native_fn_ptr));
|
||||||
wrapper.set_native_arg_count(arg_count);
|
wrapper.set_native_arg_count(arg_count);
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||||
|
use oxide_types::object::JsObject;
|
||||||
|
use oxide_types::value::JsValue;
|
||||||
|
|
||||||
|
use crate::native::{NativeFn, NativeResult};
|
||||||
|
use crate::vm::Vm;
|
||||||
|
|
||||||
|
fn invoke_target(
|
||||||
|
vm: &mut Vm,
|
||||||
|
target_val: JsValue,
|
||||||
|
this_val: JsValue,
|
||||||
|
arg_regs: &[u8],
|
||||||
|
) -> NativeResult {
|
||||||
|
if !target_val.is_object() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let tgt_ptr = target_val.as_js_object_ptr();
|
||||||
|
if tgt_ptr.is_null() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let tgt = unsafe { &*tgt_ptr };
|
||||||
|
if !tgt.is_function() || tgt.native_fn().is_none() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let func: NativeFn = unsafe { std::mem::transmute(tgt.native_fn().unwrap()) };
|
||||||
|
|
||||||
|
let base = 230u8;
|
||||||
|
let n = arg_regs.len();
|
||||||
|
let mut args_buf = [0u8; 64];
|
||||||
|
args_buf[0] = base;
|
||||||
|
vm.set_reg(base, this_val);
|
||||||
|
for (i, ®) in arg_regs.iter().enumerate().take(n.min(63)) {
|
||||||
|
vm.set_reg(base + 1 + i as u8, vm.reg(reg));
|
||||||
|
args_buf[i + 1] = base + 1 + i as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
func(vm, &args_buf[..n + 1])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind_dispatcher(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||||
|
let wrapper_val = vm.reg(254);
|
||||||
|
let wrapper = unsafe { &*wrapper_val.as_js_object_ptr() };
|
||||||
|
let bound_target = wrapper.get_prop(0);
|
||||||
|
let bound_this = wrapper.get_prop(1);
|
||||||
|
|
||||||
|
let n = args.len().saturating_sub(1);
|
||||||
|
let base = 230u8;
|
||||||
|
let mut args_buf = [0u8; 64];
|
||||||
|
args_buf[0] = base;
|
||||||
|
vm.set_reg(base, bound_this);
|
||||||
|
for (i, ®) in args.iter().skip(1).enumerate().take(n.min(63)) {
|
||||||
|
vm.set_reg(base + 1 + i as u8, vm.reg(reg));
|
||||||
|
args_buf[i + 1] = base + 1 + i as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bound_target.is_object() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let tgt_ptr = bound_target.as_js_object_ptr();
|
||||||
|
if tgt_ptr.is_null() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let tgt = unsafe { &*tgt_ptr };
|
||||||
|
if !tgt.is_function() || tgt.native_fn().is_none() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let func: NativeFn = unsafe { std::mem::transmute(tgt.native_fn().unwrap()) };
|
||||||
|
func(vm, &args_buf[..n + 1])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_call(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let target_val = vm.reg(args[0]);
|
||||||
|
let this_val = if args.len() > 1 {
|
||||||
|
vm.reg(args[1])
|
||||||
|
} else {
|
||||||
|
JsValue::undefined()
|
||||||
|
};
|
||||||
|
let arg_regs: Vec<u8> = args.iter().skip(2).copied().collect();
|
||||||
|
invoke_target(vm, target_val, this_val, &arg_regs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_apply(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let target_val = vm.reg(args[0]);
|
||||||
|
let this_val = if args.len() > 1 {
|
||||||
|
vm.reg(args[1])
|
||||||
|
} else {
|
||||||
|
JsValue::undefined()
|
||||||
|
};
|
||||||
|
|
||||||
|
let arg_regs: Vec<u8>;
|
||||||
|
if args.len() > 2 {
|
||||||
|
let arr_val = vm.reg(args[2]);
|
||||||
|
if arr_val.is_object() {
|
||||||
|
let arr_ptr = arr_val.as_js_object_ptr();
|
||||||
|
if !arr_ptr.is_null() {
|
||||||
|
let arr = unsafe { &*arr_ptr };
|
||||||
|
if arr.is_array() {
|
||||||
|
let n = arr.prop_count() as usize;
|
||||||
|
let base = 200u8;
|
||||||
|
arg_regs = (0..n).map(|i| base + i as u8).collect();
|
||||||
|
for i in 0..n {
|
||||||
|
vm.set_reg(base + i as u8, arr.get_prop(i as u8));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arg_regs = Vec::new();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arg_regs = Vec::new();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arg_regs = Vec::new();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arg_regs = Vec::new();
|
||||||
|
}
|
||||||
|
invoke_target(vm, target_val, this_val, &arg_regs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_bind(vm: &mut Vm, args: &[u8]) -> NativeResult {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let target_val = vm.reg(args[0]);
|
||||||
|
if !target_val.is_object() {
|
||||||
|
return Err(JsValue::undefined());
|
||||||
|
}
|
||||||
|
let bound_this = if args.len() > 1 {
|
||||||
|
vm.reg(args[1])
|
||||||
|
} else {
|
||||||
|
JsValue::undefined()
|
||||||
|
};
|
||||||
|
|
||||||
|
let wrapper = vm
|
||||||
|
.epoch()
|
||||||
|
.alloc(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||||
|
unsafe {
|
||||||
|
(*wrapper).set_function(true);
|
||||||
|
(*wrapper).set_native_fn(Some(bind_dispatcher as *const ()));
|
||||||
|
(*wrapper).set_native_arg_count(0);
|
||||||
|
(*wrapper).set_prop_count(2);
|
||||||
|
(*wrapper).set_inline_prop(0, target_val);
|
||||||
|
(*wrapper).set_inline_prop(1, bound_this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(JsValue::from_js_object(wrapper))
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod array;
|
pub mod array;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
pub mod function;
|
||||||
pub mod global;
|
pub mod global;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod number;
|
pub mod number;
|
||||||
|
|||||||
+43
-31
@@ -9,7 +9,7 @@ use oxide_compiler::opcode::{self, OpCode};
|
|||||||
use crate::coercion;
|
use crate::coercion;
|
||||||
use crate::native::NativeFn;
|
use crate::native::NativeFn;
|
||||||
use oxide_kernel::builtin::{
|
use oxide_kernel::builtin::{
|
||||||
ArrayMethods, ErrorMethods, NumberMethods, ObjectMethods, StringMethods,
|
ArrayMethods, ErrorMethods, FunctionMethods, NumberMethods, ObjectMethods, StringMethods,
|
||||||
};
|
};
|
||||||
use oxide_kernel::kernel::{KernelConfig, OxideKernel};
|
use oxide_kernel::kernel::{KernelConfig, OxideKernel};
|
||||||
use oxide_kernel::prop_forge::PropTemplate;
|
use oxide_kernel::prop_forge::PropTemplate;
|
||||||
@@ -206,7 +206,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
|
|
||||||
let pi_fn = crate::builtins::number::number_parse_int as *const ();
|
let pi_fn = crate::builtins::number::number_parse_int as *const ();
|
||||||
let pf_fn = crate::builtins::number::number_parse_float as *const ();
|
let pf_fn = crate::builtins::number::number_parse_float as *const ();
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
global,
|
global,
|
||||||
kernel.shape_forge().as_ref(),
|
kernel.shape_forge().as_ref(),
|
||||||
kernel.string_forge().as_ref(),
|
kernel.string_forge().as_ref(),
|
||||||
@@ -214,7 +214,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
pi_fn,
|
pi_fn,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
global,
|
global,
|
||||||
kernel.shape_forge().as_ref(),
|
kernel.shape_forge().as_ref(),
|
||||||
kernel.string_forge().as_ref(),
|
kernel.string_forge().as_ref(),
|
||||||
@@ -228,7 +228,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
let sf = kernel.string_forge().as_ref();
|
let sf = kernel.string_forge().as_ref();
|
||||||
let sh = kernel.shape_forge().as_ref();
|
let sh = kernel.shape_forge().as_ref();
|
||||||
|
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -236,7 +236,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_abs as *const (),
|
crate::builtins::math::math_abs as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -244,7 +244,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_acos as *const (),
|
crate::builtins::math::math_acos as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -252,7 +252,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_asin as *const (),
|
crate::builtins::math::math_asin as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -260,7 +260,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_atan as *const (),
|
crate::builtins::math::math_atan as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -268,7 +268,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_atan2 as *const (),
|
crate::builtins::math::math_atan2 as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -276,7 +276,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_cbrt as *const (),
|
crate::builtins::math::math_cbrt as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -284,7 +284,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_ceil as *const (),
|
crate::builtins::math::math_ceil as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -292,7 +292,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_cos as *const (),
|
crate::builtins::math::math_cos as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -300,7 +300,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_cosh as *const (),
|
crate::builtins::math::math_cosh as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -308,7 +308,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_exp as *const (),
|
crate::builtins::math::math_exp as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -316,7 +316,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_floor as *const (),
|
crate::builtins::math::math_floor as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -324,7 +324,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_hypot as *const (),
|
crate::builtins::math::math_hypot as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -332,7 +332,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_imul as *const (),
|
crate::builtins::math::math_imul as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -340,7 +340,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_log as *const (),
|
crate::builtins::math::math_log as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -348,7 +348,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_log10 as *const (),
|
crate::builtins::math::math_log10 as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -356,7 +356,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_log2 as *const (),
|
crate::builtins::math::math_log2 as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -364,7 +364,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_max as *const (),
|
crate::builtins::math::math_max as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -372,7 +372,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_min as *const (),
|
crate::builtins::math::math_min as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -380,7 +380,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_pow as *const (),
|
crate::builtins::math::math_pow as *const (),
|
||||||
2,
|
2,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -388,7 +388,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_random as *const (),
|
crate::builtins::math::math_random as *const (),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -396,7 +396,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_round as *const (),
|
crate::builtins::math::math_round as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -404,7 +404,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_sign as *const (),
|
crate::builtins::math::math_sign as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -412,7 +412,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_sin as *const (),
|
crate::builtins::math::math_sin as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -420,7 +420,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_sinh as *const (),
|
crate::builtins::math::math_sinh as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -428,7 +428,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_sqrt as *const (),
|
crate::builtins::math::math_sqrt as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -436,7 +436,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_tan as *const (),
|
crate::builtins::math::math_tan as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -444,7 +444,7 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
crate::builtins::math::math_tanh as *const (),
|
crate::builtins::math::math_tanh as *const (),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
let _ = oxide_kernel::builtin::BuiltinWorld::bind_method(
|
let _ = kernel.builtin_world().bind_method(
|
||||||
math,
|
math,
|
||||||
sh,
|
sh,
|
||||||
sf,
|
sf,
|
||||||
@@ -472,6 +472,17 @@ pub fn init_kernel_builtins(kernel: &Arc<OxideKernel>) {
|
|||||||
global.set_prop_count(cur_count + 1);
|
global.set_prop_count(cur_count + 1);
|
||||||
global.set_prop_expand_heap(cur_count, m_val);
|
global.set_prop_expand_heap(cur_count, m_val);
|
||||||
global.bump_generation();
|
global.bump_generation();
|
||||||
|
|
||||||
|
let function_methods = FunctionMethods {
|
||||||
|
call: crate::builtins::function::function_call as *const (),
|
||||||
|
apply: crate::builtins::function::function_apply as *const (),
|
||||||
|
bind: crate::builtins::function::function_bind as *const (),
|
||||||
|
};
|
||||||
|
kernel.builtin_world().bind_function_methods(
|
||||||
|
&function_methods,
|
||||||
|
kernel.string_forge().as_ref(),
|
||||||
|
kernel.shape_forge().as_ref(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
@@ -887,6 +898,7 @@ impl Vm {
|
|||||||
|
|
||||||
let func: NativeFn =
|
let func: NativeFn =
|
||||||
unsafe { std::mem::transmute(obj.native_fn().unwrap()) };
|
unsafe { std::mem::transmute(obj.native_fn().unwrap()) };
|
||||||
|
self.regs[254] = callee;
|
||||||
match func(self, args_slice) {
|
match func(self, args_slice) {
|
||||||
Ok(val) => self.regs[0] = val,
|
Ok(val) => self.regs[0] = val,
|
||||||
Err(err_val) => {
|
Err(err_val) => {
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
use oxide_compiler::compiler::Compiler;
|
||||||
|
use oxide_types::value::JsValue;
|
||||||
|
use oxide_vm::vm::Vm;
|
||||||
|
|
||||||
|
fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
|
||||||
|
let allocator = oxide_parser::Allocator::default();
|
||||||
|
let program =
|
||||||
|
oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
|
||||||
|
let module = Compiler::new()
|
||||||
|
.compile(&program)
|
||||||
|
.map_err(|e| format!("Compile error: {}", e))?;
|
||||||
|
vm.run(&module)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_call_changes_this() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "Math.max.call(null, 10, 5)").unwrap();
|
||||||
|
assert!((result.as_double() - 10.0).abs() < 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_apply_changes_this() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "Math.max.apply(null, [10, 5])").unwrap();
|
||||||
|
assert!((result.as_double() - 10.0).abs() < 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_bind_creates_wrapper() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(&mut vm, "var b = Math.max.bind(null, 1); b(5)").unwrap();
|
||||||
|
assert!((result.as_double() - 5.0).abs() < 0.0001);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user