pub mod array;
pub mod array_buffer;
pub mod async_function;
pub mod async_generator;
pub mod async_generator_function;
pub mod bigint;
pub mod boolean;
pub mod dataview;
pub mod date;
pub mod error;
pub mod eval;
pub mod function;
pub mod generator;
pub mod generator_function;
pub mod iterable;
pub mod json;
pub mod map;
pub mod math;
pub mod number;
pub mod object;
pub mod promise;
pub mod proxy;
pub mod reflect;
pub mod regexp;
pub mod set;
pub mod string;
pub mod symbol;
pub mod typed_array;
pub mod uri;
pub mod weak;
pub mod weak_map;
pub mod weak_set;
#[cfg(feature = "annex-b")]
pub mod escape;
#[cfg(feature = "intl")]
pub mod intl;
pub(crate) use self::{
array::Array,
async_function::AsyncFunction,
bigint::BigInt,
boolean::Boolean,
dataview::DataView,
date::Date,
error::{
AggregateError, Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError,
UriError,
},
eval::Eval,
function::BuiltInFunctionObject,
json::Json,
map::Map,
math::Math,
number::{IsFinite, IsNaN, Number, ParseFloat, ParseInt},
object::Object as BuiltInObjectObject,
promise::Promise,
proxy::Proxy,
reflect::Reflect,
regexp::RegExp,
set::Set,
string::String,
symbol::Symbol,
typed_array::{
BigInt64Array, BigUint64Array, Float32Array, Float64Array, Int16Array, Int32Array,
Int8Array, Uint16Array, Uint32Array, Uint8Array, Uint8ClampedArray,
},
};
use crate::{
builtins::{
array::ArrayIterator,
array_buffer::ArrayBuffer,
async_generator::AsyncGenerator,
async_generator_function::AsyncGeneratorFunction,
error::r#type::ThrowTypeError,
generator::Generator,
generator_function::GeneratorFunction,
iterable::{AsyncFromSyncIterator, AsyncIterator, Iterator},
map::MapIterator,
object::for_in_iterator::ForInIterator,
regexp::RegExpStringIterator,
set::SetIterator,
string::StringIterator,
typed_array::TypedArray,
uri::{DecodeUri, DecodeUriComponent, EncodeUri, EncodeUriComponent},
weak::WeakRef,
weak_map::WeakMap,
weak_set::WeakSet,
},
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
js_string,
native_function::{NativeFunction, NativeFunctionPointer},
object::{
shape::{property_table::PropertyTableInner, slot::SlotAttributes},
FunctionBinding, JsFunction, JsObject, JsPrototype, Object, ObjectData, ObjectKind,
CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
string::utf16,
Context, JsResult, JsString, JsValue,
};
pub(crate) trait IntrinsicObject {
fn init(realm: &Realm);
fn get(intrinsics: &Intrinsics) -> JsObject;
}
pub(crate) trait BuiltInObject: IntrinsicObject {
const NAME: &'static str;
const ATTRIBUTE: Attribute = Attribute::WRITABLE
.union(Attribute::NON_ENUMERABLE)
.union(Attribute::CONFIGURABLE);
}
pub(crate) trait BuiltInConstructor: BuiltInObject {
const LENGTH: usize;
const STANDARD_CONSTRUCTOR: fn(&StandardConstructors) -> &StandardConstructor;
fn constructor(
new_target: &JsValue,
args: &[JsValue],
context: &mut Context<'_>,
) -> JsResult<JsValue>;
}
fn global_binding<B: BuiltInObject>(context: &mut Context<'_>) -> JsResult<()> {
let name = B::NAME;
let attr = B::ATTRIBUTE;
let intrinsic = B::get(context.intrinsics());
let global_object = context.global_object();
global_object.define_property_or_throw(
name,
PropertyDescriptor::builder()
.value(intrinsic)
.writable(attr.writable())
.enumerable(attr.enumerable())
.configurable(attr.configurable())
.build(),
context,
)?;
Ok(())
}
impl Realm {
pub(crate) fn initialize(&self) {
BuiltInFunctionObject::init(self);
BuiltInObjectObject::init(self);
Iterator::init(self);
AsyncIterator::init(self);
AsyncFromSyncIterator::init(self);
ForInIterator::init(self);
Math::init(self);
Json::init(self);
Array::init(self);
ArrayIterator::init(self);
Proxy::init(self);
ArrayBuffer::init(self);
BigInt::init(self);
Boolean::init(self);
Date::init(self);
DataView::init(self);
Map::init(self);
MapIterator::init(self);
IsFinite::init(self);
IsNaN::init(self);
ParseInt::init(self);
ParseFloat::init(self);
Number::init(self);
Eval::init(self);
Set::init(self);
SetIterator::init(self);
String::init(self);
StringIterator::init(self);
RegExp::init(self);
RegExpStringIterator::init(self);
TypedArray::init(self);
Int8Array::init(self);
Uint8Array::init(self);
Uint8ClampedArray::init(self);
Int16Array::init(self);
Uint16Array::init(self);
Int32Array::init(self);
Uint32Array::init(self);
BigInt64Array::init(self);
BigUint64Array::init(self);
Float32Array::init(self);
Float64Array::init(self);
Symbol::init(self);
Error::init(self);
RangeError::init(self);
ReferenceError::init(self);
TypeError::init(self);
ThrowTypeError::init(self);
SyntaxError::init(self);
EvalError::init(self);
UriError::init(self);
AggregateError::init(self);
Reflect::init(self);
Generator::init(self);
GeneratorFunction::init(self);
Promise::init(self);
AsyncFunction::init(self);
AsyncGenerator::init(self);
AsyncGeneratorFunction::init(self);
EncodeUri::init(self);
EncodeUriComponent::init(self);
DecodeUri::init(self);
DecodeUriComponent::init(self);
WeakRef::init(self);
WeakMap::init(self);
WeakSet::init(self);
#[cfg(feature = "annex-b")]
{
escape::Escape::init(self);
escape::Unescape::init(self);
}
#[cfg(feature = "intl")]
{
intl::Intl::init(self);
intl::Collator::init(self);
intl::ListFormat::init(self);
intl::Locale::init(self);
intl::DateTimeFormat::init(self);
intl::Segmenter::init(self);
intl::segmenter::Segments::init(self);
intl::segmenter::SegmentIterator::init(self);
}
}
}
pub(crate) fn set_default_global_bindings(context: &mut Context<'_>) -> JsResult<()> {
let global_object = context.global_object();
global_object.define_property_or_throw(
utf16!("globalThis"),
PropertyDescriptor::builder()
.value(context.realm().global_this().clone())
.writable(true)
.enumerable(false)
.configurable(true),
context,
)?;
let restricted = PropertyDescriptor::builder()
.writable(false)
.enumerable(false)
.configurable(false);
global_object.define_property_or_throw(
utf16!("Infinity"),
restricted.clone().value(f64::INFINITY),
context,
)?;
global_object.define_property_or_throw(
utf16!("NaN"),
restricted.clone().value(f64::NAN),
context,
)?;
global_object.define_property_or_throw(
utf16!("undefined"),
restricted.value(JsValue::undefined()),
context,
)?;
global_binding::<BuiltInFunctionObject>(context)?;
global_binding::<BuiltInObjectObject>(context)?;
global_binding::<Math>(context)?;
global_binding::<Json>(context)?;
global_binding::<Array>(context)?;
global_binding::<Proxy>(context)?;
global_binding::<ArrayBuffer>(context)?;
global_binding::<BigInt>(context)?;
global_binding::<Boolean>(context)?;
global_binding::<Date>(context)?;
global_binding::<DataView>(context)?;
global_binding::<Map>(context)?;
global_binding::<IsFinite>(context)?;
global_binding::<IsNaN>(context)?;
global_binding::<ParseInt>(context)?;
global_binding::<ParseFloat>(context)?;
global_binding::<Number>(context)?;
global_binding::<Eval>(context)?;
global_binding::<Set>(context)?;
global_binding::<String>(context)?;
global_binding::<RegExp>(context)?;
global_binding::<TypedArray>(context)?;
global_binding::<Int8Array>(context)?;
global_binding::<Uint8Array>(context)?;
global_binding::<Uint8ClampedArray>(context)?;
global_binding::<Int16Array>(context)?;
global_binding::<Uint16Array>(context)?;
global_binding::<Int32Array>(context)?;
global_binding::<Uint32Array>(context)?;
global_binding::<BigInt64Array>(context)?;
global_binding::<BigUint64Array>(context)?;
global_binding::<Float32Array>(context)?;
global_binding::<Float64Array>(context)?;
global_binding::<Symbol>(context)?;
global_binding::<Error>(context)?;
global_binding::<RangeError>(context)?;
global_binding::<ReferenceError>(context)?;
global_binding::<TypeError>(context)?;
global_binding::<SyntaxError>(context)?;
global_binding::<EvalError>(context)?;
global_binding::<UriError>(context)?;
global_binding::<AggregateError>(context)?;
global_binding::<Reflect>(context)?;
global_binding::<Promise>(context)?;
global_binding::<EncodeUri>(context)?;
global_binding::<EncodeUriComponent>(context)?;
global_binding::<DecodeUri>(context)?;
global_binding::<DecodeUriComponent>(context)?;
global_binding::<WeakRef>(context)?;
global_binding::<WeakMap>(context)?;
global_binding::<WeakSet>(context)?;
#[cfg(feature = "annex-b")]
{
global_binding::<escape::Escape>(context)?;
global_binding::<escape::Unescape>(context)?;
}
#[cfg(feature = "intl")]
global_binding::<intl::Intl>(context)?;
Ok(())
}
#[derive(Debug)]
enum BuiltInObjectInitializer {
Shared(JsObject),
Unique { object: Object, data: ObjectData },
}
impl BuiltInObjectInitializer {
fn insert<K, P>(&mut self, key: K, property: P)
where
K: Into<PropertyKey>,
P: Into<PropertyDescriptor>,
{
match self {
Self::Shared(obj) => obj.borrow_mut().insert(key, property),
Self::Unique { object, .. } => object.insert(key, property),
};
}
fn set_prototype(&mut self, prototype: JsObject) {
match self {
Self::Shared(obj) => {
let mut obj = obj.borrow_mut();
obj.set_prototype(prototype);
}
Self::Unique { object, .. } => {
object.set_prototype(prototype);
}
}
}
fn set_data(&mut self, new_data: ObjectData) {
match self {
Self::Shared(obj) => {
assert!(
std::ptr::eq(obj.vtable(), new_data.internal_methods),
"intrinsic object's vtable didn't match with new data"
);
*obj.borrow_mut().kind_mut() = new_data.kind;
}
Self::Unique { ref mut data, .. } => *data = new_data,
}
}
fn as_shared(&mut self) -> JsObject {
match std::mem::replace(
self,
Self::Unique {
object: Object::default(),
data: ObjectData::ordinary(),
},
) {
Self::Shared(obj) => {
*self = Self::Shared(obj.clone());
obj
}
Self::Unique { mut object, data } => {
*object.kind_mut() = data.kind;
let obj = JsObject::from_object_and_vtable(object, data.internal_methods);
*self = Self::Shared(obj.clone());
obj
}
}
}
fn into_shared(mut self) -> JsObject {
self.as_shared()
}
}
struct Constructor {
prototype: JsObject,
inherits: JsPrototype,
attributes: Attribute,
}
struct ConstructorNoProto;
struct OrdinaryFunction;
trait IsConstructor {
const IS_CONSTRUCTOR: bool;
}
impl IsConstructor for Constructor {
const IS_CONSTRUCTOR: bool = true;
}
impl IsConstructor for ConstructorNoProto {
const IS_CONSTRUCTOR: bool = true;
}
impl IsConstructor for OrdinaryFunction {
const IS_CONSTRUCTOR: bool = false;
}
struct Callable<Kind> {
function: NativeFunctionPointer,
name: JsString,
length: usize,
kind: Kind,
realm: Realm,
}
struct OrdinaryObject;
trait ApplyToObject {
fn apply_to(self, object: &mut BuiltInObjectInitializer);
}
impl ApplyToObject for Constructor {
fn apply_to(self, object: &mut BuiltInObjectInitializer) {
object.insert(
PROTOTYPE,
PropertyDescriptor::builder()
.value(self.prototype.clone())
.writable(false)
.enumerable(false)
.configurable(false),
);
let object = object.as_shared();
{
let mut prototype = self.prototype.borrow_mut();
prototype.set_prototype(self.inherits);
prototype.insert(
CONSTRUCTOR,
PropertyDescriptor::builder()
.value(object)
.writable(self.attributes.writable())
.enumerable(self.attributes.enumerable())
.configurable(self.attributes.configurable()),
);
}
}
}
impl ApplyToObject for ConstructorNoProto {
fn apply_to(self, _: &mut BuiltInObjectInitializer) {}
}
impl ApplyToObject for OrdinaryFunction {
fn apply_to(self, _: &mut BuiltInObjectInitializer) {}
}
impl<S: ApplyToObject + IsConstructor> ApplyToObject for Callable<S> {
fn apply_to(self, object: &mut BuiltInObjectInitializer) {
let function = ObjectData::function(
function::Function::new(
function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: S::IS_CONSTRUCTOR.then_some(function::ConstructorKind::Base),
},
self.realm,
),
S::IS_CONSTRUCTOR,
);
object.set_data(function);
object.insert(
utf16!("length"),
PropertyDescriptor::builder()
.value(self.length)
.writable(false)
.enumerable(false)
.configurable(true),
);
object.insert(
utf16!("name"),
PropertyDescriptor::builder()
.value(self.name)
.writable(false)
.enumerable(false)
.configurable(true),
);
self.kind.apply_to(object);
}
}
impl ApplyToObject for OrdinaryObject {
fn apply_to(self, _: &mut BuiltInObjectInitializer) {}
}
#[derive(Debug)]
#[must_use = "You need to call the `build` method in order for this to correctly assign the inner data"]
struct BuiltInBuilder<'ctx, Kind> {
realm: &'ctx Realm,
object: BuiltInObjectInitializer,
kind: Kind,
prototype: JsObject,
}
impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
fn with_intrinsic<I: IntrinsicObject>(
realm: &'ctx Realm,
) -> BuiltInBuilder<'ctx, OrdinaryObject> {
BuiltInBuilder {
realm,
object: BuiltInObjectInitializer::Shared(I::get(realm.intrinsics())),
kind: OrdinaryObject,
prototype: realm.intrinsics().constructors().object().prototype(),
}
}
}
struct BuiltInConstructorWithPrototype<'ctx> {
realm: &'ctx Realm,
function: NativeFunctionPointer,
name: JsString,
length: usize,
object_property_table: PropertyTableInner,
object_storage: Vec<JsValue>,
object: JsObject,
prototype_property_table: PropertyTableInner,
prototype_storage: Vec<JsValue>,
prototype: JsObject,
__proto__: JsPrototype,
inherits: Option<JsObject>,
attributes: Attribute,
}
#[allow(dead_code)]
impl BuiltInConstructorWithPrototype<'_> {
#[inline]
const fn length(mut self, length: usize) -> Self {
self.length = length;
self
}
fn name<N: Into<JsString>>(mut self, name: N) -> Self {
self.name = name.into();
self
}
fn static_method<B>(
mut self,
function: NativeFunctionPointer,
binding: B,
length: usize,
) -> Self
where
B: Into<FunctionBinding>,
{
let binding = binding.into();
let function = BuiltInBuilder::callable(self.realm, function)
.name(binding.name)
.length(length)
.build();
debug_assert!(self
.object_property_table
.map
.get(&binding.binding)
.is_none());
self.object_property_table.insert(
binding.binding,
SlotAttributes::WRITABLE | SlotAttributes::CONFIGURABLE,
);
self.object_storage.push(function.into());
self
}
fn static_property<K, V>(mut self, key: K, value: V, attribute: Attribute) -> Self
where
K: Into<PropertyKey>,
V: Into<JsValue>,
{
let key = key.into();
debug_assert!(self.object_property_table.map.get(&key).is_none());
self.object_property_table
.insert(key, SlotAttributes::from_bits_truncate(attribute.bits()));
self.object_storage.push(value.into());
self
}
fn static_accessor<K>(
mut self,
key: K,
get: Option<JsFunction>,
set: Option<JsFunction>,
attribute: Attribute,
) -> Self
where
K: Into<PropertyKey>,
{
let mut attributes = SlotAttributes::from_bits_truncate(attribute.bits());
debug_assert!(!attributes.contains(SlotAttributes::WRITABLE));
attributes.set(SlotAttributes::GET, get.is_some());
attributes.set(SlotAttributes::SET, set.is_some());
let key = key.into();
debug_assert!(self.object_property_table.map.get(&key).is_none());
self.object_property_table.insert(key, attributes);
self.object_storage.extend([
get.map(JsValue::new).unwrap_or_default(),
set.map(JsValue::new).unwrap_or_default(),
]);
self
}
fn prototype(mut self, prototype: JsObject) -> Self {
self.__proto__ = Some(prototype);
self
}
fn method<B>(mut self, function: NativeFunctionPointer, binding: B, length: usize) -> Self
where
B: Into<FunctionBinding>,
{
let binding = binding.into();
let function = BuiltInBuilder::callable(self.realm, function)
.name(binding.name)
.length(length)
.build();
debug_assert!(self
.prototype_property_table
.map
.get(&binding.binding)
.is_none());
self.prototype_property_table.insert(
binding.binding,
SlotAttributes::WRITABLE | SlotAttributes::CONFIGURABLE,
);
self.prototype_storage.push(function.into());
self
}
fn property<K, V>(mut self, key: K, value: V, attribute: Attribute) -> Self
where
K: Into<PropertyKey>,
V: Into<JsValue>,
{
let key = key.into();
debug_assert!(self.prototype_property_table.map.get(&key).is_none());
self.prototype_property_table
.insert(key, SlotAttributes::from_bits_truncate(attribute.bits()));
self.prototype_storage.push(value.into());
self
}
fn accessor<K>(
mut self,
key: K,
get: Option<JsFunction>,
set: Option<JsFunction>,
attribute: Attribute,
) -> Self
where
K: Into<PropertyKey>,
{
let mut attributes = SlotAttributes::from_bits_truncate(attribute.bits());
debug_assert!(!attributes.contains(SlotAttributes::WRITABLE));
attributes.set(SlotAttributes::GET, get.is_some());
attributes.set(SlotAttributes::SET, set.is_some());
let key = key.into();
debug_assert!(self.prototype_property_table.map.get(&key).is_none());
self.prototype_property_table.insert(key, attributes);
self.prototype_storage.extend([
get.map(JsValue::new).unwrap_or_default(),
set.map(JsValue::new).unwrap_or_default(),
]);
self
}
#[allow(clippy::missing_const_for_fn)]
fn inherits(mut self, prototype: JsPrototype) -> Self {
self.inherits = prototype;
self
}
const fn constructor_attributes(mut self, attributes: Attribute) -> Self {
self.attributes = attributes;
self
}
fn build(mut self) {
let function = function::Function::new(
function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: (true).then_some(function::ConstructorKind::Base),
},
self.realm.clone(),
);
let length = self.length;
let name = self.name.clone();
let prototype = self.prototype.clone();
self = self.static_property("length", length, Attribute::CONFIGURABLE);
self = self.static_property("name", name, Attribute::CONFIGURABLE);
self = self.static_property(PROTOTYPE, prototype, Attribute::empty());
let attributes = self.attributes;
let object = self.object.clone();
self = self.property(CONSTRUCTOR, object, attributes);
{
let mut prototype = self.prototype.borrow_mut();
prototype
.properties_mut()
.shape
.as_unique()
.expect("The object should have a unique shape")
.override_internal(self.prototype_property_table, self.inherits);
let prototype_old_storage = std::mem::replace(
&mut prototype.properties_mut().storage,
self.prototype_storage,
);
debug_assert_eq!(prototype_old_storage.len(), 0);
}
let mut object = self.object.borrow_mut();
*object.kind_mut() = ObjectKind::Function(function);
object
.properties_mut()
.shape
.as_unique()
.expect("The object should have a unique shape")
.override_internal(self.object_property_table, self.__proto__);
let object_old_storage =
std::mem::replace(&mut object.properties_mut().storage, self.object_storage);
debug_assert_eq!(object_old_storage.len(), 0);
}
fn build_without_prototype(mut self) {
let function = function::Function::new(
function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: (true).then_some(function::ConstructorKind::Base),
},
self.realm.clone(),
);
let length = self.length;
let name = self.name.clone();
self = self.static_property("length", length, Attribute::CONFIGURABLE);
self = self.static_property("name", name, Attribute::CONFIGURABLE);
let mut object = self.object.borrow_mut();
*object.kind_mut() = ObjectKind::Function(function);
object
.properties_mut()
.shape
.as_unique()
.expect("The object should have a unique shape")
.override_internal(self.object_property_table, self.__proto__);
let object_old_storage =
std::mem::replace(&mut object.properties_mut().storage, self.object_storage);
debug_assert_eq!(object_old_storage.len(), 0);
}
}
struct BuiltInCallable<'ctx> {
realm: &'ctx Realm,
function: NativeFunctionPointer,
name: JsString,
length: usize,
}
impl BuiltInCallable<'_> {
#[inline]
const fn length(mut self, length: usize) -> Self {
self.length = length;
self
}
fn name<N: Into<JsString>>(mut self, name: N) -> Self {
self.name = name.into();
self
}
fn build(self) -> JsFunction {
let function = function::FunctionKind::Native {
function: NativeFunction::from_fn_ptr(self.function),
constructor: None,
};
let function = function::Function::new(function, self.realm.clone());
let object = self.realm.intrinsics().templates().function().create(
ObjectData::function(function, false),
vec![JsValue::new(self.length), JsValue::new(self.name)],
);
JsFunction::from_object_unchecked(object)
}
}
impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
fn callable(realm: &'ctx Realm, function: NativeFunctionPointer) -> BuiltInCallable<'ctx> {
BuiltInCallable {
realm,
function,
length: 0,
name: js_string!(""),
}
}
fn callable_with_intrinsic<I: IntrinsicObject>(
realm: &'ctx Realm,
function: NativeFunctionPointer,
) -> BuiltInBuilder<'ctx, Callable<OrdinaryFunction>> {
BuiltInBuilder {
realm,
object: BuiltInObjectInitializer::Shared(I::get(realm.intrinsics())),
kind: Callable {
function,
name: js_string!(""),
length: 0,
kind: OrdinaryFunction,
realm: realm.clone(),
},
prototype: realm.intrinsics().constructors().function().prototype(),
}
}
fn callable_with_object(
realm: &'ctx Realm,
object: JsObject,
function: NativeFunctionPointer,
) -> BuiltInBuilder<'ctx, Callable<OrdinaryFunction>> {
BuiltInBuilder {
realm,
object: BuiltInObjectInitializer::Shared(object),
kind: Callable {
function,
name: js_string!(""),
length: 0,
kind: OrdinaryFunction,
realm: realm.clone(),
},
prototype: realm.intrinsics().constructors().function().prototype(),
}
}
}
impl<'ctx> BuiltInBuilder<'ctx, Callable<Constructor>> {
fn from_standard_constructor<SC: BuiltInConstructor>(
realm: &'ctx Realm,
) -> BuiltInConstructorWithPrototype<'ctx> {
let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
BuiltInConstructorWithPrototype {
realm,
function: SC::constructor,
name: js_string!(SC::NAME),
length: SC::LENGTH,
object_property_table: PropertyTableInner::default(),
object_storage: Vec::default(),
object: constructor.constructor(),
prototype_property_table: PropertyTableInner::default(),
prototype_storage: Vec::default(),
prototype: constructor.prototype(),
__proto__: Some(realm.intrinsics().constructors().function().prototype()),
inherits: Some(realm.intrinsics().constructors().object().prototype()),
attributes: Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
}
}
}
impl<T> BuiltInBuilder<'_, T> {
fn static_method<B>(
mut self,
function: NativeFunctionPointer,
binding: B,
length: usize,
) -> Self
where
B: Into<FunctionBinding>,
{
let binding = binding.into();
let function = BuiltInBuilder::callable(self.realm, function)
.name(binding.name)
.length(length)
.build();
self.object.insert(
binding.binding,
PropertyDescriptor::builder()
.value(function)
.writable(true)
.enumerable(false)
.configurable(true),
);
self
}
fn static_property<K, V>(mut self, key: K, value: V, attribute: Attribute) -> Self
where
K: Into<PropertyKey>,
V: Into<JsValue>,
{
let property = PropertyDescriptor::builder()
.value(value)
.writable(attribute.writable())
.enumerable(attribute.enumerable())
.configurable(attribute.configurable());
self.object.insert(key, property);
self
}
fn prototype(mut self, prototype: JsObject) -> Self {
self.prototype = prototype;
self
}
}
impl<FnTyp> BuiltInBuilder<'_, Callable<FnTyp>> {
#[inline]
const fn length(mut self, length: usize) -> Self {
self.kind.length = length;
self
}
fn name<N: Into<JsString>>(mut self, name: N) -> Self {
self.kind.name = name.into();
self
}
}
impl BuiltInBuilder<'_, OrdinaryObject> {
fn build(mut self) -> JsObject {
self.kind.apply_to(&mut self.object);
self.object.set_prototype(self.prototype);
self.object.into_shared()
}
}
impl<FnTyp: ApplyToObject + IsConstructor> BuiltInBuilder<'_, Callable<FnTyp>> {
fn build(mut self) -> JsFunction {
self.kind.apply_to(&mut self.object);
self.object.set_prototype(self.prototype);
JsFunction::from_object_unchecked(self.object.into_shared())
}
}