Rust编写的JavaScript引擎,该项目是一个试验性质的项目。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1453 lines
46 KiB

//! Data structures that contain intrinsic objects and constructors.
use boa_gc::{Finalize, Trace};
use crate::{
builtins::{iterable::IteratorPrototypes, uri::UriFunctions},
object::{
shape::{shared_shape::template::ObjectTemplate, RootShape},
JsFunction, JsObject, ObjectData, CONSTRUCTOR, PROTOTYPE,
},
property::{Attribute, PropertyKey},
JsSymbol,
};
/// The intrinsic objects and constructors.
///
/// `Intrinsics` is internally stored using a `Gc`, which makes it cheapily clonable
/// for multiple references to the same set of intrinsic objects.
#[derive(Debug, Trace, Finalize)]
pub struct Intrinsics {
/// Cached standard constructors
pub(super) constructors: StandardConstructors,
/// Cached intrinsic objects
pub(super) objects: IntrinsicObjects,
/// Cached object templates.
pub(super) templates: ObjectTemplates,
}
impl crate::snapshot::Serialize for Intrinsics {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
self.constructors.serialize(s)?;
self.objects.serialize(s)?;
self.templates.serialize(s)?;
Ok(())
}
}
impl Intrinsics {
pub(crate) fn new(root_shape: &RootShape) -> Self {
let constructors = StandardConstructors::default();
let templates = ObjectTemplates::new(root_shape, &constructors);
Self {
constructors,
objects: IntrinsicObjects::default(),
templates,
}
}
/// Return the cached intrinsic objects.
#[inline]
pub const fn objects(&self) -> &IntrinsicObjects {
&self.objects
}
/// Return the cached standard constructors.
#[inline]
pub const fn constructors(&self) -> &StandardConstructors {
&self.constructors
}
pub(crate) const fn templates(&self) -> &ObjectTemplates {
&self.templates
}
}
/// Store a builtin constructor (such as `Object`) and its corresponding prototype.
#[derive(Debug, Trace, Finalize)]
pub struct StandardConstructor {
constructor: JsFunction,
prototype: JsObject,
}
impl crate::snapshot::Serialize for StandardConstructor {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
self.constructor.serialize(s)?;
self.prototype.serialize(s)?;
Ok(())
}
}
impl Default for StandardConstructor {
fn default() -> Self {
Self {
constructor: JsFunction::empty_intrinsic_function(true),
prototype: JsObject::with_null_proto(),
}
}
}
impl StandardConstructor {
/// Build a constructor with a defined prototype.
fn with_prototype(prototype: JsObject) -> Self {
Self {
constructor: JsFunction::empty_intrinsic_function(true),
prototype,
}
}
/// Return the prototype of the constructor object.
///
/// This is the same as `Object.prototype`, `Array.prototype`, etc
#[inline]
pub fn prototype(&self) -> JsObject {
self.prototype.clone()
}
/// Return the constructor object.
///
/// This is the same as `Object`, `Array`, etc.
#[inline]
pub fn constructor(&self) -> JsObject {
self.constructor.clone().into()
}
}
/// Cached core standard constructors.
#[derive(Debug, Trace, Finalize)]
pub struct StandardConstructors {
object: StandardConstructor,
proxy: StandardConstructor,
date: StandardConstructor,
function: StandardConstructor,
async_function: StandardConstructor,
generator_function: StandardConstructor,
async_generator_function: StandardConstructor,
array: StandardConstructor,
bigint: StandardConstructor,
number: StandardConstructor,
boolean: StandardConstructor,
string: StandardConstructor,
regexp: StandardConstructor,
symbol: StandardConstructor,
error: StandardConstructor,
type_error: StandardConstructor,
reference_error: StandardConstructor,
range_error: StandardConstructor,
syntax_error: StandardConstructor,
eval_error: StandardConstructor,
uri_error: StandardConstructor,
aggregate_error: StandardConstructor,
map: StandardConstructor,
set: StandardConstructor,
typed_array: StandardConstructor,
typed_int8_array: StandardConstructor,
typed_uint8_array: StandardConstructor,
typed_uint8clamped_array: StandardConstructor,
typed_int16_array: StandardConstructor,
typed_uint16_array: StandardConstructor,
typed_int32_array: StandardConstructor,
typed_uint32_array: StandardConstructor,
typed_bigint64_array: StandardConstructor,
typed_biguint64_array: StandardConstructor,
typed_float32_array: StandardConstructor,
typed_float64_array: StandardConstructor,
array_buffer: StandardConstructor,
data_view: StandardConstructor,
date_time_format: StandardConstructor,
promise: StandardConstructor,
weak_ref: StandardConstructor,
weak_map: StandardConstructor,
weak_set: StandardConstructor,
#[cfg(feature = "intl")]
collator: StandardConstructor,
#[cfg(feature = "intl")]
list_format: StandardConstructor,
#[cfg(feature = "intl")]
locale: StandardConstructor,
#[cfg(feature = "intl")]
segmenter: StandardConstructor,
}
impl crate::snapshot::Serialize for StandardConstructors {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
self.object.serialize(s)?;
self.proxy.serialize(s)?;
self.date.serialize(s)?;
self.function.serialize(s)?;
self.async_function.serialize(s)?;
self.generator_function.serialize(s)?;
self.async_generator_function.serialize(s)?;
self.array.serialize(s)?;
self.bigint.serialize(s)?;
self.number.serialize(s)?;
self.boolean.serialize(s)?;
self.string.serialize(s)?;
self.regexp.serialize(s)?;
self.symbol.serialize(s)?;
self.error.serialize(s)?;
self.type_error.serialize(s)?;
self.reference_error.serialize(s)?;
self.range_error.serialize(s)?;
self.syntax_error.serialize(s)?;
self.eval_error.serialize(s)?;
self.uri_error.serialize(s)?;
self.aggregate_error.serialize(s)?;
self.map.serialize(s)?;
self.set.serialize(s)?;
self.typed_array.serialize(s)?;
self.typed_int8_array.serialize(s)?;
self.typed_uint8_array.serialize(s)?;
self.typed_uint8clamped_array.serialize(s)?;
self.typed_int16_array.serialize(s)?;
self.typed_uint16_array.serialize(s)?;
self.typed_int32_array.serialize(s)?;
self.typed_uint32_array.serialize(s)?;
self.typed_bigint64_array.serialize(s)?;
self.typed_biguint64_array.serialize(s)?;
self.typed_float32_array.serialize(s)?;
self.typed_float64_array.serialize(s)?;
self.array_buffer.serialize(s)?;
self.data_view.serialize(s)?;
self.date_time_format.serialize(s)?;
self.promise.serialize(s)?;
self.weak_ref.serialize(s)?;
self.weak_map.serialize(s)?;
self.weak_set.serialize(s)?;
#[cfg(feature = "intl")]
self.collator.serialize(s)?;
#[cfg(feature = "intl")]
self.list_format.serialize(s)?;
#[cfg(feature = "intl")]
self.locale.serialize(s)?;
#[cfg(feature = "intl")]
self.segmenter.serialize(s)?;
Ok(())
}
}
impl Default for StandardConstructors {
fn default() -> Self {
Self {
object: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
ObjectData::object_prototype(),
)),
async_generator_function: StandardConstructor::default(),
proxy: StandardConstructor::default(),
date: StandardConstructor::default(),
function: StandardConstructor {
constructor: JsFunction::empty_intrinsic_function(true),
prototype: JsFunction::empty_intrinsic_function(false).into(),
},
async_function: StandardConstructor::default(),
generator_function: StandardConstructor::default(),
array: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
ObjectData::array(),
)),
bigint: StandardConstructor::default(),
number: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
ObjectData::number(0.0),
)),
boolean: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
ObjectData::boolean(false),
)),
string: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
None,
ObjectData::string("".into()),
)),
regexp: StandardConstructor::default(),
symbol: StandardConstructor::default(),
error: StandardConstructor::default(),
type_error: StandardConstructor::default(),
reference_error: StandardConstructor::default(),
range_error: StandardConstructor::default(),
syntax_error: StandardConstructor::default(),
eval_error: StandardConstructor::default(),
uri_error: StandardConstructor::default(),
aggregate_error: StandardConstructor::default(),
map: StandardConstructor::default(),
set: StandardConstructor::default(),
typed_array: StandardConstructor::default(),
typed_int8_array: StandardConstructor::default(),
typed_uint8_array: StandardConstructor::default(),
typed_uint8clamped_array: StandardConstructor::default(),
typed_int16_array: StandardConstructor::default(),
typed_uint16_array: StandardConstructor::default(),
typed_int32_array: StandardConstructor::default(),
typed_uint32_array: StandardConstructor::default(),
typed_bigint64_array: StandardConstructor::default(),
typed_biguint64_array: StandardConstructor::default(),
typed_float32_array: StandardConstructor::default(),
typed_float64_array: StandardConstructor::default(),
array_buffer: StandardConstructor::default(),
data_view: StandardConstructor::default(),
date_time_format: StandardConstructor::default(),
promise: StandardConstructor::default(),
weak_ref: StandardConstructor::default(),
weak_map: StandardConstructor::default(),
weak_set: StandardConstructor::default(),
#[cfg(feature = "intl")]
collator: StandardConstructor::default(),
#[cfg(feature = "intl")]
list_format: StandardConstructor::default(),
#[cfg(feature = "intl")]
locale: StandardConstructor::default(),
#[cfg(feature = "intl")]
segmenter: StandardConstructor::default(),
}
}
}
impl StandardConstructors {
/// Returns the `AsyncGeneratorFunction` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-asyncgeneratorfunction-constructor
#[inline]
pub const fn async_generator_function(&self) -> &StandardConstructor {
&self.async_generator_function
}
/// Returns the `Object` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-object-constructor
#[inline]
pub const fn object(&self) -> &StandardConstructor {
&self.object
}
/// Returns the `Proxy` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-proxy-constructor
#[inline]
pub const fn proxy(&self) -> &StandardConstructor {
&self.proxy
}
/// Returns the `Date` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-date-constructor
#[inline]
pub const fn date(&self) -> &StandardConstructor {
&self.date
}
/// Returns the `Function` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-function-constructor
#[inline]
pub const fn function(&self) -> &StandardConstructor {
&self.function
}
/// Returns the `AsyncFunction` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-async-function-constructor
#[inline]
pub const fn async_function(&self) -> &StandardConstructor {
&self.async_function
}
/// Returns the `GeneratorFunction` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-generatorfunction-constructor
#[inline]
pub const fn generator_function(&self) -> &StandardConstructor {
&self.generator_function
}
/// Returns the `Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-array-constructor
#[inline]
pub const fn array(&self) -> &StandardConstructor {
&self.array
}
/// Returns the `BigInt` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint-constructor
#[inline]
pub const fn bigint(&self) -> &StandardConstructor {
&self.bigint
}
/// Returns the `Number` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-number-constructor
#[inline]
pub const fn number(&self) -> &StandardConstructor {
&self.number
}
/// Returns the `Boolean` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-boolean-constructor
#[inline]
pub const fn boolean(&self) -> &StandardConstructor {
&self.boolean
}
/// Returns the `String` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-string-constructor
#[inline]
pub const fn string(&self) -> &StandardConstructor {
&self.string
}
/// Returns the `RegExp` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-regexp-constructor
#[inline]
pub const fn regexp(&self) -> &StandardConstructor {
&self.regexp
}
/// Returns the `Symbol` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-symbol-constructor
#[inline]
pub const fn symbol(&self) -> &StandardConstructor {
&self.symbol
}
/// Returns the `Error` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-error-constructor
#[inline]
pub const fn error(&self) -> &StandardConstructor {
&self.error
}
/// Returns the `ReferenceError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-referenceerror
#[inline]
pub const fn reference_error(&self) -> &StandardConstructor {
&self.reference_error
}
/// Returns the `TypeError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-typeerror
#[inline]
pub const fn type_error(&self) -> &StandardConstructor {
&self.type_error
}
/// Returns the `RangeError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-rangeerror
#[inline]
pub const fn range_error(&self) -> &StandardConstructor {
&self.range_error
}
/// Returns the `SyntaxError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-syntaxerror
#[inline]
pub const fn syntax_error(&self) -> &StandardConstructor {
&self.syntax_error
}
/// Returns the `EvalError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-evalerror
#[inline]
pub const fn eval_error(&self) -> &StandardConstructor {
&self.eval_error
}
/// Returns the `URIError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-native-error-types-used-in-this-standard-urierror
#[inline]
pub const fn uri_error(&self) -> &StandardConstructor {
&self.uri_error
}
/// Returns the `AggregateError` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-aggregate-error-constructor
#[inline]
pub const fn aggregate_error(&self) -> &StandardConstructor {
&self.aggregate_error
}
/// Returns the `Map` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-map-constructor
#[inline]
pub const fn map(&self) -> &StandardConstructor {
&self.map
}
/// Returns the `Set` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-set-constructor
#[inline]
pub const fn set(&self) -> &StandardConstructor {
&self.set
}
/// Returns the `TypedArray` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_array(&self) -> &StandardConstructor {
&self.typed_array
}
/// Returns the `Int8Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_int8_array(&self) -> &StandardConstructor {
&self.typed_int8_array
}
/// Returns the `Uint8Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_uint8_array(&self) -> &StandardConstructor {
&self.typed_uint8_array
}
/// Returns the `Uint8ClampedArray` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_uint8clamped_array(&self) -> &StandardConstructor {
&self.typed_uint8clamped_array
}
/// Returns the `Int16Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_int16_array(&self) -> &StandardConstructor {
&self.typed_int16_array
}
/// Returns the `Uint16Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_uint16_array(&self) -> &StandardConstructor {
&self.typed_uint16_array
}
/// Returns the `Uint32Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_uint32_array(&self) -> &StandardConstructor {
&self.typed_uint32_array
}
/// Returns the `Int32Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_int32_array(&self) -> &StandardConstructor {
&self.typed_int32_array
}
/// Returns the `BigInt64Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_bigint64_array(&self) -> &StandardConstructor {
&self.typed_bigint64_array
}
/// Returns the `BigUint64Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_biguint64_array(&self) -> &StandardConstructor {
&self.typed_biguint64_array
}
/// Returns the `Float32Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_float32_array(&self) -> &StandardConstructor {
&self.typed_float32_array
}
/// Returns the `Float64Array` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-typedarray-constructors
#[inline]
pub const fn typed_float64_array(&self) -> &StandardConstructor {
&self.typed_float64_array
}
/// Returns the `ArrayBuffer` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-arraybuffer-constructor
#[inline]
pub const fn array_buffer(&self) -> &StandardConstructor {
&self.array_buffer
}
/// Returns the `DataView` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-dataview-constructor
#[inline]
pub const fn data_view(&self) -> &StandardConstructor {
&self.data_view
}
/// Returns the `Intl.DateTimeFormat` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-intl-datetimeformat-constructor
#[inline]
pub const fn date_time_format(&self) -> &StandardConstructor {
&self.date_time_format
}
/// Returns the `Promise` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-promise-constructor
#[inline]
pub const fn promise(&self) -> &StandardConstructor {
&self.promise
}
/// Returns the `WeakRef` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-weak-ref-constructor
#[inline]
pub const fn weak_ref(&self) -> &StandardConstructor {
&self.weak_ref
}
/// Returns the `WeakMap` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-weakmap-constructor
#[inline]
pub const fn weak_map(&self) -> &StandardConstructor {
&self.weak_map
}
/// Returns the `WeakSet` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-weakset-constructor
#[inline]
pub const fn weak_set(&self) -> &StandardConstructor {
&self.weak_set
}
/// Returns the `Intl.Collator` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-intl.collator
#[inline]
#[cfg(feature = "intl")]
pub const fn collator(&self) -> &StandardConstructor {
&self.collator
}
/// Returns the `Intl.ListFormat` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-Intl.ListFormat
#[inline]
#[cfg(feature = "intl")]
pub const fn list_format(&self) -> &StandardConstructor {
&self.list_format
}
/// Returns the `Intl.Locale` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-Intl.Locale
#[inline]
#[cfg(feature = "intl")]
pub const fn locale(&self) -> &StandardConstructor {
&self.locale
}
/// Returns the `Intl.Segmenter` constructor.
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma402/#sec-intl.segmenter
#[inline]
#[cfg(feature = "intl")]
pub const fn segmenter(&self) -> &StandardConstructor {
&self.segmenter
}
}
/// Cached intrinsic objects
#[derive(Debug, Trace, Finalize)]
pub struct IntrinsicObjects {
/// [`%Reflect%`](https://tc39.es/ecma262/#sec-reflect)
reflect: JsObject,
/// [`%Math%`](https://tc39.es/ecma262/#sec-math)
math: JsObject,
/// [`%JSON%`](https://tc39.es/ecma262/#sec-json)
json: JsObject,
/// [`%ThrowTypeError%`](https://tc39.es/ecma262/#sec-%throwtypeerror%)
throw_type_error: JsFunction,
/// [`%Array.prototype.values%`](https://tc39.es/ecma262/#sec-array.prototype.values)
array_prototype_values: JsFunction,
/// Cached iterator prototypes.
iterator_prototypes: IteratorPrototypes,
/// [`%GeneratorFunction.prototype.prototype%`](https://tc39.es/ecma262/#sec-properties-of-generator-prototype)
generator: JsObject,
/// [`%AsyncGeneratorFunction.prototype.prototype%`](https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-prototype)
async_generator: JsObject,
/// [`%eval%`](https://tc39.es/ecma262/#sec-eval-x)
eval: JsFunction,
/// URI related functions
uri_functions: UriFunctions,
/// [`%isFinite%`](https://tc39.es/ecma262/#sec-isfinite-number)
is_finite: JsFunction,
/// [`%isNaN%`](https://tc39.es/ecma262/#sec-isnan-number)
is_nan: JsFunction,
/// [`%parseFloat%`](https://tc39.es/ecma262/#sec-parsefloat-string)
parse_float: JsFunction,
/// [`%parseInt%`](https://tc39.es/ecma262/#sec-parseint-string-radix)
parse_int: JsFunction,
/// [`%escape%`](https://tc39.es/ecma262/#sec-escape-string)
#[cfg(feature = "annex-b")]
escape: JsFunction,
/// [`%unescape%`](https://tc39.es/ecma262/#sec-unescape-string)
#[cfg(feature = "annex-b")]
unescape: JsFunction,
/// [`%Intl%`](https://tc39.es/ecma402/#intl-object)
#[cfg(feature = "intl")]
intl: JsObject,
/// [`%SegmentsPrototype%`](https://tc39.es/ecma402/#sec-%segmentsprototype%-object)
#[cfg(feature = "intl")]
segments_prototype: JsObject,
}
impl crate::snapshot::Serialize for IntrinsicObjects {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
self.reflect.serialize(s)?;
self.math.serialize(s)?;
self.json.serialize(s)?;
self.throw_type_error.serialize(s)?;
self.array_prototype_values.serialize(s)?;
self.iterator_prototypes.serialize(s)?;
self.generator.serialize(s)?;
self.async_generator.serialize(s)?;
self.eval.serialize(s)?;
self.uri_functions.serialize(s)?;
self.is_finite.serialize(s)?;
self.is_nan.serialize(s)?;
self.parse_float.serialize(s)?;
self.parse_int.serialize(s)?;
#[cfg(feature = "annex-b")]
{
self.escape.serialize(s)?;
self.unescape.serialize(s)?;
}
#[cfg(feature = "intl")]
{
self.intl.serialize(s)?;
self.segments_prototype.serialize(s)?;
}
Ok(())
}
}
impl Default for IntrinsicObjects {
fn default() -> Self {
Self {
reflect: JsObject::default(),
math: JsObject::default(),
json: JsObject::default(),
throw_type_error: JsFunction::empty_intrinsic_function(false),
array_prototype_values: JsFunction::empty_intrinsic_function(false),
iterator_prototypes: IteratorPrototypes::default(),
generator: JsObject::default(),
async_generator: JsObject::default(),
eval: JsFunction::empty_intrinsic_function(false),
uri_functions: UriFunctions::default(),
is_finite: JsFunction::empty_intrinsic_function(false),
is_nan: JsFunction::empty_intrinsic_function(false),
parse_float: JsFunction::empty_intrinsic_function(false),
parse_int: JsFunction::empty_intrinsic_function(false),
#[cfg(feature = "annex-b")]
escape: JsFunction::empty_intrinsic_function(false),
#[cfg(feature = "annex-b")]
unescape: JsFunction::empty_intrinsic_function(false),
#[cfg(feature = "intl")]
intl: JsObject::default(),
#[cfg(feature = "intl")]
segments_prototype: JsObject::default(),
}
}
}
impl IntrinsicObjects {
/// Gets the [`%ThrowTypeError%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-%throwtypeerror%
#[inline]
pub fn throw_type_error(&self) -> JsFunction {
self.throw_type_error.clone()
}
/// Gets the [`%Array.prototype.values%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-array.prototype.values
#[inline]
pub fn array_prototype_values(&self) -> JsFunction {
self.array_prototype_values.clone()
}
/// Gets the cached iterator prototypes.
#[inline]
pub const fn iterator_prototypes(&self) -> &IteratorPrototypes {
&self.iterator_prototypes
}
/// Gets the [`%GeneratorFunction.prototype.prototype%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-generator-objects
#[inline]
pub fn generator(&self) -> JsObject {
self.generator.clone()
}
/// Gets the [`%AsyncGeneratorFunction.prototype.prototype%`] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-asyncgenerator-objects
#[inline]
pub fn async_generator(&self) -> JsObject {
self.async_generator.clone()
}
/// Gets the [`%eval%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-eval-x
pub fn eval(&self) -> JsFunction {
self.eval.clone()
}
/// Gets the URI intrinsic functions.
pub const fn uri_functions(&self) -> &UriFunctions {
&self.uri_functions
}
/// Gets the [`%Reflect%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-reflect
pub fn reflect(&self) -> JsObject {
self.reflect.clone()
}
/// Gets the [`%Math%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-math
pub fn math(&self) -> JsObject {
self.math.clone()
}
/// Gets the [`%JSON%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma262/#sec-json
pub fn json(&self) -> JsObject {
self.json.clone()
}
/// Gets the [`%isFinite%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-isfinite-number
pub fn is_finite(&self) -> JsFunction {
self.is_finite.clone()
}
/// Gets the [`%isNaN%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-isnan-number
pub fn is_nan(&self) -> JsFunction {
self.is_nan.clone()
}
/// Gets the [`%parseFloat%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-parsefloat-string
pub fn parse_float(&self) -> JsFunction {
self.parse_float.clone()
}
/// Gets the [`%parseInt%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-parseint-string-radix
pub fn parse_int(&self) -> JsFunction {
self.parse_int.clone()
}
/// Gets the [`%escape%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-escape-string
#[cfg(feature = "annex-b")]
pub fn escape(&self) -> JsFunction {
self.escape.clone()
}
/// Gets the [`%unescape%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-unescape-string
#[cfg(feature = "annex-b")]
pub fn unescape(&self) -> JsFunction {
self.unescape.clone()
}
/// Gets the [`%Intl%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma402/#intl-object
#[cfg(feature = "intl")]
pub fn intl(&self) -> JsObject {
self.intl.clone()
}
/// Gets the [`%SegmentsPrototype%`][spec] intrinsic object.
///
/// [spec]: https://tc39.es/ecma402/#sec-%segmentsprototype%-object
#[cfg(feature = "intl")]
pub fn segments_prototype(&self) -> JsObject {
self.segments_prototype.clone()
}
}
/// Contains commonly used [`ObjectTemplate`]s.
#[derive(Debug, Trace, Finalize)]
pub(crate) struct ObjectTemplates {
iterator_result: ObjectTemplate,
ordinary_object: ObjectTemplate,
array: ObjectTemplate,
number: ObjectTemplate,
string: ObjectTemplate,
symbol: ObjectTemplate,
bigint: ObjectTemplate,
boolean: ObjectTemplate,
unmapped_arguments: ObjectTemplate,
mapped_arguments: ObjectTemplate,
function_with_prototype: ObjectTemplate,
function_prototype: ObjectTemplate,
function: ObjectTemplate,
async_function: ObjectTemplate,
function_without_proto: ObjectTemplate,
function_with_prototype_without_proto: ObjectTemplate,
namespace: ObjectTemplate,
}
impl crate::snapshot::Serialize for ObjectTemplates {
fn serialize(
&self,
s: &mut crate::snapshot::SnapshotSerializer,
) -> Result<(), crate::snapshot::SnapshotError> {
self.iterator_result.serialize(s)?;
self.ordinary_object.serialize(s)?;
self.array.serialize(s)?;
self.number.serialize(s)?;
self.string.serialize(s)?;
self.symbol.serialize(s)?;
self.bigint.serialize(s)?;
self.boolean.serialize(s)?;
self.unmapped_arguments.serialize(s)?;
self.mapped_arguments.serialize(s)?;
self.function_with_prototype.serialize(s)?;
self.function_prototype.serialize(s)?;
self.function.serialize(s)?;
self.async_function.serialize(s)?;
self.function_without_proto.serialize(s)?;
self.function_with_prototype_without_proto.serialize(s)?;
self.namespace.serialize(s)?;
Ok(())
}
}
impl ObjectTemplates {
pub(crate) fn new(root_shape: &RootShape, constructors: &StandardConstructors) -> Self {
let root_shape = root_shape.shape();
// pre-initialize used shapes.
let ordinary_object =
ObjectTemplate::with_prototype(root_shape, constructors.object().prototype());
let mut array = ObjectTemplate::new(root_shape);
let length_property_key: PropertyKey = "length".into();
array.property(
length_property_key.clone(),
Attribute::WRITABLE | Attribute::PERMANENT | Attribute::NON_ENUMERABLE,
);
array.set_prototype(constructors.array().prototype());
let number = ObjectTemplate::with_prototype(root_shape, constructors.number().prototype());
let symbol = ObjectTemplate::with_prototype(root_shape, constructors.symbol().prototype());
let bigint = ObjectTemplate::with_prototype(root_shape, constructors.bigint().prototype());
let boolean =
ObjectTemplate::with_prototype(root_shape, constructors.boolean().prototype());
let mut string = ObjectTemplate::new(root_shape);
string.property(
length_property_key.clone(),
Attribute::READONLY | Attribute::PERMANENT | Attribute::NON_ENUMERABLE,
);
string.set_prototype(constructors.string().prototype());
let name_property_key: PropertyKey = "name".into();
let mut function = ObjectTemplate::new(root_shape);
function.property(
length_property_key.clone(),
Attribute::READONLY | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
);
function.property(
name_property_key,
Attribute::READONLY | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
);
let function_without_proto = function.clone();
let mut async_function = function.clone();
let mut function_with_prototype = function.clone();
function_with_prototype.property(
PROTOTYPE.into(),
Attribute::WRITABLE | Attribute::PERMANENT | Attribute::NON_ENUMERABLE,
);
let function_with_prototype_without_proto = function_with_prototype.clone();
function.set_prototype(constructors.function().prototype());
function_with_prototype.set_prototype(constructors.function().prototype());
async_function.set_prototype(constructors.async_function().prototype());
let mut function_prototype = ordinary_object.clone();
function_prototype.property(
CONSTRUCTOR.into(),
Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
);
let mut unmapped_arguments = ordinary_object.clone();
// 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len),
// [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
unmapped_arguments.property(
length_property_key,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
);
// 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {
// [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false,
// [[Configurable]]: true }).
unmapped_arguments.property(
JsSymbol::iterator().into(),
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
);
let mut mapped_arguments = unmapped_arguments.clone();
// 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {
// [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false,
// [[Configurable]]: false }).
unmapped_arguments.accessor(
"callee".into(),
true,
true,
Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
);
// 21. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {
// [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
mapped_arguments.property(
"callee".into(),
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
);
let mut iterator_result = ordinary_object.clone();
iterator_result.property(
"value".into(),
Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::ENUMERABLE,
);
iterator_result.property(
"done".into(),
Attribute::WRITABLE | Attribute::CONFIGURABLE | Attribute::ENUMERABLE,
);
let mut namespace = ObjectTemplate::new(root_shape);
namespace.property(JsSymbol::to_string_tag().into(), Attribute::empty());
Self {
iterator_result,
ordinary_object,
array,
number,
string,
symbol,
bigint,
boolean,
unmapped_arguments,
mapped_arguments,
function_with_prototype,
function_prototype,
function,
async_function,
function_without_proto,
function_with_prototype_without_proto,
namespace,
}
}
/// Cached iterator result template.
///
/// Transitions:
///
/// 1. `__proto__`: `Object.prototype`
/// 2. `"done"`: (`WRITABLE`, `CONFIGURABLE`, `ENUMERABLE`)
/// 3. `"value"`: (`WRITABLE`, `CONFIGURABLE`, `ENUMERABLE`)
pub(crate) const fn iterator_result(&self) -> &ObjectTemplate {
&self.iterator_result
}
/// Cached ordinary object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Object.prototype`
pub(crate) const fn ordinary_object(&self) -> &ObjectTemplate {
&self.ordinary_object
}
/// Cached array object template.
///
/// Transitions:
///
/// 1. `"length"`: (`WRITABLE`, `PERMANENT`,`NON_ENUMERABLE`)
/// 2. `__proto__`: `Array.prototype`
pub(crate) const fn array(&self) -> &ObjectTemplate {
&self.array
}
/// Cached number object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Number.prototype`
pub(crate) const fn number(&self) -> &ObjectTemplate {
&self.number
}
/// Cached string object template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `PERMANENT`,`NON_ENUMERABLE`)
/// 2. `__proto__`: `String.prototype`
pub(crate) const fn string(&self) -> &ObjectTemplate {
&self.string
}
/// Cached symbol object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Symbol.prototype`
pub(crate) const fn symbol(&self) -> &ObjectTemplate {
&self.symbol
}
/// Cached bigint object template.
///
/// Transitions:
///
/// 1. `__proto__`: `BigInt.prototype`
pub(crate) const fn bigint(&self) -> &ObjectTemplate {
&self.bigint
}
/// Cached boolean object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Boolean.prototype`
pub(crate) const fn boolean(&self) -> &ObjectTemplate {
&self.boolean
}
/// Cached unmapped arguments object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Object.prototype`
/// 2. `"length"`: (`WRITABLE`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `@@iterator`: (`WRITABLE`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 4. `get/set` `"callee"`: (`NON_ENUMERABLE`, `PERMANENT`)
pub(crate) const fn unmapped_arguments(&self) -> &ObjectTemplate {
&self.unmapped_arguments
}
/// Cached mapped arguments object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Object.prototype`
/// 2. `"length"`: (`WRITABLE`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `@@iterator`: (`WRITABLE`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 4. `"callee"`: (`WRITABLE`, `NON_ENUMERABLE`, `CONFIGURABLE`)
pub(crate) const fn mapped_arguments(&self) -> &ObjectTemplate {
&self.mapped_arguments
}
/// Cached function object with `"prototype"` property template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 2. `"name"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `"prototype"`: (`WRITABLE`, `PERMANENT`, `NON_ENUMERABLE`)
/// 4. `__proto__`: `Function.prototype`
pub(crate) const fn function_with_prototype(&self) -> &ObjectTemplate {
&self.function_with_prototype
}
/// Cached constructor function object template.
///
/// Transitions:
///
/// 1. `__proto__`: `Object.prototype`
/// 2. `"contructor"`: (`WRITABLE`, `CONFIGURABLE`, `NON_ENUMERABLE`)
pub(crate) const fn function_prototype(&self) -> &ObjectTemplate {
&self.function_prototype
}
/// Cached function object property template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 2. `"name"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `__proto__`: `Function.prototype`
pub(crate) const fn function(&self) -> &ObjectTemplate {
&self.function
}
/// Cached function object property template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 2. `"name"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `__proto__`: `AsyncFunction.prototype`
pub(crate) const fn async_function(&self) -> &ObjectTemplate {
&self.async_function
}
/// Cached function object without `__proto__` template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 2. `"name"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
pub(crate) const fn function_without_proto(&self) -> &ObjectTemplate {
&self.function_without_proto
}
/// Cached function object with `"prototype"` and without `__proto__` template.
///
/// Transitions:
///
/// 1. `"length"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 2. `"name"`: (`READONLY`, `NON_ENUMERABLE`, `CONFIGURABLE`)
/// 3. `"prototype"`: (`WRITABLE`, `PERMANENT`, `NON_ENUMERABLE`)
pub(crate) const fn function_with_prototype_without_proto(&self) -> &ObjectTemplate {
&self.function_with_prototype_without_proto
}
/// Cached namespace object template.
///
/// Transitions:
///
/// 1. `@@toStringTag`: (`READONLY`, `NON_ENUMERABLE`, `PERMANENT`)
pub(crate) const fn namespace(&self) -> &ObjectTemplate {
&self.namespace
}
}