-
-
Notifications
You must be signed in to change notification settings - Fork 415
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
17 changed files
with
559 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
name = "boa_builtins" | ||
description = "Builtins of the Boa JavaScript engine." | ||
publish = true | ||
version.workspace = true | ||
edition.workspace = true | ||
authors.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
rust-version.workspace = true | ||
build = "build.rs" | ||
|
||
[dependencies] | ||
bitflags = "2.1.0" | ||
phf = "^0.11.1" | ||
phf_shared = "^0.11.1" | ||
|
||
[build-dependencies] | ||
boa_macros.workspace = true | ||
phf_codegen = "^0.11.1" | ||
phf_shared = "^0.11.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# TOOD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
use std::fs::File; | ||
use std::hash::{Hash, Hasher}; | ||
use std::io::{self, BufWriter, Write}; | ||
use std::path::Path; | ||
use std::{env, fmt}; | ||
|
||
use phf_shared::{FmtConst, PhfBorrow, PhfHash}; | ||
|
||
use boa_macros::utf16; | ||
|
||
/// List of well known symbols. | ||
#[derive(Debug, Clone, Copy)] | ||
#[repr(u8)] | ||
#[allow(dead_code)] | ||
enum WellKnown { | ||
AsyncIterator, | ||
HasInstance, | ||
IsConcatSpreadable, | ||
Iterator, | ||
Match, | ||
MatchAll, | ||
Replace, | ||
Search, | ||
Species, | ||
Split, | ||
ToPrimitive, | ||
ToStringTag, | ||
Unscopables, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
pub enum StaticPropertyKey<'a> { | ||
String(&'a [u16]), | ||
Symbol(u8), | ||
} | ||
|
||
impl PhfHash for StaticPropertyKey<'static> { | ||
#[inline] | ||
fn phf_hash<H: Hasher>(&self, state: &mut H) { | ||
self.hash(state) | ||
} | ||
} | ||
|
||
impl FmtConst for StaticPropertyKey<'static> { | ||
fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
if matches!(self, StaticPropertyKey::String(_)) { | ||
f.write_str("StaticPropertyKey::String(")?; | ||
} else { | ||
f.write_str("StaticPropertyKey::Symbol(")?; | ||
} | ||
|
||
match self { | ||
StaticPropertyKey::String(s) => write!(f, "&{:?})", s), | ||
StaticPropertyKey::Symbol(s) => write!(f, "{})", s), | ||
} | ||
} | ||
} | ||
|
||
impl<'b, 'a: 'b> PhfBorrow<StaticPropertyKey<'b>> for StaticPropertyKey<'a> { | ||
fn borrow(&self) -> &StaticPropertyKey<'b> { | ||
self | ||
} | ||
} | ||
|
||
fn main() -> io::Result<()> { | ||
let file = Path::new(&env::var("OUT_DIR").unwrap()).join("static_shapes_codegen.rs"); | ||
let mut file = BufWriter::new(File::create(file)?); | ||
|
||
// writeln!(&mut file, "\n\n")?; | ||
|
||
writeln!( | ||
&mut file, | ||
"pub static EMPTY_OBJECT_STATIC_SHAPE: ::phf::OrderedMap::<StaticPropertyKey<'static>, (u32, Attribute)> = \n{};", | ||
phf_codegen::OrderedMap::<StaticPropertyKey<'static>>::new() | ||
.build() | ||
)?; | ||
|
||
writeln!( | ||
&mut file, | ||
"pub static JSON_OBJECT_STATIC_SHAPE: ::phf::OrderedMap::<StaticPropertyKey<'static>, (u32, Attribute)> = \n{};", | ||
phf_codegen::OrderedMap::new() | ||
.entry(StaticPropertyKey::String(utf16!("parse")), "(0, Attribute::WRITABLE.union(Attribute::CONFIGURABLE))") | ||
.entry(StaticPropertyKey::String(utf16!("stringify")), "(1, Attribute::WRITABLE.union(Attribute::CONFIGURABLE))") | ||
.entry(StaticPropertyKey::Symbol(WellKnown::ToStringTag as u8), "(2, Attribute::WRITABLE.union(Attribute::CONFIGURABLE))") | ||
.build() | ||
)?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static BYTE_STR_KEYS: ::phf::Map<&[u8], u32> = \n{};", | ||
// phf_codegen::Map::<&[u8]>::new() | ||
// .entry(b"foo", "0") | ||
// .entry(b"bar", "1") | ||
// .entry(b"baz", "2") | ||
// .entry(b"quux4555", "3") | ||
// .build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static SET: ::phf::Set<u32> = \n{};", | ||
// phf_codegen::Set::new() | ||
// .entry(1u32) | ||
// .entry(2u32) | ||
// .entry(3u32) | ||
// .build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static ORDERED_MAP: ::phf::OrderedMap<u32, &'static str> = \n{};", | ||
// phf_codegen::OrderedMap::new() | ||
// .entry(1u32, "\"a\"") | ||
// .entry(2u32, "\"b\"") | ||
// .entry(3u32, "\"c\"") | ||
// .build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static ORDERED_SET: ::phf::OrderedSet<u32> = \n{};", | ||
// phf_codegen::OrderedSet::new() | ||
// .entry(1u32) | ||
// .entry(2u32) | ||
// .entry(3u32) | ||
// .build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static STR_KEYS: ::phf::Map<&'static str, u32> = \n{};", | ||
// phf_codegen::Map::new() | ||
// .entry("a", "1") | ||
// .entry("b", "2") | ||
// .entry("c", "3") | ||
// .build() | ||
// )?; | ||
|
||
// write!( | ||
// &mut file, | ||
// "static UNICASE_MAP: ::phf::Map<::unicase::UniCase<&'static str>, &'static str> = \n{};", | ||
// phf_codegen::Map::new() | ||
// .entry(UniCase::new("abc"), "\"a\"") | ||
// .entry(UniCase::new("DEF"), "\"b\"") | ||
// .build() | ||
// )?; | ||
|
||
// write!( | ||
// &mut file, | ||
// "static UNCASED_MAP: ::phf::Map<&'static ::uncased::UncasedStr, &'static str> = \n{};", | ||
// phf_codegen::Map::new() | ||
// .entry(UncasedStr::new("abc"), "\"a\"") | ||
// .entry(UncasedStr::new("DEF"), "\"b\"") | ||
// .build() | ||
// )?; | ||
|
||
// //u32 is used here purely for a type that impls `Hash+PhfHash+Eq+fmt::Debug`, but is not required for the empty test itself | ||
// writeln!( | ||
// &mut file, | ||
// "static EMPTY: ::phf::Map<u32, u32> = \n{};", | ||
// phf_codegen::Map::<u32>::new().build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static EMPTY_ORDERED: ::phf::OrderedMap<u32, u32> = \n{};", | ||
// phf_codegen::OrderedMap::<u32>::new().build() | ||
// )?; | ||
|
||
// writeln!( | ||
// &mut file, | ||
// "static ARRAY_KEYS: ::phf::Map<[u8; 3], u32> = \n{};", | ||
// phf_codegen::Map::<[u8; 3]>::new() | ||
// .entry(*b"foo", "0") | ||
// .entry(*b"bar", "1") | ||
// .entry(*b"baz", "2") | ||
// .build() | ||
// )?; | ||
|
||
// // key type required here as it will infer `&'static [u8; 3]` instead | ||
// writeln!( | ||
// &mut file, | ||
// "static BYTE_STR_KEYS: ::phf::Map<&[u8], u32> = \n{};", | ||
// phf_codegen::Map::<&[u8]>::new() | ||
// .entry(b"foo", "0") | ||
// .entry(b"bar", "1") | ||
// .entry(b"baz", "2") | ||
// .entry(b"quux", "3") | ||
// .build() | ||
// ) | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use std::hash::{Hash, Hasher}; | ||
|
||
use bitflags::bitflags; | ||
use phf::PhfHash; | ||
use phf_shared::PhfBorrow; | ||
|
||
bitflags! { | ||
/// This struct constains the property flags as described in the ECMAScript specification. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub struct Attribute: u8 { | ||
/// The `Writable` attribute decides whether the value associated with the property can be changed or not, from its initial value. | ||
const WRITABLE = 0b0000_0001; | ||
|
||
/// If the property can be enumerated by a `for-in` loop. | ||
const ENUMERABLE = 0b0000_0010; | ||
|
||
/// If the property descriptor can be changed later. | ||
const CONFIGURABLE = 0b0000_0100; | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub enum StaticPropertyKey<'a> { | ||
String(&'a [u16]), | ||
Symbol(u8), | ||
} | ||
|
||
impl PhfHash for StaticPropertyKey<'static> { | ||
#[inline] | ||
fn phf_hash<H: Hasher>(&self, state: &mut H) { | ||
self.hash(state) | ||
} | ||
} | ||
|
||
impl<'b, 'a: 'b> PhfBorrow<StaticPropertyKey<'b>> for StaticPropertyKey<'a> { | ||
#[inline] | ||
fn borrow(&self) -> &StaticPropertyKey<'b> { | ||
self | ||
} | ||
} | ||
|
||
pub type Slot = (u32, Attribute); | ||
pub type StaticShape = phf::OrderedMap<StaticPropertyKey<'static>, Slot>; | ||
|
||
include!(concat!(env!("OUT_DIR"), "/static_shapes_codegen.rs")); | ||
|
||
// static NUMBER_BUITIN_OBJECT_STATIC_SHAPE_REF: &StaticShape = &NUMBER_BUITIN_OBJECT_STATIC_SHAPE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Temp allow | ||
#![allow(dead_code)] | ||
#![allow(clippy::needless_pass_by_value)] | ||
|
||
use std::fmt::Debug; | ||
|
||
use boa_builtins::StaticPropertyKey; | ||
use boa_gc::{Finalize, Trace}; | ||
|
||
use crate::{property::PropertyKey, symbol::WellKnown, JsSymbol}; | ||
|
||
use super::{ | ||
shared_shape::TransitionKey, slot::SlotAttributes, ChangeTransition, JsPrototype, Shape, Slot, | ||
UniqueShape, | ||
}; | ||
|
||
pub(crate) type StaticShapeInner = &'static boa_builtins::StaticShape; | ||
|
||
/// TODO: doc | ||
fn from_static_property_key(key: &StaticPropertyKey<'_>) -> PropertyKey { | ||
match key { | ||
boa_builtins::StaticPropertyKey::String(s) => PropertyKey::from(*s), | ||
boa_builtins::StaticPropertyKey::Symbol(s) => { | ||
let symbol = match WellKnown::try_from(*s).expect("should be an well known symbol") { | ||
WellKnown::AsyncIterator => JsSymbol::async_iterator(), | ||
WellKnown::HasInstance => JsSymbol::has_instance(), | ||
WellKnown::IsConcatSpreadable => JsSymbol::is_concat_spreadable(), | ||
WellKnown::Iterator => JsSymbol::iterator(), | ||
WellKnown::Match => JsSymbol::r#match(), | ||
WellKnown::MatchAll => JsSymbol::match_all(), | ||
WellKnown::Replace => JsSymbol::replace(), | ||
WellKnown::Search => JsSymbol::search(), | ||
WellKnown::Species => JsSymbol::species(), | ||
WellKnown::Split => JsSymbol::split(), | ||
WellKnown::ToPrimitive => JsSymbol::to_primitive(), | ||
WellKnown::ToStringTag => JsSymbol::to_string_tag(), | ||
WellKnown::Unscopables => JsSymbol::unscopables(), | ||
}; | ||
|
||
PropertyKey::Symbol(symbol) | ||
} | ||
} | ||
} | ||
|
||
/// TODO: doc | ||
fn to_static_property_key(key: &PropertyKey) -> Option<StaticPropertyKey<'_>> { | ||
match key { | ||
PropertyKey::String(s) => Some(StaticPropertyKey::String(s.as_slice())), | ||
PropertyKey::Symbol(s) => Some(StaticPropertyKey::Symbol(s.hash().try_into().ok()?)), | ||
PropertyKey::Index(_) => None, | ||
} | ||
} | ||
|
||
/// Represents a [`Shape`] that is not shared with any other object. | ||
/// | ||
/// This is useful for objects that are inherently unique like, | ||
/// the builtin object. | ||
/// | ||
/// Cloning this does a shallow clone. | ||
#[derive(Debug, Clone, Trace, Finalize)] | ||
pub(crate) struct StaticShape { | ||
inner: StaticShapeInner, | ||
} | ||
|
||
impl StaticShape { | ||
/// Create a new [`UniqueShape`]. | ||
pub(crate) const fn new(inner: StaticShapeInner) -> Self { | ||
Self { inner } | ||
} | ||
|
||
/// Inserts a new property into the [`UniqueShape`]. | ||
pub(crate) fn insert_property_transition(&self, _key: TransitionKey) -> UniqueShape { | ||
todo!() | ||
} | ||
|
||
/// Remove a property from the [`UniqueShape`]. | ||
/// | ||
/// This will cause the current shape to be invalidated, and a new [`UniqueShape`] will be returned. | ||
pub(crate) fn remove_property_transition(&self, _key: &PropertyKey) -> UniqueShape { | ||
todo!() | ||
} | ||
|
||
/// Does a property lookup on the [`UniqueShape`] returning the [`Slot`] where it's | ||
/// located or [`None`] otherwise. | ||
pub(crate) fn lookup(&self, key: &PropertyKey) -> Option<Slot> { | ||
let key = to_static_property_key(key)?; | ||
|
||
// SAFETY: only used to extend the lifetime, so we are able to call get. | ||
let key: &StaticPropertyKey<'static> = unsafe { std::mem::transmute(&key) }; | ||
let (index, attributes) = self.inner.get(key)?; | ||
|
||
Some(Slot { | ||
index: *index, | ||
attributes: SlotAttributes::from_bits_retain(attributes.bits()), | ||
}) | ||
} | ||
|
||
/// Change the attributes of a property from the [`UniqueShape`]. | ||
/// | ||
/// This will cause the current shape to be invalidated, and a new [`UniqueShape`] will be returned. | ||
/// | ||
/// NOTE: This assumes that the property had already been inserted. | ||
pub(crate) fn change_attributes_transition( | ||
&self, | ||
_key: &TransitionKey, | ||
) -> ChangeTransition<Shape> { | ||
todo!() | ||
} | ||
|
||
/// Change the prototype of the [`UniqueShape`]. | ||
/// | ||
/// This will cause the current shape to be invalidated, and a new [`UniqueShape`] will be returned. | ||
pub(crate) fn change_prototype_transition(&self, _prototype: JsPrototype) -> UniqueShape { | ||
todo!() | ||
} | ||
|
||
/// Gets all keys first strings then symbols in creation order. | ||
pub(crate) fn keys(&self) -> Vec<PropertyKey> { | ||
self.inner.keys().map(from_static_property_key).collect() | ||
} | ||
|
||
/// TODO: doc | ||
pub(crate) fn to_unique(&self, _prototype: JsPrototype) -> UniqueShape { | ||
// UniqueShape::new( | ||
// prototype, | ||
// self.property_table() | ||
// .inner() | ||
// .borrow() | ||
// .clone_count(self.property_count()), | ||
// ) | ||
todo!() | ||
} | ||
|
||
/// Return location in memory of the [`UniqueShape`]. | ||
pub(crate) fn to_addr_usize(&self) -> usize { | ||
let ptr: *const _ = self.inner; | ||
ptr as usize | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters