diff --git a/libs/jsruntime/src/builtins/builtin_mod.rs.hbs b/libs/jsruntime/src/builtins/builtin_mod.rs.hbs index a9b3d292f..b0d551649 100644 --- a/libs/jsruntime/src/builtins/builtin_mod.rs.hbs +++ b/libs/jsruntime/src/builtins/builtin_mod.rs.hbs @@ -32,19 +32,27 @@ impl Runtime { matches!(value, Value::Object(object) if self.is_{{metadata.id}}_object(*object)) } - /// Creates the {{metadata.class}} constructor. - pub(super) fn create_{{metadata.id}}_constructor(&mut self) -> HandleMut { - logger::debug!(event = "create_{{metadata.id}}_constructor"); + /// Initialize the {{metadata.class}} constructor. + pub(super) fn init_{{metadata.id}}_constructor(&mut self) { + logger::debug!(event = "init_{{metadata.id}}_constructor"); - #[allow(unused_mut)] - let mut constructor = self.create_builtin_function(&BuiltinFunctionParams { - lambda: constructor::, + let mut constructor = self.builtins.{{metadata.id}}_constructor; + + self.init_builtin_function(constructor, &BuiltinFunctionParams { + lambda: {{metadata.id}}_constructor::, name: const_string_handle!("{{metadata.class}}"), length: 1, slots: &[], - prototype: Some(self.builtins.{{metadata.id}}_prototype), }); + constructor.set_constructor(); + + let result = constructor.define_own_property( + Symbol::PROTOTYPE.into(), + Property::data_xxx(Value::Object(self.builtins.{{metadata.id}}_prototype)), + ); + debug_assert!(matches!(result, Ok(true))); + {{#each constructorProperties}} {{#if (eq kind "constructor.function")}} let func = self.create_builtin_function(&BuiltinFunctionParams { @@ -52,30 +60,27 @@ impl Runtime { name: const_string_handle!("{{name}}"), length: {{this.length}}, slots: &[], - prototype: None, }); - let result = constructor.define_own_property(Symbol::{{symbol}}.into(), Property::data_wxc(Value::Object(func))); + let result = constructor.define_own_property( + Symbol::{{symbol}}.into(), Property::data_wxc(Value::Object(func))); debug_assert!(matches!(result, Ok(true))); {{/if}} {{/each}} - // TODO(refactor): bind outside this function - let result = self.builtins.{{metadata.id}}_prototype.define_own_property(Symbol::CONSTRUCTOR.into(), Property::data_wxc(Value::Object(constructor))); - debug_assert!(matches!(result, Ok(true))); - - constructor } - /// Creates the {{metadata.class}} prototype object. + /// Initializes the {{metadata.class}} prototype object. pub(super) fn init_{{metadata.id}}_prototype(&mut self) { logger::debug!(event = "init_{{metadata.id}}_prototype"); - #[allow(unused)] let mut prototype = self.builtins.{{metadata.id}}_prototype; {{#if metadata.inherits}} prototype.set_prototype(self.builtins.{{metadata.inherits}}_prototype); {{/if}} + let result = prototype.define_own_property(Symbol::CONSTRUCTOR.into(), Property::data_wxc(Value::Object(self.builtins.{{metadata.id}}_constructor))); + debug_assert!(matches!(result, Ok(true))); + {{#each prototypeProperties}} {{#if (eq kind "prototype.property")}} imp::{{imp}}(self, prototype); @@ -86,7 +91,6 @@ impl Runtime { name: const_string_handle!("{{name}}"), length: {{this.length}}, slots: &[], - prototype: None, }); let result = prototype.define_own_property(Symbol::{{symbol}}.into(), Property::data_wxc(Value::Object(func))); debug_assert!(matches!(result, Ok(true))); @@ -97,9 +101,8 @@ impl Runtime { } // lambda functions -// TODO: use proc-macro -extern "C" fn constructor( +extern "C" fn {{metadata.id}}_constructor( runtime: &mut Runtime, context: &mut CallContext, retv: &mut Value, diff --git a/libs/jsruntime/src/builtins/function/imp.rs b/libs/jsruntime/src/builtins/function/imp.rs index 47b7a9fe4..eecb8fc2b 100644 --- a/libs/jsruntime/src/builtins/function/imp.rs +++ b/libs/jsruntime/src/builtins/function/imp.rs @@ -69,7 +69,7 @@ pub fn function_prototype_bind( let target = runtime.this_func(context.this())?; let this = context.arg(0); let args = &context.args()[1..]; - let mut bound_func = runtime.bound_function_create(target, this, args)?; + let bound_func = runtime.bound_function_create(target, this, args)?; let length = match target.get_own_property(&Symbol::LENGTH.into()) { Some(prop) => { let target_length = runtime.value_to_length(prop.value())?; @@ -82,12 +82,12 @@ pub fn function_prototype_bind( None => 0, }; debug_assert!(length <= u16::MAX as u64); - runtime.set_function_length(&mut bound_func, length as u16); + runtime.set_function_length(bound_func, length as u16); let target_name = target .get_value(&Symbol::NAME.into()) .unwrap_or(&Value::Undefined); if let Value::String(name) = target_name { - runtime.set_function_name(&mut bound_func, *name); + runtime.set_function_name(bound_func, *name); } Ok(Value::Object(bound_func)) } diff --git a/libs/jsruntime/src/builtins/global/imp.rs b/libs/jsruntime/src/builtins/global/imp.rs index 62a1c546c..65d6e796c 100644 --- a/libs/jsruntime/src/builtins/global/imp.rs +++ b/libs/jsruntime/src/builtins/global/imp.rs @@ -89,78 +89,78 @@ pub fn parse_int(runtime: &mut Runtime, context: &mut CallContext) -> Resu //#sec-constructor-properties-of-the-global-object-aggregate-error global.constructor pub fn define_aggregate_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_aggregate_error_constructor(); + let constructor = runtime.builtins.aggregate_error_constructor; runtime.define_constructor(Symbol::AGGREGATE_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-error global.constructor pub fn define_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_error_constructor(); + let constructor = runtime.builtins.error_constructor; runtime.define_constructor(Symbol::ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-evalerror global.constructor pub fn define_eval_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_eval_error_constructor(); + let constructor = runtime.builtins.eval_error_constructor; runtime.define_constructor(Symbol::EVAL_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-function global.constructor pub fn define_function_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_function_constructor(); + let constructor = runtime.builtins.function_constructor; runtime.define_constructor(Symbol::FUNCTION, constructor); } //#_internalerror global.constructor { "name": "InternalError" } pub fn define_internal_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_internal_error_constructor(); + let constructor = runtime.builtins.internal_error_constructor; runtime.define_constructor(Symbol::INTERNAL_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-object global.constructor pub fn define_object_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_object_constructor(); + let constructor = runtime.builtins.object_constructor; runtime.define_constructor(Symbol::OBJECT, constructor); } //#sec-constructor-properties-of-the-global-object-promise global.constructor pub fn define_promise_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_promise_constructor(); + let constructor = runtime.builtins.promise_constructor; runtime.define_constructor(Symbol::PROMISE, constructor); } //#sec-constructor-properties-of-the-global-object-rangeerror global.constructor pub fn define_range_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_range_error_constructor(); + let constructor = runtime.builtins.range_error_constructor; runtime.define_constructor(Symbol::RANGE_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-referenceerror global.constructor pub fn define_reference_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_reference_error_constructor(); + let constructor = runtime.builtins.reference_error_constructor; runtime.define_constructor(Symbol::REFERENCE_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-string global.constructor pub fn define_string_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_string_constructor(); + let constructor = runtime.builtins.string_constructor; runtime.define_constructor(Symbol::STRING, constructor); } //#sec-constructor-properties-of-the-global-object-syntaxerror global.constructor pub fn define_syntax_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_syntax_error_constructor(); + let constructor = runtime.builtins.syntax_error_constructor; runtime.define_constructor(Symbol::SYNTAX_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-typeerror global.constructor pub fn define_type_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_type_error_constructor(); + let constructor = runtime.builtins.type_error_constructor; runtime.define_constructor(Symbol::TYPE_ERROR, constructor); } //#sec-constructor-properties-of-the-global-object-urierror global.constructor pub fn define_uri_error_constructor(runtime: &mut Runtime) { - let constructor = runtime.create_uri_error_constructor(); + let constructor = runtime.builtins.uri_error_constructor; runtime.define_constructor(Symbol::URI_ERROR, constructor); } diff --git a/libs/jsruntime/src/builtins/global/mod.rs.hbs b/libs/jsruntime/src/builtins/global/mod.rs.hbs index 8e73db708..43e1d5fa5 100644 --- a/libs/jsruntime/src/builtins/global/mod.rs.hbs +++ b/libs/jsruntime/src/builtins/global/mod.rs.hbs @@ -38,7 +38,6 @@ impl Runtime { name: const_string_handle!("{{name}}"), length: {{this.length}}, slots: &[], - prototype: None, }); self.define_global_property(Symbol::{{symbol}}, Property::data_wxc(Value::Object(func))); @@ -57,7 +56,6 @@ impl Runtime { } // lambda functions -// TODO: use proc-macro {{#each globalProperties}} {{#if (eq kind "global.function")}} diff --git a/libs/jsruntime/src/builtins/mod.rs b/libs/jsruntime/src/builtins/mod.rs index 19ce83ef3..48f6eadc2 100644 --- a/libs/jsruntime/src/builtins/mod.rs +++ b/libs/jsruntime/src/builtins/mod.rs @@ -40,31 +40,57 @@ use crate::types::Value; pub(crate) struct Builtins { // [[GlobalObject]] pub(crate) global_object: HandleMut, + // %Object% + pub(crate) object_constructor: HandleMut, // %Object.prototype% pub(crate) object_prototype: HandleMut, + // %Function% + pub(crate) function_constructor: HandleMut, // %Function.prototype% pub(crate) function_prototype: HandleMut, + // %String% + pub(crate) string_constructor: HandleMut, // %String.prototype% pub(crate) string_prototype: HandleMut, + // %Promise% + pub(crate) promise_constructor: HandleMut, // %Promise.prototype% pub(crate) promise_prototype: HandleMut, + // %Error% + pub(crate) error_constructor: HandleMut, // %Error.prototype% pub(crate) error_prototype: HandleMut, + // %AggregateError% + pub(crate) aggregate_error_constructor: HandleMut, // %AggregateError.prototype% pub(crate) aggregate_error_prototype: HandleMut, + // %EvalError% + pub(crate) eval_error_constructor: HandleMut, // %EvalError.prototype% pub(crate) eval_error_prototype: HandleMut, + // %InternalError% + pub(crate) internal_error_constructor: HandleMut, // %InternalError.prototype% pub(crate) internal_error_prototype: HandleMut, + // %RangeError% + pub(crate) range_error_constructor: HandleMut, // %RangeError.prototype% pub(crate) range_error_prototype: HandleMut, + // %ReferenceError% + pub(crate) reference_error_constructor: HandleMut, // %ReferenceError.prototype% pub(crate) reference_error_prototype: HandleMut, + // %SyntaxError% + pub(crate) syntax_error_constructor: HandleMut, // %SyntaxError.prototype% pub(crate) syntax_error_prototype: HandleMut, + // %TypeError% + pub(crate) type_error_constructor: HandleMut, // %TypeError.prototype% pub(crate) type_error_prototype: HandleMut, - // URIError.prototype% + // %URIError% + pub(crate) uri_error_constructor: HandleMut, + // %URIError.prototype% pub(crate) uri_error_prototype: HandleMut, } @@ -73,18 +99,31 @@ impl Builtins { pub(crate) fn new(heap: &mut Heap) -> Self { Self { global_object: heap.alloc_mut(Object::new()), + object_constructor: heap.alloc_mut(Object::new()), object_prototype: heap.alloc_mut(Object::new()), + function_constructor: heap.alloc_mut(Object::new()), function_prototype: heap.alloc_mut(Object::new()), + string_constructor: heap.alloc_mut(Object::new()), string_prototype: heap.alloc_mut(Object::new()), + promise_constructor: heap.alloc_mut(Object::new()), promise_prototype: heap.alloc_mut(Object::new()), + error_constructor: heap.alloc_mut(Object::new()), error_prototype: heap.alloc_mut(Object::new()), + aggregate_error_constructor: heap.alloc_mut(Object::new()), aggregate_error_prototype: heap.alloc_mut(Object::new()), + eval_error_constructor: heap.alloc_mut(Object::new()), eval_error_prototype: heap.alloc_mut(Object::new()), + internal_error_constructor: heap.alloc_mut(Object::new()), internal_error_prototype: heap.alloc_mut(Object::new()), + reference_error_constructor: heap.alloc_mut(Object::new()), reference_error_prototype: heap.alloc_mut(Object::new()), + range_error_constructor: heap.alloc_mut(Object::new()), range_error_prototype: heap.alloc_mut(Object::new()), + syntax_error_constructor: heap.alloc_mut(Object::new()), syntax_error_prototype: heap.alloc_mut(Object::new()), + type_error_constructor: heap.alloc_mut(Object::new()), type_error_prototype: heap.alloc_mut(Object::new()), + uri_error_constructor: heap.alloc_mut(Object::new()), uri_error_prototype: heap.alloc_mut(Object::new()), } } @@ -98,18 +137,31 @@ impl Runtime { } fn init_intrinsic_objects(&mut self) { + self.init_object_constructor(); self.init_object_prototype(); + self.init_function_constructor(); self.init_function_prototype(); + self.init_string_constructor(); self.init_string_prototype(); + self.init_promise_constructor(); self.init_promise_prototype(); + self.init_error_constructor(); self.init_error_prototype(); + self.init_aggregate_error_constructor(); self.init_aggregate_error_prototype(); + self.init_eval_error_constructor(); self.init_eval_error_prototype(); + self.init_internal_error_constructor(); self.init_internal_error_prototype(); + self.init_range_error_constructor(); self.init_range_error_prototype(); + self.init_reference_error_constructor(); self.init_reference_error_prototype(); + self.init_syntax_error_constructor(); self.init_syntax_error_prototype(); + self.init_type_error_constructor(); self.init_type_error_prototype(); + self.init_uri_error_constructor(); self.init_uri_error_prototype(); } @@ -120,36 +172,35 @@ impl Runtime { ?params.name, params.length, ?params.slots, - ?params.prototype ); + let func = self.create_object(); + self.init_builtin_function(func, params); + func + } + + fn init_builtin_function( + &mut self, + mut func: HandleMut, + params: &BuiltinFunctionParams, + ) { let closure = self.create_closure(params.lambda, LambdaId::HOST, 0); - let mut func = self.create_object(); func.set_prototype(self.builtins.function_prototype); func.slots_mut().extend_from_slice(params.slots); func.set_closure(closure); - if let Some(prototype) = params.prototype { - func.set_constructor(); - let result = func.define_own_property( - Symbol::PROTOTYPE.into(), - Property::data_xxx(Value::Object(prototype)), - ); - debug_assert!(matches!(result, Ok(true))); - } - self.set_function_length(&mut func, params.length); + self.set_function_length(func, params.length); // TODO: prefix - self.set_function_name(&mut func, params.name); - func + self.set_function_name(func, params.name); } // 10.2.9 SetFunctionName ( F, name [ , prefix ] ) - fn set_function_name(&mut self, func: &mut HandleMut, name: Handle) { + fn set_function_name(&mut self, mut func: HandleMut, name: Handle) { let result = func.define_own_property(Symbol::NAME.into(), Property::data_xxc(Value::String(name))); debug_assert!(matches!(result, Ok(true))); } // 10.2.10 SetFunctionLength ( F, length ) - fn set_function_length(&mut self, func: &mut HandleMut, length: u16) { + fn set_function_length(&mut self, mut func: HandleMut, length: u16) { let result = func.define_own_property( Symbol::LENGTH.into(), Property::data_xxc(Value::Number(length as f64)), @@ -314,5 +365,4 @@ struct BuiltinFunctionParams<'a, X> { name: Handle, length: u16, slots: &'a [Value], - prototype: Option>, } diff --git a/libs/jsruntime/src/builtins/promise/imp.rs b/libs/jsruntime/src/builtins/promise/imp.rs index dec1e3112..51e624951 100644 --- a/libs/jsruntime/src/builtins/promise/imp.rs +++ b/libs/jsruntime/src/builtins/promise/imp.rs @@ -88,7 +88,6 @@ impl Runtime { name: crate::types::string::EMPTY, length: 1, slots: &[Value::Object(promise)], - prototype: None, }); let reject = self.create_builtin_function(&BuiltinFunctionParams { @@ -96,7 +95,6 @@ impl Runtime { name: crate::types::string::EMPTY, length: 1, slots: &[Value::Object(promise)], - prototype: None, }); (resolve, reject)