Browse Source

Implement abstract operation `GetPrototypeFromConstructor` (#1561)

pull/1565/head
jedel1043 3 years ago committed by GitHub
parent
commit
c91af158d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      boa/src/builtins/array/mod.rs
  2. 14
      boa/src/builtins/boolean/mod.rs
  3. 17
      boa/src/builtins/date/mod.rs
  4. 15
      boa/src/builtins/error/eval.rs
  5. 14
      boa/src/builtins/error/mod.rs
  6. 14
      boa/src/builtins/error/range.rs
  7. 14
      boa/src/builtins/error/reference.rs
  8. 14
      boa/src/builtins/error/syntax.rs
  9. 14
      boa/src/builtins/error/type.rs
  10. 14
      boa/src/builtins/error/uri.rs
  11. 15
      boa/src/builtins/function/mod.rs
  12. 18
      boa/src/builtins/map/mod.rs
  13. 14
      boa/src/builtins/number/mod.rs
  14. 19
      boa/src/builtins/object/mod.rs
  15. 18
      boa/src/builtins/regexp/mod.rs
  16. 18
      boa/src/builtins/set/mod.rs
  17. 16
      boa/src/builtins/string/mod.rs
  18. 36
      boa/src/object/internal_methods/mod.rs

17
boa/src/builtins/array/mod.rs

@ -17,7 +17,11 @@ use crate::{
builtins::array::array_iterator::ArrayIterator, builtins::array::array_iterator::ArrayIterator,
builtins::BuiltIn, builtins::BuiltIn,
builtins::Number, builtins::Number,
object::{ConstructorBuilder, FunctionBuilder, JsObject, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder,
JsObject, ObjectData,
},
property::{Attribute, PropertyDescriptor, PropertyNameKind}, property::{Attribute, PropertyDescriptor, PropertyNameKind},
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
value::{IntegerOrInfinity, JsValue}, value::{IntegerOrInfinity, JsValue},
@ -130,15 +134,8 @@ impl Array {
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
// If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget. // If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
// 2. Let proto be ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%"). // 2. Let proto be ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%").
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::array_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().array_object().prototype());
// 3. Let numberOfArgs be the number of elements in values. // 3. Let numberOfArgs be the number of elements in values.
let number_of_args = args.len(); let number_of_args = args.len();

14
boa/src/builtins/boolean/mod.rs

@ -14,7 +14,8 @@ mod tests;
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
property::Attribute, property::Attribute,
BoaProfiler, Context, JsResult, JsValue, BoaProfiler, Context, JsResult, JsValue,
}; };
@ -66,15 +67,8 @@ impl Boolean {
if new_target.is_undefined() { if new_target.is_undefined() {
return Ok(JsValue::new(data)); return Ok(JsValue::new(data));
} }
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::boolean_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let boolean = JsValue::new_object(context); let boolean = JsValue::new_object(context);
boolean boolean

17
boa/src/builtins/date/mod.rs

@ -3,8 +3,9 @@ mod tests;
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
context::StandardObjects,
gc::{empty_trace, Finalize, Trace}, gc::{empty_trace, Finalize, Trace},
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
property::Attribute, property::Attribute,
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
value::{JsValue, PreferredType}, value::{JsValue, PreferredType},
@ -340,15 +341,11 @@ impl Date {
if new_target.is_undefined() { if new_target.is_undefined() {
Ok(Self::make_date_string()) Ok(Self::make_date_string())
} else { } else {
let prototype = new_target let prototype = get_prototype_from_constructor(
.as_object() new_target,
.and_then(|obj| { StandardObjects::object_object,
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context) context,
.map(|o| o.as_object()) )?;
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = obj.into(); let this = obj.into();

15
boa/src/builtins/error/eval.rs

@ -11,7 +11,9 @@
//! [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-evalerror //! [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-evalerror
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError
use crate::object::PROTOTYPE; use crate::context::StandardObjects;
use crate::object::internal_methods::get_prototype_from_constructor;
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData}, object::{ConstructorBuilder, ObjectData},
@ -62,15 +64,8 @@ impl EvalError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/mod.rs

@ -12,7 +12,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
profiler::BoaProfiler, profiler::BoaProfiler,
property::Attribute, property::Attribute,
Context, JsResult, JsValue, Context, JsResult, JsValue,
@ -78,15 +79,8 @@ impl Error {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/range.rs

@ -11,7 +11,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
profiler::BoaProfiler, profiler::BoaProfiler,
property::Attribute, property::Attribute,
Context, JsResult, JsValue, Context, JsResult, JsValue,
@ -59,15 +60,8 @@ impl RangeError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/reference.rs

@ -11,7 +11,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
profiler::BoaProfiler, profiler::BoaProfiler,
property::Attribute, property::Attribute,
Context, JsResult, JsValue, Context, JsResult, JsValue,
@ -58,15 +59,8 @@ impl ReferenceError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/syntax.rs

@ -13,7 +13,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
profiler::BoaProfiler, profiler::BoaProfiler,
property::Attribute, property::Attribute,
Context, JsResult, JsValue, Context, JsResult, JsValue,
@ -61,15 +62,8 @@ impl SyntaxError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/type.rs

@ -17,7 +17,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
property::Attribute, property::Attribute,
BoaProfiler, Context, JsResult, JsValue, BoaProfiler, Context, JsResult, JsValue,
}; };
@ -64,15 +65,8 @@ impl TypeError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

14
boa/src/builtins/error/uri.rs

@ -12,7 +12,8 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
profiler::BoaProfiler, profiler::BoaProfiler,
property::Attribute, property::Attribute,
Context, JsResult, JsValue, Context, JsResult, JsValue,
@ -60,15 +61,8 @@ impl UriError {
args: &[JsValue], args: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::error_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().error_object().prototype());
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());
let this = JsValue::new(obj); let this = JsValue::new(obj);

15
boa/src/builtins/function/mod.rs

@ -11,7 +11,9 @@
//! [spec]: https://tc39.es/ecma262/#sec-function-objects //! [spec]: https://tc39.es/ecma262/#sec-function-objects
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
use crate::object::PROTOTYPE; use crate::context::StandardObjects;
use crate::object::internal_methods::get_prototype_from_constructor;
use crate::{ use crate::{
builtins::{Array, BuiltIn}, builtins::{Array, BuiltIn},
environment::lexical_environment::Environment, environment::lexical_environment::Environment,
@ -302,15 +304,8 @@ impl BuiltInFunctionObject {
_: &[JsValue], _: &[JsValue],
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::function_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let this = JsValue::new_object(context); let this = JsValue::new_object(context);
this.as_object() this.as_object()

18
boa/src/builtins/map/mod.rs

@ -14,7 +14,11 @@
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder,
ObjectData,
},
property::{Attribute, PropertyDescriptor, PropertyNameKind}, property::{Attribute, PropertyDescriptor, PropertyNameKind},
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
BoaProfiler, Context, JsResult, JsValue, BoaProfiler, Context, JsResult, JsValue,
@ -114,16 +118,8 @@ impl Map {
return context return context
.throw_type_error("calling a builtin Map constructor without new is forbidden"); .throw_type_error("calling a builtin Map constructor without new is forbidden");
} }
let map_prototype = context.standard_objects().map_object().prototype(); let prototype =
let prototype = new_target get_prototype_from_constructor(new_target, StandardObjects::map_object, context)?;
.as_object()
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or(map_prototype);
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());

14
boa/src/builtins/number/mod.rs

@ -15,9 +15,10 @@
use super::string::is_trimmable_whitespace; use super::string::is_trimmable_whitespace;
use super::{function::make_builtin_fn, JsArgs}; use super::{function::make_builtin_fn, JsArgs};
use crate::context::StandardObjects;
use crate::{ use crate::{
builtins::BuiltIn, builtins::BuiltIn,
object::{ConstructorBuilder, ObjectData, PROTOTYPE}, object::{internal_methods::get_prototype_from_constructor, ConstructorBuilder, ObjectData},
property::Attribute, property::Attribute,
value::{AbstractRelation, IntegerOrInfinity, JsValue}, value::{AbstractRelation, IntegerOrInfinity, JsValue},
BoaProfiler, Context, JsResult, BoaProfiler, Context, JsResult,
@ -166,15 +167,8 @@ impl Number {
if new_target.is_undefined() { if new_target.is_undefined() {
return Ok(JsValue::new(data)); return Ok(JsValue::new(data));
} }
let prototype = new_target let prototype =
.as_object() get_prototype_from_constructor(new_target, StandardObjects::number_object, context)?;
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let this = JsValue::new_object(context); let this = JsValue::new_object(context);
this.as_object() this.as_object()
.expect("this should be an object") .expect("this should be an object")

19
boa/src/builtins/object/mod.rs

@ -15,9 +15,10 @@
use crate::{ use crate::{
builtins::{BuiltIn, JsArgs}, builtins::{BuiltIn, JsArgs},
context::StandardObjects,
object::{ object::{
ConstructorBuilder, IntegrityLevel, JsObject, Object as BuiltinObject, ObjectData, internal_methods::get_prototype_from_constructor, ConstructorBuilder, IntegrityLevel,
ObjectInitializer, ObjectKind, PROTOTYPE, JsObject, Object as BuiltinObject, ObjectData, ObjectInitializer, ObjectKind,
}, },
property::{Attribute, DescriptorKind, PropertyDescriptor, PropertyKey, PropertyNameKind}, property::{Attribute, DescriptorKind, PropertyDescriptor, PropertyKey, PropertyNameKind},
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
@ -99,15 +100,11 @@ impl Object {
context: &mut Context, context: &mut Context,
) -> JsResult<JsValue> { ) -> JsResult<JsValue> {
if !new_target.is_undefined() { if !new_target.is_undefined() {
let prototype = new_target let prototype = get_prototype_from_constructor(
.as_object() new_target,
.and_then(|obj| { StandardObjects::object_object,
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context) context,
.map(|o| o.as_object()) )?;
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
let object = JsValue::new_object(context); let object = JsValue::new_object(context);
object object

18
boa/src/builtins/regexp/mod.rs

@ -13,8 +13,12 @@ pub mod regexp_string_iterator;
use crate::{ use crate::{
builtins::{array::Array, string, BuiltIn}, builtins::{array::Array, string, BuiltIn},
context::StandardObjects,
gc::{empty_trace, Finalize, Trace}, gc::{empty_trace, Finalize, Trace},
object::{ConstructorBuilder, FunctionBuilder, JsObject, Object, ObjectData, PROTOTYPE}, object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder,
JsObject, Object, ObjectData,
},
property::Attribute, property::Attribute,
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
value::{IntegerOrInfinity, JsValue}, value::{IntegerOrInfinity, JsValue},
@ -257,17 +261,9 @@ impl RegExp {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-regexpalloc /// [spec]: https://tc39.es/ecma262/#sec-regexpalloc
fn alloc(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> { fn alloc(this: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
let proto = if let Some(obj) = this.as_object() { let proto = get_prototype_from_constructor(this, StandardObjects::regexp_object, context)?;
obj.get(PROTOTYPE, context)?
} else {
context
.standard_objects()
.regexp_object()
.prototype()
.into()
};
Ok(JsObject::new(Object::create(proto)).into()) Ok(JsObject::new(Object::create(proto.into())).into())
} }
/// `22.2.3.2.2 RegExpInitialize ( obj, pattern, flags )` /// `22.2.3.2.2 RegExpInitialize ( obj, pattern, flags )`

18
boa/src/builtins/set/mod.rs

@ -12,7 +12,11 @@
use crate::{ use crate::{
builtins::{iterable::get_iterator, BuiltIn}, builtins::{iterable::get_iterator, BuiltIn},
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE}, context::StandardObjects,
object::{
internal_methods::get_prototype_from_constructor, ConstructorBuilder, FunctionBuilder,
ObjectData,
},
property::{Attribute, PropertyNameKind}, property::{Attribute, PropertyNameKind},
symbol::WellKnownSymbols, symbol::WellKnownSymbols,
BoaProfiler, Context, JsResult, JsValue, BoaProfiler, Context, JsResult, JsValue,
@ -123,16 +127,8 @@ impl Set {
} }
// 2 // 2
let set_prototype = context.standard_objects().set_object().prototype(); let prototype =
let prototype = new_target get_prototype_from_constructor(new_target, StandardObjects::set_object, context)?;
.as_object()
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or(set_prototype);
let obj = context.construct_object(); let obj = context.construct_object();
obj.set_prototype_instance(prototype.into()); obj.set_prototype_instance(prototype.into());

16
boa/src/builtins/string/mod.rs

@ -14,7 +14,9 @@ pub mod string_iterator;
mod tests; mod tests;
use crate::builtins::Symbol; use crate::builtins::Symbol;
use crate::object::{JsObject, PROTOTYPE}; use crate::context::StandardObjects;
use crate::object::internal_methods::get_prototype_from_constructor;
use crate::object::JsObject;
use crate::{ use crate::{
builtins::{string::string_iterator::StringIterator, Array, BuiltIn, RegExp}, builtins::{string::string_iterator::StringIterator, Array, BuiltIn, RegExp},
object::{ConstructorBuilder, ObjectData}, object::{ConstructorBuilder, ObjectData},
@ -179,16 +181,8 @@ impl String {
return Ok(string.into()); return Ok(string.into());
} }
// todo: extract `GetPrototypeFromConstructor` function let prototype =
let prototype = new_target get_prototype_from_constructor(new_target, StandardObjects::string_object, context)?;
.as_object()
.and_then(|obj| {
obj.__get__(&PROTOTYPE.into(), obj.clone().into(), context)
.map(|o| o.as_object())
.transpose()
})
.transpose()?
.unwrap_or_else(|| context.standard_objects().object_object().prototype());
Ok(Self::string_create(string, prototype, context).into()) Ok(Self::string_create(string, prototype, context).into())
} }

36
boa/src/object/internal_methods/mod.rs

@ -6,12 +6,15 @@
//! [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots //! [spec]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
use crate::{ use crate::{
context::{StandardConstructor, StandardObjects},
object::JsObject, object::JsObject,
property::{DescriptorKind, PropertyDescriptor, PropertyKey}, property::{DescriptorKind, PropertyDescriptor, PropertyKey},
value::JsValue, value::JsValue,
BoaProfiler, Context, JsResult, BoaProfiler, Context, JsResult,
}; };
use super::PROTOTYPE;
pub(super) mod array; pub(super) mod array;
pub(super) mod string; pub(super) mod string;
@ -859,3 +862,36 @@ pub(crate) fn validate_and_apply_property_descriptor(
// 10. Return true. // 10. Return true.
true true
} }
/// Abstract operation `GetPrototypeFromConstructor`
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-getprototypefromconstructor
#[inline]
#[track_caller]
pub(crate) fn get_prototype_from_constructor<F>(
constructor: &JsValue,
default: F,
context: &mut Context,
) -> JsResult<JsObject>
where
F: FnOnce(&StandardObjects) -> &StandardConstructor,
{
// 1. Assert: intrinsicDefaultProto is this specification's name of an intrinsic
// object.
// The corresponding object must be an intrinsic that is intended to be used
// as the [[Prototype]] value of an object.
// 2. Let proto be ? Get(constructor, "prototype").
if let Some(object) = constructor.as_object() {
if let Some(proto) = object.get(PROTOTYPE, context)?.as_object() {
return Ok(proto);
}
}
// 3. If Type(proto) is not Object, then
// TODO: handle realms
// a. Let realm be ? GetFunctionRealm(constructor).
// b. Set proto to realm's intrinsic object named intrinsicDefaultProto.
Ok(default(context.standard_objects()).prototype())
}

Loading…
Cancel
Save