diff --git a/Cargo.lock b/Cargo.lock
index 6515de884b8..5655cad8430 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -370,6 +370,17 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "boa_builtins"
+version = "0.16.0"
+dependencies = [
+ "bitflags 2.3.1",
+ "boa_macros",
+ "phf",
+ "phf_codegen",
+ "phf_shared",
+]
+
 [[package]]
 name = "boa_cli"
 version = "0.16.0"
@@ -396,6 +407,7 @@ version = "0.16.0"
 dependencies = [
  "bitflags 2.3.1",
  "boa_ast",
+ "boa_builtins",
  "boa_gc",
  "boa_icu_provider",
  "boa_interner",
@@ -3014,6 +3026,16 @@ dependencies = [
  "phf_shared",
 ]
 
+[[package]]
+name = "phf_codegen"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
 [[package]]
 name = "phf_generator"
 version = "0.11.1"
diff --git a/Cargo.toml b/Cargo.toml
index d47cb01a06e..c31054aeb72 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
 [workspace]
 members = [
     "boa_ast",
+    "boa_builtins",
     "boa_cli",
     "boa_engine",
     "boa_examples",
@@ -28,6 +29,7 @@ description = "Boa is a Javascript lexer, parser and compiler written in Rust. C
 
 [workspace.dependencies]
 boa_ast = { version = "0.16.0", path = "boa_ast" }
+boa_builtins = { version = "0.16.0", path = "boa_builtins" }
 boa_engine = { version = "0.16.0", path = "boa_engine" }
 boa_gc = { version = "0.16.0", path = "boa_gc" }
 boa_icu_provider = { version = "0.16.0", path = "boa_icu_provider" }
diff --git a/boa_builtins/Cargo.toml b/boa_builtins/Cargo.toml
new file mode 100644
index 00000000000..099b7df8271
--- /dev/null
+++ b/boa_builtins/Cargo.toml
@@ -0,0 +1,25 @@
+[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"
+
+[features]
+annex-b = []
+
+[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"
+bitflags = "2.1.0"
diff --git a/boa_builtins/README.md b/boa_builtins/README.md
new file mode 100644
index 00000000000..29b26df1359
--- /dev/null
+++ b/boa_builtins/README.md
@@ -0,0 +1 @@
+# TOOD
diff --git a/boa_builtins/build.rs b/boa_builtins/build.rs
new file mode 100644
index 00000000000..d0046363d87
--- /dev/null
+++ b/boa_builtins/build.rs
@@ -0,0 +1,1530 @@
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::fmt::Debug;
+use std::fs::File;
+use std::hash::{Hash, Hasher};
+use std::io::{self, BufWriter, Write};
+use std::path::Path;
+use std::{env, fmt};
+
+use bitflags::bitflags;
+use phf_shared::{FmtConst, PhfBorrow, PhfHash};
+
+use boa_macros::utf16;
+
+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;
+
+        const GET = 0b0000_1000;
+        const SET = 0b0001_0000;
+    }
+}
+
+/// 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,
+}
+
+pub struct EncodedStaticPropertyKey(u16);
+
+impl EncodedStaticPropertyKey {
+    #[inline]
+    pub fn decode(&self) -> StaticPropertyKey {
+        let value = self.0 >> 1;
+        if self.0 & 1 == 0 {
+            StaticPropertyKey::String(value)
+        } else {
+            StaticPropertyKey::Symbol(value as u8)
+        }
+    }
+}
+
+const fn string(index: u16) -> EncodedStaticPropertyKey {
+    debug_assert!(index < 2u16.pow(15));
+
+    EncodedStaticPropertyKey(index << 1)
+}
+
+const fn symbol(index: u8) -> EncodedStaticPropertyKey {
+    EncodedStaticPropertyKey(((index as u16) << 1) | 1)
+}
+
+impl Debug for EncodedStaticPropertyKey {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.decode().fmt(f)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum StaticPropertyKey {
+    String(u16),
+    Symbol(u8),
+}
+
+impl StaticPropertyKey {
+    #[inline]
+    pub fn encode(self) -> EncodedStaticPropertyKey {
+        match self {
+            StaticPropertyKey::String(x) => string(x),
+            StaticPropertyKey::Symbol(x) => symbol(x),
+        }
+    }
+}
+
+impl Debug for StaticPropertyKey {
+    #[inline]
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match *self {
+            StaticPropertyKey::String(index) => {
+                let string = RAW_STATICS[index as usize];
+                let string = String::from_utf16_lossy(string);
+                write!(f, "String(\"{string}\")")
+            }
+            StaticPropertyKey::Symbol(symbol) => {
+                write!(f, "Symbol({symbol})")
+            }
+        }
+    }
+}
+
+impl Eq for EncodedStaticPropertyKey {}
+
+impl PartialEq for EncodedStaticPropertyKey {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl Hash for EncodedStaticPropertyKey {
+    #[inline]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
+impl PhfHash for EncodedStaticPropertyKey {
+    #[inline]
+    fn phf_hash<H: Hasher>(&self, state: &mut H) {
+        self.hash(state)
+    }
+}
+
+impl PhfBorrow<EncodedStaticPropertyKey> for EncodedStaticPropertyKey {
+    #[inline]
+    fn borrow(&self) -> &EncodedStaticPropertyKey {
+        self
+    }
+}
+
+impl FmtConst for EncodedStaticPropertyKey {
+    #[inline]
+    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let key = self.decode();
+        if matches!(key, StaticPropertyKey::String { .. }) {
+            f.write_str("string(")?;
+        } else {
+            f.write_str("symbol(")?;
+        }
+
+        match key {
+            StaticPropertyKey::String(index) => {
+                write!(
+                    f,
+                    "/* */ {index})",
+                    // String::from_utf16_lossy(value),
+                )
+            }
+            StaticPropertyKey::Symbol(s) => write!(f, "{})", s),
+        }
+    }
+}
+
+trait ToPropertyKey {
+    fn to_property_key(self, _context: &Context) -> StaticPropertyKey;
+}
+
+impl ToPropertyKey for &'static [u16] {
+    fn to_property_key(self, context: &Context) -> StaticPropertyKey {
+        let index = context.insert_or_get(self);
+        StaticPropertyKey::String(index)
+    }
+}
+
+impl ToPropertyKey for WellKnown {
+    fn to_property_key(self, _context: &Context) -> StaticPropertyKey {
+        StaticPropertyKey::Symbol(self as u8)
+    }
+}
+
+#[allow(clippy::type_complexity)]
+struct Context {
+    strings: RefCell<(HashMap<&'static [u16], u16>, Vec<&'static [u16]>)>,
+}
+
+impl Context {
+    fn new() -> Self {
+        Self {
+            strings: RefCell::default(),
+        }
+    }
+
+    fn insert_or_get(&self, value: &'static [u16]) -> u16 {
+        let mut strings = self.strings.borrow_mut();
+        if let Some(index) = strings.0.get(value) {
+            return *index;
+        }
+        let index = strings.1.len();
+        debug_assert!(index < u16::MAX as usize);
+        let index = index as u16;
+
+        strings.0.insert(value, index);
+        strings.1.push(value);
+
+        index
+    }
+
+    fn build(&self, file: &mut BufWriter<File>) -> io::Result<()> {
+        let strings = self.strings.borrow();
+
+        let len = strings.1.len();
+
+        writeln!(file, "\npub const RAW_STATICS: &[&[u16]; {len}] = &[")?;
+        for string in &strings.1 {
+            writeln!(
+                file,
+                "    /* {} */ &{:?},",
+                String::from_utf16_lossy(string),
+                string
+            )?;
+        }
+        writeln!(file, "];")?;
+        Ok(())
+    }
+}
+
+struct BuiltInBuilder<'a> {
+    context: &'a Context,
+    name: &'static str,
+    map: phf_codegen::OrderedMap<EncodedStaticPropertyKey>,
+    prototype: Option<&'static str>,
+
+    slot_index: usize,
+}
+
+impl<'a> BuiltInBuilder<'a> {
+    fn new(context: &'a Context, name: &'static str) -> Self {
+        Self {
+            context,
+            name,
+            map: phf_codegen::OrderedMap::new(),
+            prototype: None,
+            slot_index: 0,
+        }
+    }
+
+    fn inherits(&mut self, prototype: &'static str) -> &mut Self {
+        self.prototype = Some(prototype);
+        self
+    }
+
+    fn method<K>(&mut self, key: K) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        let key = key.to_property_key(self.context).encode();
+        let attributes = Attribute::WRITABLE | Attribute::CONFIGURABLE;
+        self.map.entry(
+            key,
+            &format!(
+                "({}, Attribute::from_bits_retain({}))",
+                self.slot_index,
+                attributes.bits()
+            ),
+        );
+        self.slot_index += 1;
+        self
+    }
+
+    fn accessor<K>(&mut self, key: K, mut attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        // TODO: should they always be set?
+        attributes |= Attribute::GET;
+        attributes |= Attribute::SET;
+
+        let key = key.to_property_key(self.context).encode();
+        self.map.entry(
+            key,
+            &format!(
+                "({}, Attribute::from_bits_retain({}))",
+                self.slot_index,
+                attributes.bits()
+            ),
+        );
+        self.slot_index += 2;
+        self
+    }
+
+    fn property<K>(&mut self, key: K, attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        assert!(!attributes.contains(Attribute::GET) && !attributes.contains(Attribute::SET));
+
+        let key = key.to_property_key(self.context).encode();
+        self.map.entry(
+            key,
+            &format!(
+                "({}, Attribute::from_bits_retain({}))",
+                self.slot_index,
+                attributes.bits()
+            ),
+        );
+        self.slot_index += 1;
+        self
+    }
+
+    fn build(&mut self, file: &mut BufWriter<File>) -> io::Result<&'static str> {
+        let prototype = if let Some(prototype) = self.prototype {
+            format!("Some(&'static {})", prototype)
+        } else {
+            "None".into()
+        };
+        writeln!(
+            file,
+            "pub static {}_STATIC_SHAPE: StaticShape = StaticShape {{\n    storage_len: {},\n    prototype: {},\n    property_table: {} }};",
+            self.name,
+            self.slot_index + 1,
+            prototype,
+            self.map.build(),
+        )?;
+
+        Ok(self.name)
+    }
+}
+
+struct BuiltInBuilderConstructor<'a> {
+    object: BuiltInBuilder<'a>,
+    prototype: BuiltInBuilder<'a>,
+}
+
+impl<'a> BuiltInBuilderConstructor<'a> {
+    fn new(context: &'a Context, name: &'static str) -> Self {
+        Self::with_constructor_attributes(
+            context,
+            name,
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+    }
+
+    fn with_constructor_attributes(
+        context: &'a Context,
+        name: &'static str,
+        constructor_attributes: Attribute,
+    ) -> Self {
+        let object_name = Box::leak(format!("{name}_CONSTRUCTOR").into_boxed_str());
+        let prototype_name = Box::leak(format!("{name}_PROTOTYPE").into_boxed_str());
+        let mut this = Self {
+            object: BuiltInBuilder::new(context, object_name),
+            prototype: BuiltInBuilder::new(context, prototype_name),
+        };
+
+        this.object
+            .property(utf16!("length"), Attribute::CONFIGURABLE);
+        this.object
+            .property(utf16!("name"), Attribute::CONFIGURABLE);
+        this.object
+            .property(utf16!("prototype"), Attribute::empty());
+
+        this.prototype
+            .property(utf16!("constructor"), constructor_attributes);
+
+        this
+    }
+
+    fn inherits(&mut self, prototype: &'static str) -> &mut Self {
+        self.object.inherits(prototype);
+        self
+    }
+
+    fn method<K>(&mut self, key: K) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.prototype.method(key);
+        self
+    }
+
+    fn static_method<K>(&mut self, key: K) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.object.method(key);
+        self
+    }
+
+    fn accessor<K>(&mut self, key: K, attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.prototype.accessor(key, attributes);
+        self
+    }
+
+    fn static_accessor<K>(&mut self, key: K, attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.object.accessor(key, attributes);
+        self
+    }
+
+    fn static_property<K>(&mut self, key: K, attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.object.property(key, attributes);
+        self
+    }
+
+    fn property<K>(&mut self, key: K, attributes: Attribute) -> &mut Self
+    where
+        K: ToPropertyKey,
+    {
+        self.prototype.property(key, attributes);
+        self
+    }
+
+    fn build(&mut self, file: &mut BufWriter<File>) -> io::Result<()> {
+        self.object.build(file)?;
+        self.prototype.build(file)?;
+
+        Ok(())
+    }
+}
+
+fn main() -> io::Result<()> {
+    // TODO: split into separate files
+    // TODO: Move common parts between build and lib.rs into common.rs file.
+
+    // TODO: because the generated static shapes for builtin file does not change that often and it's not that big,
+    //       it's kept as rust source code which changes only in certain places when a property is added or removed.
+    //       We could properly cache this into the git history, to avoid generating it on a fresh build.
+    //       (even though it's fast to build).
+
+    let file = Path::new(&env::var("OUT_DIR").unwrap()).join("static_shapes_codegen.rs");
+    let file = &mut BufWriter::new(File::create(file)?);
+
+    let context = Context::new();
+
+    for string in RAW_STATICS {
+        context.insert_or_get(string);
+    }
+
+    BuiltInBuilder::new(&context, "EMPTY_OBJECT").build(file)?;
+
+    BuiltInBuilder::new(&context, "JSON_OBJECT")
+        .method(utf16!("parse"))
+        .method(utf16!("stringify"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "MATH_OBJECT")
+        .property(utf16!("E"), Attribute::empty())
+        .property(utf16!("LN10"), Attribute::empty())
+        .property(utf16!("LN2"), Attribute::empty())
+        .property(utf16!("LOG10E"), Attribute::empty())
+        .property(utf16!("LOG2E"), Attribute::empty())
+        .property(utf16!("PI"), Attribute::empty())
+        .property(utf16!("SQRT1_2"), Attribute::empty())
+        .property(utf16!("SQRT2"), Attribute::empty())
+        .method(utf16!("abs"))
+        .method(utf16!("acos"))
+        .method(utf16!("acosh"))
+        .method(utf16!("asin"))
+        .method(utf16!("asinh"))
+        .method(utf16!("atan"))
+        .method(utf16!("atanh"))
+        .method(utf16!("atan2"))
+        .method(utf16!("cbrt"))
+        .method(utf16!("ceil"))
+        .method(utf16!("clz32"))
+        .method(utf16!("cos"))
+        .method(utf16!("cosh"))
+        .method(utf16!("exp"))
+        .method(utf16!("expm1"))
+        .method(utf16!("floor"))
+        .method(utf16!("fround"))
+        .method(utf16!("hypot"))
+        .method(utf16!("imul"))
+        .method(utf16!("log"))
+        .method(utf16!("log1p"))
+        .method(utf16!("log10"))
+        .method(utf16!("log2"))
+        .method(utf16!("max"))
+        .method(utf16!("min"))
+        .method(utf16!("pow"))
+        .method(utf16!("random"))
+        .method(utf16!("round"))
+        .method(utf16!("sign"))
+        .method(utf16!("sin"))
+        .method(utf16!("sinh"))
+        .method(utf16!("sqrt"))
+        .method(utf16!("tan"))
+        .method(utf16!("tanh"))
+        .method(utf16!("trunc"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "REFLECT_OBJECT")
+        .method(utf16!("apply"))
+        .method(utf16!("construct"))
+        .method(utf16!("defineProperty"))
+        .method(utf16!("deleteProperty"))
+        .method(utf16!("get"))
+        .method(utf16!("getOwnPropertyDescriptor"))
+        .method(utf16!("getPrototypeOf"))
+        .method(utf16!("has"))
+        .method(utf16!("isExtensible"))
+        .method(utf16!("ownKeys"))
+        .method(utf16!("preventExtensions"))
+        .method(utf16!("set"))
+        .method(utf16!("setPrototypeOf"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "OBJECT")
+        .accessor(utf16!("__proto__"), Attribute::CONFIGURABLE)
+        .method(utf16!("hasOwnProperty"))
+        .method(utf16!("propertyIsEnumerable"))
+        .method(utf16!("toString"))
+        .method(utf16!("toLocaleString"))
+        .method(utf16!("valueOf"))
+        .method(utf16!("isPrototypeOf"))
+        .method(utf16!("__defineGetter__"))
+        .method(utf16!("__defineSetter__"))
+        .method(utf16!("__lookupGetter__"))
+        .method(utf16!("__lookupSetter__"))
+        .static_method(utf16!("create"))
+        .static_method(utf16!("setPrototypeOf"))
+        .static_method(utf16!("getPrototypeOf"))
+        .static_method(utf16!("defineProperty"))
+        .static_method(utf16!("defineProperties"))
+        .static_method(utf16!("assign"))
+        .static_method(utf16!("is"))
+        .static_method(utf16!("keys"))
+        .static_method(utf16!("values"))
+        .static_method(utf16!("entries"))
+        .static_method(utf16!("seal"))
+        .static_method(utf16!("isSealed"))
+        .static_method(utf16!("freeze"))
+        .static_method(utf16!("isFrozen"))
+        .static_method(utf16!("preventExtensions"))
+        .static_method(utf16!("isExtensible"))
+        .static_method(utf16!("getOwnPropertyDescriptor"))
+        .static_method(utf16!("getOwnPropertyDescriptors"))
+        .static_method(utf16!("getOwnPropertyNames"))
+        .static_method(utf16!("getOwnPropertySymbols"))
+        .static_method(utf16!("hasOwn"))
+        .static_method(utf16!("fromEntries"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "FUNCTION")
+        .property(utf16!("length"), Attribute::CONFIGURABLE)
+        .property(utf16!("name"), Attribute::CONFIGURABLE)
+        .method(utf16!("apply"))
+        .method(utf16!("bind"))
+        .method(utf16!("call"))
+        .method(utf16!("toString"))
+        .property(WellKnown::HasInstance, Attribute::empty())
+        .accessor(utf16!("caller"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("arguments"), Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "ARRAY")
+        .property(utf16!("length"), Attribute::WRITABLE)
+        .property(
+            utf16!("values"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(
+            WellKnown::Iterator,
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(WellKnown::Unscopables, Attribute::CONFIGURABLE)
+        .method(utf16!("at"))
+        .method(utf16!("concat"))
+        .method(utf16!("push"))
+        .method(utf16!("indexOf"))
+        .method(utf16!("lastIndexOf"))
+        .method(utf16!("includes"))
+        .method(utf16!("map"))
+        .method(utf16!("fill"))
+        .method(utf16!("forEach"))
+        .method(utf16!("filter"))
+        .method(utf16!("pop"))
+        .method(utf16!("join"))
+        .method(utf16!("toString"))
+        .method(utf16!("reverse"))
+        .method(utf16!("shift"))
+        .method(utf16!("unshift"))
+        .method(utf16!("every"))
+        .method(utf16!("find"))
+        .method(utf16!("findIndex"))
+        .method(utf16!("findLast"))
+        .method(utf16!("findLastIndex"))
+        .method(utf16!("flat"))
+        .method(utf16!("flatMap"))
+        .method(utf16!("slice"))
+        .method(utf16!("some"))
+        .method(utf16!("sort"))
+        .method(utf16!("splice"))
+        .method(utf16!("toLocaleString"))
+        .method(utf16!("reduce"))
+        .method(utf16!("reduceRight"))
+        .method(utf16!("keys"))
+        .method(utf16!("entries"))
+        .method(utf16!("copyWithin"))
+        // Static properties
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .static_method(utf16!("from"))
+        .static_method(utf16!("isArray"))
+        .static_method(utf16!("of"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "DATE")
+        .static_method(utf16!("now"))
+        .static_method(utf16!("parse"))
+        .static_method(utf16!("UTC"))
+        .method(utf16!("getDate"))
+        .method(utf16!("getDay"))
+        .method(utf16!("getFullYear"))
+        .method(utf16!("getHours"))
+        .method(utf16!("getMilliseconds"))
+        .method(utf16!("getMinutes"))
+        .method(utf16!("getMonth"))
+        .method(utf16!("getSeconds"))
+        .method(utf16!("getTime"))
+        .method(utf16!("getTimezoneOffset"))
+        .method(utf16!("getUTCDate"))
+        .method(utf16!("getUTCDay"))
+        .method(utf16!("getUTCFullYear"))
+        .method(utf16!("getUTCHours"))
+        .method(utf16!("getUTCMilliseconds"))
+        .method(utf16!("getUTCMinutes"))
+        .method(utf16!("getUTCMonth"))
+        .method(utf16!("getUTCSeconds"))
+        .method(utf16!("getYear"))
+        .method(utf16!("setDate"))
+        .method(utf16!("setFullYear"))
+        .method(utf16!("setHours"))
+        .method(utf16!("setMilliseconds"))
+        .method(utf16!("setMinutes"))
+        .method(utf16!("setMonth"))
+        .method(utf16!("setSeconds"))
+        .method(utf16!("setTime"))
+        .method(utf16!("setUTCDate"))
+        .method(utf16!("setUTCFullYear"))
+        .method(utf16!("setUTCHours"))
+        .method(utf16!("setUTCMilliseconds"))
+        .method(utf16!("setUTCMinutes"))
+        .method(utf16!("setUTCMonth"))
+        .method(utf16!("setUTCSeconds"))
+        .method(utf16!("setYear"))
+        .method(utf16!("toDateString"))
+        .method(utf16!("toISOString"))
+        .method(utf16!("toJSON"))
+        .method(utf16!("toLocaleDateString"))
+        .method(utf16!("toLocaleString"))
+        .method(utf16!("toLocaleTimeString"))
+        .method(utf16!("toString"))
+        .method(utf16!("toTimeString"))
+        .method(utf16!("valueOf"))
+        .property(
+            utf16!("toGMTString"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(
+            utf16!("toUTCString"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(WellKnown::ToPrimitive, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "NUMBER")
+        .static_property(utf16!("EPSILON"), Attribute::empty())
+        .static_property(utf16!("MAX_SAFE_INTEGER"), Attribute::empty())
+        .static_property(utf16!("MIN_SAFE_INTEGER"), Attribute::empty())
+        .static_property(utf16!("MAX_VALUE"), Attribute::empty())
+        .static_property(utf16!("MIN_VALUE"), Attribute::empty())
+        .static_property(utf16!("NEGATIVE_INFINITY"), Attribute::empty())
+        .static_property(utf16!("POSITIVE_INFINITY"), Attribute::empty())
+        .static_property(utf16!("NaN"), Attribute::empty())
+        .static_property(
+            utf16!("parseInt"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .static_property(
+            utf16!("parseFloat"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .static_method(utf16!("isFinite"))
+        .static_method(utf16!("isNaN"))
+        .static_method(utf16!("isSafeInteger"))
+        .static_method(utf16!("isInteger"))
+        .method(utf16!("toExponential"))
+        .method(utf16!("toFixed"))
+        .method(utf16!("toLocaleString"))
+        .method(utf16!("toPrecision"))
+        .method(utf16!("toString"))
+        .method(utf16!("valueOf"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "BOOLEAN")
+        .method(utf16!("toString"))
+        .method(utf16!("valueOf"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "BIGINT")
+        .method(utf16!("toString"))
+        .method(utf16!("valueOf"))
+        .static_method(utf16!("asIntN"))
+        .static_method(utf16!("asUintN"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "SYMBOL")
+        .static_method(utf16!("for"))
+        .static_method(utf16!("keyFor"))
+        .static_property(utf16!("asyncIterator"), Attribute::empty())
+        .static_property(utf16!("hasInstance"), Attribute::empty())
+        .static_property(utf16!("isConcatSpreadable"), Attribute::empty())
+        .static_property(utf16!("iterator"), Attribute::empty())
+        .static_property(utf16!("match"), Attribute::empty())
+        .static_property(utf16!("matchAll"), Attribute::empty())
+        .static_property(utf16!("replace"), Attribute::empty())
+        .static_property(utf16!("search"), Attribute::empty())
+        .static_property(utf16!("species"), Attribute::empty())
+        .static_property(utf16!("split"), Attribute::empty())
+        .static_property(utf16!("toPrimitive"), Attribute::empty())
+        .static_property(utf16!("toStringTag"), Attribute::empty())
+        .static_property(utf16!("unscopables"), Attribute::empty())
+        .method(utf16!("toString"))
+        .method(utf16!("valueOf"))
+        .accessor(utf16!("description"), Attribute::CONFIGURABLE)
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .property(WellKnown::ToPrimitive, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    let mut builder = BuiltInBuilderConstructor::new(&context, "STRING");
+    builder
+        .property(utf16!("length"), Attribute::empty())
+        .property(
+            utf16!("trimStart"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(
+            utf16!("trimEnd"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .static_method(utf16!("raw"))
+        .static_method(utf16!("fromCharCode"))
+        .static_method(utf16!("fromCodePoint"))
+        .method(utf16!("charAt"))
+        .method(utf16!("charCodeAt"))
+        .method(utf16!("codePointAt"))
+        .method(utf16!("toString"))
+        .method(utf16!("concat"))
+        .method(utf16!("repeat"))
+        .method(utf16!("slice"))
+        .method(utf16!("startsWith"))
+        .method(utf16!("endsWith"))
+        .method(utf16!("includes"))
+        .method(utf16!("indexOf"))
+        .method(utf16!("lastIndexOf"))
+        .method(utf16!("localeCompare"))
+        .method(utf16!("match"))
+        .method(utf16!("normalize"))
+        .method(utf16!("padEnd"))
+        .method(utf16!("padStart"))
+        .method(utf16!("trim"))
+        .method(utf16!("toLowerCase"))
+        .method(utf16!("toUpperCase"))
+        .method(utf16!("toLocaleLowerCase"))
+        .method(utf16!("toLocaleUpperCase"))
+        .method(utf16!("substring"))
+        .method(utf16!("split"))
+        .method(utf16!("valueOf"))
+        .method(utf16!("matchAll"))
+        .method(utf16!("replace"))
+        .method(utf16!("replaceAll"))
+        .method(WellKnown::Iterator)
+        .method(utf16!("search"))
+        .method(utf16!("at"));
+
+    #[cfg(feature = "annex-b")]
+    {
+        builder
+            .property(
+                utf16!("trimLeft"),
+                Attribute::WRITABLE | Attribute::CONFIGURABLE,
+            )
+            .property(
+                utf16!("trimRight"),
+                Attribute::WRITABLE | Attribute::CONFIGURABLE,
+            )
+            .method(utf16!("substr"))
+            .method(utf16!("anchor"))
+            .method(utf16!("big"))
+            .method(utf16!("blink"))
+            .method(utf16!("bold"))
+            .method(utf16!("fixed"))
+            .method(utf16!("fontcolor"))
+            .method(utf16!("fontsize"))
+            .method(utf16!("italics"))
+            .method(utf16!("link"))
+            .method(utf16!("small"))
+            .method(utf16!("strike"))
+            .method(utf16!("sub"))
+            .method(utf16!("sup"));
+    }
+    builder.build(file)?;
+
+    let mut regexp = BuiltInBuilderConstructor::new(&context, "REGEXP");
+    regexp
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .property(
+            utf16!("lastIndex"),
+            Attribute::WRITABLE | Attribute::ENUMERABLE | Attribute::CONFIGURABLE,
+        )
+        .method(utf16!("test"))
+        .method(utf16!("exec"))
+        .method(utf16!("toString"))
+        .method(WellKnown::Match)
+        .method(WellKnown::MatchAll)
+        .method(WellKnown::Replace)
+        .method(WellKnown::Search)
+        .method(WellKnown::Split)
+        .accessor(utf16!("hasIndices"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("global"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("ignoreCase"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("multiline"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("dotAll"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("unicode"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("sticky"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("flags"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("source"), Attribute::CONFIGURABLE);
+
+    #[cfg(feature = "annex-b")]
+    regexp.method(utf16!("compile"));
+
+    regexp.build(file)?;
+
+    let attribute = Attribute::WRITABLE | Attribute::CONFIGURABLE;
+    BuiltInBuilderConstructor::new(&context, "ERROR")
+        .property(utf16!("name"), attribute)
+        .property(utf16!("message"), attribute)
+        .method(utf16!("toString"))
+        .build(file)?;
+
+    let attribute = Attribute::WRITABLE | Attribute::CONFIGURABLE;
+    BuiltInBuilderConstructor::new(&context, "NATIVE_ERROR")
+        .property(utf16!("name"), attribute)
+        .property(utf16!("message"), attribute)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "MAP")
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .property(
+            utf16!("entries"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(
+            WellKnown::Iterator,
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .method(utf16!("clear"))
+        .method(utf16!("delete"))
+        .method(utf16!("forEach"))
+        .method(utf16!("get"))
+        .method(utf16!("has"))
+        .method(utf16!("keys"))
+        .method(utf16!("set"))
+        .method(utf16!("values"))
+        .accessor(utf16!("size"), Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "SET")
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .method(utf16!("add"))
+        .method(utf16!("clear"))
+        .method(utf16!("delete"))
+        .method(utf16!("entries"))
+        .method(utf16!("forEach"))
+        .method(utf16!("has"))
+        .property(
+            utf16!("keys"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .accessor(utf16!("size"), Attribute::CONFIGURABLE)
+        .property(
+            utf16!("values"),
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(
+            WellKnown::Iterator,
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "TYPED_ARRAY")
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .property(
+            WellKnown::Iterator,
+            Attribute::WRITABLE | Attribute::CONFIGURABLE,
+        )
+        .accessor(utf16!("buffer"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("byteLength"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("byteOffset"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("length"), Attribute::CONFIGURABLE)
+        .accessor(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .static_method(utf16!("from"))
+        .static_method(utf16!("of"))
+        .method(utf16!("at"))
+        .method(utf16!("copyWithin"))
+        .method(utf16!("entries"))
+        .method(utf16!("every"))
+        .method(utf16!("fill"))
+        .method(utf16!("filter"))
+        .method(utf16!("find"))
+        .method(utf16!("findIndex"))
+        .method(utf16!("forEach"))
+        .method(utf16!("includes"))
+        .method(utf16!("indexOf"))
+        .method(utf16!("join"))
+        .method(utf16!("keys"))
+        .method(utf16!("lastIndexOf"))
+        .method(utf16!("map"))
+        .method(utf16!("reduce"))
+        .method(utf16!("reduceRight"))
+        .method(utf16!("reverse"))
+        .method(utf16!("set"))
+        .method(utf16!("slice"))
+        .method(utf16!("some"))
+        .method(utf16!("sort"))
+        .method(utf16!("subarray"))
+        .method(utf16!("values"))
+        // 23.2.3.29 %TypedArray%.prototype.toString ( )
+        // The initial value of the %TypedArray%.prototype.toString data property is the same
+        // built-in function object as the Array.prototype.toString method defined in 23.1.3.30.
+        .method(utf16!("toString"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "TYPED_ARRAY_INSTANCE")
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .property(utf16!("BYTES_PER_ELEMENT"), Attribute::empty())
+        .static_property(utf16!("BYTES_PER_ELEMENT"), Attribute::empty())
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "ARRAY_BUFFER")
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .static_method(utf16!("isView"))
+        .accessor(utf16!("byteLength"), Attribute::CONFIGURABLE)
+        .method(utf16!("slice"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "DATA_VIEW")
+        .accessor(utf16!("buffer"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("byteLength"), Attribute::CONFIGURABLE)
+        .accessor(utf16!("byteOffset"), Attribute::CONFIGURABLE)
+        .method(utf16!("getBigInt64"))
+        .method(utf16!("getBigUint64"))
+        .method(utf16!("getFloat32"))
+        .method(utf16!("getFloat64"))
+        .method(utf16!("getInt8"))
+        .method(utf16!("getInt16"))
+        .method(utf16!("getInt32"))
+        .method(utf16!("getUint8"))
+        .method(utf16!("getUint16"))
+        .method(utf16!("getUint32"))
+        .method(utf16!("setBigInt64"))
+        .method(utf16!("setBigUint64"))
+        .method(utf16!("setFloat32"))
+        .method(utf16!("setFloat64"))
+        .method(utf16!("setInt8"))
+        .method(utf16!("setInt16"))
+        .method(utf16!("setInt32"))
+        .method(utf16!("setUint8"))
+        .method(utf16!("setUint16"))
+        .method(utf16!("setUint32"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "WEAK_REF")
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .method(utf16!("deref"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "PROMISE")
+        .static_method(utf16!("all"))
+        .static_method(utf16!("allSettled"))
+        .static_method(utf16!("any"))
+        .static_method(utf16!("race"))
+        .static_method(utf16!("reject"))
+        .static_method(utf16!("resolve"))
+        .static_accessor(WellKnown::Species, Attribute::CONFIGURABLE)
+        .method(utf16!("then"))
+        .method(utf16!("catch"))
+        .method(utf16!("finally"))
+        // <https://tc39.es/ecma262/#sec-promise.prototype-@@tostringtag>
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "WEAK_MAP")
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .method(utf16!("delete"))
+        .method(utf16!("get"))
+        .method(utf16!("has"))
+        .method(utf16!("set"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::new(&context, "WEAK_SET")
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .method(utf16!("add"))
+        .method(utf16!("delete"))
+        .method(utf16!("has"))
+        .build(file)?;
+
+    BuiltInBuilderConstructor::with_constructor_attributes(
+        &context,
+        "GENERATOR_FUNCTION",
+        Attribute::CONFIGURABLE,
+    )
+    // .inherits(Some(
+    //     realm.intrinsics().constructors().function().prototype(),
+    // ))
+    .property(utf16!("prototype"), Attribute::CONFIGURABLE)
+    .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+    .build(file)?;
+
+    BuiltInBuilder::new(&context, "ITERATOR_PROTOTYPE")
+        .method(WellKnown::Iterator)
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "COMMON_ITERATOR_PROTOTYPE")
+        .method(utf16!("next"))
+        .property(WellKnown::ToStringTag, Attribute::CONFIGURABLE)
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "FOR_IN_ITERATOR_PROTOTYPE")
+        .method(utf16!("next"))
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "ASYNC_ITERATOR_PROTOTYPE")
+        .method(WellKnown::AsyncIterator)
+        .build(file)?;
+
+    BuiltInBuilder::new(&context, "ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE")
+        .method(utf16!("next"))
+        .method(utf16!("return"))
+        .method(utf16!("throw"))
+        .build(file)?;
+
+    context.build(file)?;
+
+    Ok(())
+}
+
+/// Array of raw static strings that aren't reference counted.
+///
+/// The macro `static_strings` automatically sorts the array of strings, making it faster
+/// for searches by using `binary_search`.
+const RAW_STATICS: &[&[u16]] = &[
+    utf16!(""),
+    // Misc
+    utf16!(","),
+    utf16!(":"),
+    // Generic use
+    utf16!("name"),
+    utf16!("length"),
+    utf16!("arguments"),
+    utf16!("prototype"),
+    utf16!("constructor"),
+    utf16!("return"),
+    utf16!("throw"),
+    utf16!("global"),
+    utf16!("globalThis"),
+    // typeof
+    utf16!("null"),
+    utf16!("undefined"),
+    utf16!("number"),
+    utf16!("string"),
+    utf16!("symbol"),
+    utf16!("bigint"),
+    utf16!("object"),
+    utf16!("function"),
+    // Property descriptor
+    utf16!("value"),
+    utf16!("get"),
+    utf16!("set"),
+    utf16!("writable"),
+    utf16!("enumerable"),
+    utf16!("configurable"),
+    // Object object
+    utf16!("Object"),
+    utf16!("assign"),
+    utf16!("create"),
+    utf16!("toString"),
+    utf16!("valueOf"),
+    utf16!("is"),
+    utf16!("seal"),
+    utf16!("isSealed"),
+    utf16!("freeze"),
+    utf16!("isFrozen"),
+    utf16!("isExtensible"),
+    utf16!("hasOwnProperty"),
+    utf16!("isPrototypeOf"),
+    utf16!("setPrototypeOf"),
+    utf16!("getPrototypeOf"),
+    utf16!("defineProperty"),
+    utf16!("defineProperties"),
+    utf16!("deleteProperty"),
+    utf16!("construct"),
+    utf16!("hasOwn"),
+    utf16!("ownKeys"),
+    utf16!("keys"),
+    utf16!("values"),
+    utf16!("entries"),
+    utf16!("fromEntries"),
+    // Function object
+    utf16!("Function"),
+    utf16!("apply"),
+    utf16!("bind"),
+    utf16!("call"),
+    // Generator object
+    utf16!("Generator"),
+    // Array object
+    utf16!("Array"),
+    utf16!("at"),
+    utf16!("from"),
+    utf16!("isArray"),
+    utf16!("of"),
+    utf16!("copyWithin"),
+    utf16!("every"),
+    utf16!("fill"),
+    utf16!("filter"),
+    utf16!("find"),
+    utf16!("findIndex"),
+    utf16!("findLast"),
+    utf16!("findLastIndex"),
+    utf16!("flat"),
+    utf16!("flatMap"),
+    utf16!("forEach"),
+    utf16!("includes"),
+    utf16!("indexOf"),
+    utf16!("join"),
+    utf16!("map"),
+    utf16!("next"),
+    utf16!("reduce"),
+    utf16!("reduceRight"),
+    utf16!("reverse"),
+    utf16!("shift"),
+    utf16!("slice"),
+    utf16!("splice"),
+    utf16!("some"),
+    utf16!("sort"),
+    utf16!("unshift"),
+    utf16!("push"),
+    utf16!("pop"),
+    // String object
+    utf16!("String"),
+    utf16!("charAt"),
+    utf16!("charCodeAt"),
+    utf16!("codePointAt"),
+    utf16!("concat"),
+    utf16!("endsWith"),
+    utf16!("fromCharCode"),
+    utf16!("fromCodePoint"),
+    utf16!("lastIndexOf"),
+    utf16!("match"),
+    utf16!("matchAll"),
+    utf16!("normalize"),
+    utf16!("padEnd"),
+    utf16!("padStart"),
+    utf16!("raw"),
+    utf16!("repeat"),
+    utf16!("replace"),
+    utf16!("replaceAll"),
+    utf16!("search"),
+    utf16!("split"),
+    utf16!("startsWith"),
+    utf16!("substr"),
+    utf16!("substring"),
+    utf16!("toLocaleString"),
+    utf16!("toLowerCase"),
+    utf16!("toUpperCase"),
+    utf16!("trim"),
+    utf16!("trimEnd"),
+    utf16!("trimStart"),
+    // Number object
+    utf16!("Number"),
+    utf16!("Infinity"),
+    utf16!("NaN"),
+    utf16!("parseInt"),
+    utf16!("parseFloat"),
+    utf16!("isFinite"),
+    utf16!("isNaN"),
+    utf16!("EPSILON"),
+    utf16!("MAX_SAFE_INTEGER"),
+    utf16!("MIN_SAFE_INTEGER"),
+    utf16!("MAX_VALUE"),
+    utf16!("MIN_VALUE"),
+    utf16!("isSafeInteger"),
+    utf16!("isInteger"),
+    utf16!("toExponential"),
+    utf16!("toFixed"),
+    utf16!("toPrecision"),
+    // Boolean object
+    utf16!("Boolean"),
+    // BigInt object
+    utf16!("BigInt"),
+    utf16!("asIntN"),
+    utf16!("asUintN"),
+    // RegExp object
+    utf16!("RegExp"),
+    utf16!("exec"),
+    utf16!("test"),
+    utf16!("flags"),
+    utf16!("index"),
+    utf16!("lastIndex"),
+    utf16!("hasIndices"),
+    utf16!("ignoreCase"),
+    utf16!("multiline"),
+    utf16!("dotAll"),
+    utf16!("unicode"),
+    utf16!("sticky"),
+    utf16!("source"),
+    utf16!("get hasIndices"),
+    utf16!("get global"),
+    utf16!("get ignoreCase"),
+    utf16!("get multiline"),
+    utf16!("get dotAll"),
+    utf16!("get unicode"),
+    utf16!("get sticky"),
+    utf16!("get flags"),
+    utf16!("get source"),
+    // Symbol object
+    utf16!("Symbol"),
+    utf16!("for"),
+    utf16!("keyFor"),
+    utf16!("description"),
+    utf16!("asyncIterator"),
+    utf16!("hasInstance"),
+    utf16!("species"),
+    utf16!("unscopables"),
+    utf16!("iterator"),
+    utf16!("toStringTag"),
+    utf16!("toPrimitive"),
+    utf16!("get description"),
+    // Map object
+    utf16!("Map"),
+    utf16!("clear"),
+    utf16!("delete"),
+    utf16!("has"),
+    utf16!("size"),
+    // Set object
+    utf16!("Set"),
+    utf16!("add"),
+    // Reflect object
+    utf16!("Reflect"),
+    // Proxy object
+    utf16!("Proxy"),
+    utf16!("revocable"),
+    // Error objects
+    utf16!("Error"),
+    utf16!("AggregateError"),
+    utf16!("TypeError"),
+    utf16!("RangeError"),
+    utf16!("SyntaxError"),
+    utf16!("ReferenceError"),
+    utf16!("EvalError"),
+    utf16!("ThrowTypeError"),
+    utf16!("URIError"),
+    utf16!("message"),
+    // Date object
+    utf16!("Date"),
+    utf16!("toJSON"),
+    utf16!("getDate"),
+    utf16!("getDay"),
+    utf16!("getFullYear"),
+    utf16!("getHours"),
+    utf16!("getMilliseconds"),
+    utf16!("getMinutes"),
+    utf16!("getMonth"),
+    utf16!("getSeconds"),
+    utf16!("getTime"),
+    utf16!("getYear"),
+    utf16!("getUTCDate"),
+    utf16!("getUTCDay"),
+    utf16!("getUTCFullYear"),
+    utf16!("getUTCHours"),
+    utf16!("getUTCMinutes"),
+    utf16!("getUTCMonth"),
+    utf16!("getUTCSeconds"),
+    utf16!("setDate"),
+    utf16!("setFullYear"),
+    utf16!("setHours"),
+    utf16!("setMilliseconds"),
+    utf16!("setMinutes"),
+    utf16!("setMonth"),
+    utf16!("setSeconds"),
+    utf16!("setYear"),
+    utf16!("setTime"),
+    utf16!("setUTCDate"),
+    utf16!("setUTCFullYear"),
+    utf16!("setUTCHours"),
+    utf16!("setUTCMinutes"),
+    utf16!("setUTCMonth"),
+    utf16!("setUTCSeconds"),
+    utf16!("toDateString"),
+    utf16!("toGMTString"),
+    utf16!("toISOString"),
+    utf16!("toTimeString"),
+    utf16!("toUTCString"),
+    utf16!("now"),
+    utf16!("UTC"),
+    // JSON object
+    utf16!("JSON"),
+    utf16!("parse"),
+    utf16!("stringify"),
+    // Iterator object
+    utf16!("Array Iterator"),
+    utf16!("Set Iterator"),
+    utf16!("String Iterator"),
+    utf16!("Map Iterator"),
+    utf16!("For In Iterator"),
+    // Math object
+    utf16!("Math"),
+    utf16!("LN10"),
+    utf16!("LN2"),
+    utf16!("LOG10E"),
+    utf16!("LOG2E"),
+    utf16!("PI"),
+    utf16!("SQRT1_2"),
+    utf16!("SQRT2"),
+    utf16!("abs"),
+    utf16!("acos"),
+    utf16!("acosh"),
+    utf16!("asin"),
+    utf16!("asinh"),
+    utf16!("atan"),
+    utf16!("atanh"),
+    utf16!("atan2"),
+    utf16!("cbrt"),
+    utf16!("ceil"),
+    utf16!("clz32"),
+    utf16!("cos"),
+    utf16!("cosh"),
+    utf16!("exp"),
+    utf16!("expm1"),
+    utf16!("floor"),
+    utf16!("fround"),
+    utf16!("hypot"),
+    utf16!("imul"),
+    utf16!("log"),
+    utf16!("log1p"),
+    utf16!("log10"),
+    utf16!("log2"),
+    utf16!("max"),
+    utf16!("min"),
+    utf16!("pow"),
+    utf16!("random"),
+    utf16!("round"),
+    utf16!("sign"),
+    utf16!("sin"),
+    utf16!("sinh"),
+    utf16!("sqrt"),
+    utf16!("tan"),
+    utf16!("tanh"),
+    utf16!("trunc"),
+    // Intl object
+    utf16!("Intl"),
+    utf16!("DateTimeFormat"),
+    // TypedArray object
+    utf16!("TypedArray"),
+    utf16!("ArrayBuffer"),
+    utf16!("Int8Array"),
+    utf16!("Uint8Array"),
+    utf16!("Int16Array"),
+    utf16!("Uint16Array"),
+    utf16!("Int32Array"),
+    utf16!("Uint32Array"),
+    utf16!("BigInt64Array"),
+    utf16!("BigUint64Array"),
+    utf16!("Float32Array"),
+    utf16!("Float64Array"),
+    utf16!("buffer"),
+    utf16!("byteLength"),
+    utf16!("byteOffset"),
+    utf16!("isView"),
+    utf16!("subarray"),
+    utf16!("get byteLength"),
+    utf16!("get buffer"),
+    utf16!("get byteOffset"),
+    utf16!("get size"),
+    utf16!("get length"),
+    // DataView object
+    utf16!("DataView"),
+    utf16!("getBigInt64"),
+    utf16!("getBigUint64"),
+    utf16!("getFloat32"),
+    utf16!("getFloat64"),
+    utf16!("getInt8"),
+    utf16!("getInt16"),
+    utf16!("getInt32"),
+    utf16!("getUint8"),
+    utf16!("getUint16"),
+    utf16!("getUint32"),
+    utf16!("setBigInt64"),
+    utf16!("setBigUint64"),
+    utf16!("setFloat32"),
+    utf16!("setFloat64"),
+    utf16!("setInt8"),
+    utf16!("setInt16"),
+    utf16!("setInt32"),
+    utf16!("setUint8"),
+    utf16!("setUint16"),
+    utf16!("setUint32"),
+    // Console object
+    utf16!("console"),
+    utf16!("assert"),
+    utf16!("debug"),
+    utf16!("error"),
+    utf16!("info"),
+    utf16!("trace"),
+    utf16!("warn"),
+    utf16!("exception"),
+    utf16!("count"),
+    utf16!("countReset"),
+    utf16!("group"),
+    utf16!("groupCollapsed"),
+    utf16!("groupEnd"),
+    utf16!("time"),
+    utf16!("timeLog"),
+    utf16!("timeEnd"),
+    utf16!("dir"),
+    utf16!("dirxml"),
+    // Minified name
+    utf16!("a"),
+    utf16!("b"),
+    utf16!("c"),
+    utf16!("d"),
+    utf16!("e"),
+    utf16!("f"),
+    utf16!("g"),
+    utf16!("h"),
+    utf16!("i"),
+    utf16!("j"),
+    utf16!("k"),
+    utf16!("l"),
+    utf16!("m"),
+    utf16!("n"),
+    utf16!("o"),
+    utf16!("p"),
+    utf16!("q"),
+    utf16!("r"),
+    utf16!("s"),
+    utf16!("t"),
+    utf16!("u"),
+    utf16!("v"),
+    utf16!("w"),
+    utf16!("x"),
+    utf16!("y"),
+    utf16!("z"),
+    utf16!("A"),
+    utf16!("B"),
+    utf16!("C"),
+    utf16!("D"),
+    utf16!("E"),
+    utf16!("F"),
+    utf16!("G"),
+    utf16!("H"),
+    utf16!("I"),
+    utf16!("J"),
+    utf16!("K"),
+    utf16!("L"),
+    utf16!("M"),
+    utf16!("N"),
+    utf16!("O"),
+    utf16!("P"),
+    utf16!("Q"),
+    utf16!("R"),
+    utf16!("S"),
+    utf16!("T"),
+    utf16!("U"),
+    utf16!("V"),
+    utf16!("W"),
+    utf16!("X"),
+    utf16!("Y"),
+    utf16!("Z"),
+    utf16!("_"),
+    utf16!("$"),
+    // Well known symbols
+    utf16!("Symbol.asyncIterator"),
+    utf16!("[Symbol.asyncIterator]"),
+    utf16!("Symbol.hasInstance"),
+    utf16!("[Symbol.hasInstance]"),
+    utf16!("Symbol.isConcatSpreadable"),
+    utf16!("[Symbol.isConcatSpreadable]"),
+    utf16!("Symbol.iterator"),
+    utf16!("[Symbol.iterator]"),
+    utf16!("Symbol.match"),
+    utf16!("[Symbol.match]"),
+    utf16!("Symbol.matchAll"),
+    utf16!("[Symbol.matchAll]"),
+    utf16!("Symbol.replace"),
+    utf16!("[Symbol.replace]"),
+    utf16!("Symbol.search"),
+    utf16!("[Symbol.search]"),
+    utf16!("Symbol.species"),
+    utf16!("[Symbol.species]"),
+    utf16!("Symbol.split"),
+    utf16!("[Symbol.split]"),
+    utf16!("Symbol.toPrimitive"),
+    utf16!("[Symbol.toPrimitive]"),
+    utf16!("Symbol.toStringTag"),
+    utf16!("[Symbol.toStringTag]"),
+    utf16!("Symbol.unscopables"),
+    utf16!("[Symbol.unscopables]"),
+];
diff --git a/boa_builtins/src/lib.rs b/boa_builtins/src/lib.rs
new file mode 100644
index 00000000000..4f61654213d
--- /dev/null
+++ b/boa_builtins/src/lib.rs
@@ -0,0 +1,181 @@
+use std::{
+    fmt::{self, Debug},
+    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(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct StaticString {
+    index: u16,
+}
+
+impl StaticString {
+    #[inline]
+    pub fn index(self) -> u16 {
+        self.index
+    }
+}
+
+#[derive(Clone, Copy)]
+pub struct EncodedStaticPropertyKey(u16);
+
+impl EncodedStaticPropertyKey {
+    #[inline]
+    pub fn decode(&self) -> StaticPropertyKey {
+        let value = self.0 >> 1;
+        if self.0 & 1 == 0 {
+            StaticPropertyKey::String(value)
+        } else {
+            StaticPropertyKey::Symbol(value as u8)
+        }
+    }
+}
+
+const fn string(index: u16) -> EncodedStaticPropertyKey {
+    debug_assert!(index < 2u16.pow(15));
+
+    EncodedStaticPropertyKey(index << 1)
+}
+
+const fn symbol(index: u8) -> EncodedStaticPropertyKey {
+    EncodedStaticPropertyKey(((index as u16) << 1) | 1)
+}
+
+impl Debug for EncodedStaticPropertyKey {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.decode().fmt(f)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum StaticPropertyKey {
+    String(u16),
+    Symbol(u8),
+}
+
+impl StaticPropertyKey {
+    #[inline]
+    pub fn encode(self) -> EncodedStaticPropertyKey {
+        match self {
+            StaticPropertyKey::String(x) => string(x),
+            StaticPropertyKey::Symbol(x) => symbol(x),
+        }
+    }
+}
+
+impl Debug for StaticPropertyKey {
+    #[inline]
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match *self {
+            StaticPropertyKey::String(index) => {
+                let string = RAW_STATICS[index as usize];
+                let string = String::from_utf16_lossy(string);
+                write!(f, "String(\"{string}\")")
+            }
+            StaticPropertyKey::Symbol(symbol) => {
+                write!(f, "Symbol({symbol})")
+            }
+        }
+    }
+}
+
+impl Eq for EncodedStaticPropertyKey {}
+
+impl PartialEq for EncodedStaticPropertyKey {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl Hash for EncodedStaticPropertyKey {
+    #[inline]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
+impl PhfHash for EncodedStaticPropertyKey {
+    #[inline]
+    fn phf_hash<H: Hasher>(&self, state: &mut H) {
+        self.hash(state)
+    }
+}
+
+impl PhfBorrow<EncodedStaticPropertyKey> for EncodedStaticPropertyKey {
+    #[inline]
+    fn borrow(&self) -> &EncodedStaticPropertyKey {
+        self
+    }
+}
+
+pub type Slot = (u8, Attribute);
+
+#[derive(Debug)]
+pub struct StaticShape {
+    pub property_table: phf::OrderedMap<EncodedStaticPropertyKey, Slot>,
+
+    pub storage_len: usize,
+
+    /// \[\[Prototype\]\]
+    pub prototype: Option<&'static StaticShape>,
+}
+
+impl StaticShape {
+    #[inline]
+    pub fn get(&self, key: StaticPropertyKey) -> Option<Slot> {
+        // SAFETY: only used to extend the lifetime, so we are able to call get.
+        self.property_table
+            .get(&key.encode())
+            .map(|(index, attributes)| (*index, *attributes))
+    }
+
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.property_table.is_empty()
+    }
+
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.property_table.len()
+    }
+
+    #[inline]
+    pub fn get_string_key_expect(&self, index: usize) -> StaticString {
+        match self
+            .property_table
+            .index(index)
+            .expect("there should be a key at the given index")
+            .0
+            .decode()
+        {
+            StaticPropertyKey::String(index) => StaticString { index },
+            StaticPropertyKey::Symbol(s) => {
+                panic!("The key should be a string at position {index}, but symbol {s}")
+            }
+        }
+    }
+}
+
+include!(concat!(env!("OUT_DIR"), "/static_shapes_codegen.rs"));
+
+// static NUMBER_BUITIN_OBJECT_STATIC_SHAPE_REF: &StaticShape = &NUMBER_BUITIN_OBJECT_STATIC_SHAPE;
diff --git a/boa_cli/src/debug/shape.rs b/boa_cli/src/debug/shape.rs
index 167bc5b3c47..e874008cf92 100644
--- a/boa_cli/src/debug/shape.rs
+++ b/boa_cli/src/debug/shape.rs
@@ -31,8 +31,12 @@ fn r#type(_: &JsValue, args: &[JsValue], _: &mut Context<'_>) -> JsResult<JsValu
 
     Ok(if shape.is_shared() {
         js_string!("shared")
-    } else {
+    } else if shape.is_unique() {
         js_string!("unique")
+    } else if shape.is_static() {
+        js_string!("static")
+    } else {
+        unreachable!("shapes can only be shared, unique, or static")
     }
     .into())
 }
diff --git a/boa_engine/Cargo.toml b/boa_engine/Cargo.toml
index 1b59d7e951e..3b42721edc9 100644
--- a/boa_engine/Cargo.toml
+++ b/boa_engine/Cargo.toml
@@ -43,10 +43,11 @@ flowgraph = []
 trace = []
 
 # Enable Boa's additional ECMAScript features for web browsers.
-annex-b = ["boa_parser/annex-b"]
+annex-b = ["boa_parser/annex-b", "boa_builtins/annex-b"]
 
 [dependencies]
 boa_interner.workspace = true
+boa_builtins.workspace = true
 boa_gc = { workspace = true, features = [ "thinvec" ] }
 boa_profiler.workspace = true
 boa_macros.workspace = true
diff --git a/boa_engine/src/builtins/array/array_iterator.rs b/boa_engine/src/builtins/array/array_iterator.rs
index 417efb815ae..5514499ed01 100644
--- a/boa_engine/src/builtins/array/array_iterator.rs
+++ b/boa_engine/src/builtins/array/array_iterator.rs
@@ -12,9 +12,8 @@ use crate::{
     context::intrinsics::Intrinsics,
     error::JsNativeError,
     object::{JsObject, ObjectData},
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsResult,
 };
 use boa_gc::{Finalize, Trace};
@@ -39,21 +38,20 @@ impl IntrinsicObject for ArrayIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("ArrayIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                "Array Iterator",
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .static_property("Array Iterator")
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/array/mod.rs b/boa_engine/src/builtins/array/mod.rs
index 8f684027bb1..72774455898 100644
--- a/boa_engine/src/builtins/array/mod.rs
+++ b/boa_engine/src/builtins/array/mod.rs
@@ -21,7 +21,7 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData, CONSTRUCTOR},
-    property::{Attribute, PropertyDescriptor, PropertyNameKind},
+    property::{PropertyDescriptor, PropertyNameKind},
     realm::Realm,
     symbol::JsSymbol,
     value::{IntegerOrInfinity, JsValue},
@@ -44,9 +44,6 @@ impl IntrinsicObject for Array {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let symbol_iterator = JsSymbol::iterator();
-        let symbol_unscopables = JsSymbol::unscopables();
-
         let get_species = BuiltInBuilder::callable(realm, Self::get_species)
             .name("get [Symbol.species]")
             .build();
@@ -61,71 +58,54 @@ impl IntrinsicObject for Array {
 
         let unscopables_object = Self::unscopables_object();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .property(
-                utf16!("length"),
-                0,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
-            )
-            .property(
-                utf16!("values"),
-                values_function.clone(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                symbol_iterator,
-                values_function,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                symbol_unscopables,
-                unscopables_object,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .method(Self::at, "at", 1)
-            .method(Self::concat, "concat", 1)
-            .method(Self::push, "push", 1)
-            .method(Self::index_of, "indexOf", 1)
-            .method(Self::last_index_of, "lastIndexOf", 1)
-            .method(Self::includes_value, "includes", 1)
-            .method(Self::map, "map", 1)
-            .method(Self::fill, "fill", 1)
-            .method(Self::for_each, "forEach", 1)
-            .method(Self::filter, "filter", 1)
-            .method(Self::pop, "pop", 0)
-            .method(Self::join, "join", 1)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::reverse, "reverse", 0)
-            .method(Self::shift, "shift", 0)
-            .method(Self::unshift, "unshift", 1)
-            .method(Self::every, "every", 1)
-            .method(Self::find, "find", 1)
-            .method(Self::find_index, "findIndex", 1)
-            .method(Self::find_last, "findLast", 1)
-            .method(Self::find_last_index, "findLastIndex", 1)
-            .method(Self::flat, "flat", 0)
-            .method(Self::flat_map, "flatMap", 1)
-            .method(Self::slice, "slice", 2)
-            .method(Self::some, "some", 1)
-            .method(Self::sort, "sort", 1)
-            .method(Self::splice, "splice", 2)
-            .method(Self::to_locale_string, "toLocaleString", 0)
-            .method(Self::reduce, "reduce", 1)
-            .method(Self::reduce_right, "reduceRight", 1)
-            .method(Self::keys, "keys", 0)
-            .method(Self::entries, "entries", 0)
-            .method(Self::copy_within, "copyWithin", 2)
-            // Static Methods
-            .static_method(Self::from, "from", 1)
-            .static_method(Self::is_array, "isArray", 1)
-            .static_method(Self::of, "of", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::ARRAY_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::ARRAY_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(0)
+        .property(values_function.clone())
+        .property(values_function)
+        .property(unscopables_object)
+        .method(Self::at, 1)
+        .method(Self::concat, 1)
+        .method(Self::push, 1)
+        .method(Self::index_of, 1)
+        .method(Self::last_index_of, 1)
+        .method(Self::includes_value, 1)
+        .method(Self::map, 1)
+        .method(Self::fill, 1)
+        .method(Self::for_each, 1)
+        .method(Self::filter, 1)
+        .method(Self::pop, 0)
+        .method(Self::join, 1)
+        .method(Self::to_string, 0)
+        .method(Self::reverse, 0)
+        .method(Self::shift, 0)
+        .method(Self::unshift, 1)
+        .method(Self::every, 1)
+        .method(Self::find, 1)
+        .method(Self::find_index, 1)
+        .method(Self::find_last, 1)
+        .method(Self::find_last_index, 1)
+        .method(Self::flat, 0)
+        .method(Self::flat_map, 1)
+        .method(Self::slice, 2)
+        .method(Self::some, 1)
+        .method(Self::sort, 1)
+        .method(Self::splice, 2)
+        .method(Self::to_locale_string, 0)
+        .method(Self::reduce, 1)
+        .method(Self::reduce_right, 1)
+        .method(Self::keys, 0)
+        .method(Self::entries, 0)
+        .method(Self::copy_within, 2)
+        // Static Methods
+        .static_accessor(Some(get_species), None)
+        .static_method(Self::from, 1)
+        .static_method(Self::is_array, 1)
+        .static_method(Self::of, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/array_buffer/mod.rs b/boa_engine/src/builtins/array_buffer/mod.rs
index 6d57ec67e21..1a1100540b5 100644
--- a/boa_engine/src/builtins/array_buffer/mod.rs
+++ b/boa_engine/src/builtins/array_buffer/mod.rs
@@ -15,10 +15,7 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
-    string::utf16,
-    symbol::JsSymbol,
     value::{IntegerOrInfinity, Numeric},
     Context, JsArgs, JsResult, JsValue,
 };
@@ -51,8 +48,6 @@ impl IntrinsicObject for ArrayBuffer {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE;
-
         let get_species = BuiltInBuilder::callable(realm, Self::get_species)
             .name("get [Symbol.species]")
             .build();
@@ -61,27 +56,17 @@ impl IntrinsicObject for ArrayBuffer {
             .name("get byteLength")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .accessor(
-                utf16!("byteLength"),
-                Some(get_byte_length),
-                None,
-                flag_attributes,
-            )
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .static_method(Self::is_view, "isView", 1)
-            .method(Self::slice, "slice", 2)
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::ARRAY_BUFFER_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::ARRAY_BUFFER_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_accessor(Some(get_species), None)
+        .static_method(Self::is_view, 1)
+        .accessor(Some(get_byte_length), None)
+        .method(Self::slice, 2)
+        .property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/bigint/mod.rs b/boa_engine/src/builtins/bigint/mod.rs
index d649bf60830..77845981bc7 100644
--- a/boa_engine/src/builtins/bigint/mod.rs
+++ b/boa_engine/src/builtins/bigint/mod.rs
@@ -17,9 +17,7 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::JsObject,
-    property::Attribute,
     realm::Realm,
-    symbol::JsSymbol,
     value::{IntegerOrInfinity, PreferredType},
     Context, JsArgs, JsBigInt, JsResult, JsValue,
 };
@@ -39,17 +37,17 @@ impl IntrinsicObject for BigInt {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::value_of, "valueOf", 0)
-            .static_method(Self::as_int_n, "asIntN", 2)
-            .static_method(Self::as_uint_n, "asUintN", 2)
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::BIGINT_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::BIGINT_PROTOTYPE_STATIC_SHAPE,
+        )
+        .method(Self::to_string, 0)
+        .method(Self::value_of, 0)
+        .static_method(Self::as_int_n, 2)
+        .static_method(Self::as_uint_n, 2)
+        .property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/boolean/mod.rs b/boa_engine/src/builtins/boolean/mod.rs
index 91f8186f566..2d36b6dce48 100644
--- a/boa_engine/src/builtins/boolean/mod.rs
+++ b/boa_engine/src/builtins/boolean/mod.rs
@@ -32,10 +32,14 @@ impl IntrinsicObject for Boolean {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::value_of, "valueOf", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::BOOLEAN_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::BOOLEAN_PROTOTYPE_STATIC_SHAPE,
+        )
+        .method(Self::to_string, 0)
+        .method(Self::value_of, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/dataview/mod.rs b/boa_engine/src/builtins/dataview/mod.rs
index 56ba390303b..ba07e4f77ba 100644
--- a/boa_engine/src/builtins/dataview/mod.rs
+++ b/boa_engine/src/builtins/dataview/mod.rs
@@ -12,10 +12,7 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
-    string::utf16,
-    symbol::JsSymbol,
     value::JsValue,
     Context, JsArgs, JsResult,
 };
@@ -33,8 +30,6 @@ pub struct DataView {
 
 impl IntrinsicObject for DataView {
     fn init(realm: &Realm) {
-        let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE;
-
         let get_buffer = BuiltInBuilder::callable(realm, Self::get_buffer)
             .name("get buffer")
             .build();
@@ -47,46 +42,36 @@ impl IntrinsicObject for DataView {
             .name("get byteOffset")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .accessor(utf16!("buffer"), Some(get_buffer), None, flag_attributes)
-            .accessor(
-                utf16!("byteLength"),
-                Some(get_byte_length),
-                None,
-                flag_attributes,
-            )
-            .accessor(
-                utf16!("byteOffset"),
-                Some(get_byte_offset),
-                None,
-                flag_attributes,
-            )
-            .method(Self::get_big_int64, "getBigInt64", 1)
-            .method(Self::get_big_uint64, "getBigUint64", 1)
-            .method(Self::get_float32, "getFloat32", 1)
-            .method(Self::get_float64, "getFloat64", 1)
-            .method(Self::get_int8, "getInt8", 1)
-            .method(Self::get_int16, "getInt16", 1)
-            .method(Self::get_int32, "getInt32", 1)
-            .method(Self::get_uint8, "getUint8", 1)
-            .method(Self::get_uint16, "getUint16", 1)
-            .method(Self::get_uint32, "getUint32", 1)
-            .method(Self::set_big_int64, "setBigInt64", 2)
-            .method(Self::set_big_uint64, "setBigUint64", 2)
-            .method(Self::set_float32, "setFloat32", 2)
-            .method(Self::set_float64, "setFloat64", 2)
-            .method(Self::set_int8, "setInt8", 2)
-            .method(Self::set_int16, "setInt16", 2)
-            .method(Self::set_int32, "setInt32", 2)
-            .method(Self::set_uint8, "setUint8", 2)
-            .method(Self::set_uint16, "setUint16", 2)
-            .method(Self::set_uint32, "setUint32", 2)
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::DATA_VIEW_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::DATA_VIEW_PROTOTYPE_STATIC_SHAPE,
+        )
+        .accessor(Some(get_buffer), None)
+        .accessor(Some(get_byte_length), None)
+        .accessor(Some(get_byte_offset), None)
+        .method(Self::get_big_int64, 1)
+        .method(Self::get_big_uint64, 1)
+        .method(Self::get_float32, 1)
+        .method(Self::get_float64, 1)
+        .method(Self::get_int8, 1)
+        .method(Self::get_int16, 1)
+        .method(Self::get_int32, 1)
+        .method(Self::get_uint8, 1)
+        .method(Self::get_uint16, 1)
+        .method(Self::get_uint32, 1)
+        .method(Self::set_big_int64, 2)
+        .method(Self::set_big_uint64, 2)
+        .method(Self::set_float32, 2)
+        .method(Self::set_float64, 2)
+        .method(Self::set_int8, 2)
+        .method(Self::set_int16, 2)
+        .method(Self::set_int32, 2)
+        .method(Self::set_uint8, 2)
+        .method(Self::set_uint16, 2)
+        .method(Self::set_uint32, 2)
+        .property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/date/mod.rs b/boa_engine/src/builtins/date/mod.rs
index f6ce1d798e5..2d0d1a7c10e 100644
--- a/boa_engine/src/builtins/date/mod.rs
+++ b/boa_engine/src/builtins/date/mod.rs
@@ -22,10 +22,8 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     value::{IntegerOrNan, JsValue, PreferredType},
     Context, JsArgs, JsError, JsResult,
 };
@@ -106,70 +104,62 @@ impl IntrinsicObject for Date {
             .length(1)
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_method(Self::now, "now", 0)
-            .static_method(Self::parse, "parse", 1)
-            .static_method(Self::utc, "UTC", 7)
-            .method(Self::get_date::<true>, "getDate", 0)
-            .method(Self::get_day::<true>, "getDay", 0)
-            .method(Self::get_full_year::<true>, "getFullYear", 0)
-            .method(Self::get_hours::<true>, "getHours", 0)
-            .method(Self::get_milliseconds::<true>, "getMilliseconds", 0)
-            .method(Self::get_minutes::<true>, "getMinutes", 0)
-            .method(Self::get_month::<true>, "getMonth", 0)
-            .method(Self::get_seconds::<true>, "getSeconds", 0)
-            .method(Self::get_time, "getTime", 0)
-            .method(Self::get_timezone_offset, "getTimezoneOffset", 0)
-            .method(Self::get_date::<false>, "getUTCDate", 0)
-            .method(Self::get_day::<false>, "getUTCDay", 0)
-            .method(Self::get_full_year::<false>, "getUTCFullYear", 0)
-            .method(Self::get_hours::<false>, "getUTCHours", 0)
-            .method(Self::get_milliseconds::<false>, "getUTCMilliseconds", 0)
-            .method(Self::get_minutes::<false>, "getUTCMinutes", 0)
-            .method(Self::get_month::<false>, "getUTCMonth", 0)
-            .method(Self::get_seconds::<false>, "getUTCSeconds", 0)
-            .method(Self::get_year, "getYear", 0)
-            .method(Self::set_date::<true>, "setDate", 1)
-            .method(Self::set_full_year::<true>, "setFullYear", 3)
-            .method(Self::set_hours::<true>, "setHours", 4)
-            .method(Self::set_milliseconds::<true>, "setMilliseconds", 1)
-            .method(Self::set_minutes::<true>, "setMinutes", 3)
-            .method(Self::set_month::<true>, "setMonth", 2)
-            .method(Self::set_seconds::<true>, "setSeconds", 2)
-            .method(Self::set_time, "setTime", 1)
-            .method(Self::set_date::<false>, "setUTCDate", 1)
-            .method(Self::set_full_year::<false>, "setUTCFullYear", 3)
-            .method(Self::set_hours::<false>, "setUTCHours", 4)
-            .method(Self::set_milliseconds::<false>, "setUTCMilliseconds", 1)
-            .method(Self::set_minutes::<false>, "setUTCMinutes", 3)
-            .method(Self::set_month::<false>, "setUTCMonth", 2)
-            .method(Self::set_seconds::<false>, "setUTCSeconds", 2)
-            .method(Self::set_year, "setYear", 1)
-            .method(Self::to_date_string, "toDateString", 0)
-            .method(Self::to_iso_string, "toISOString", 0)
-            .method(Self::to_json, "toJSON", 1)
-            .method(Self::to_locale_date_string, "toLocaleDateString", 0)
-            .method(Self::to_locale_string, "toLocaleString", 0)
-            .method(Self::to_locale_time_string, "toLocaleTimeString", 0)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::to_time_string, "toTimeString", 0)
-            .method(Self::value_of, "valueOf", 0)
-            .property(
-                "toGMTString",
-                to_utc_string.clone(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                "toUTCString",
-                to_utc_string,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::to_primitive(),
-                to_primitive,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::DATE_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::DATE_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method(Self::now, 0)
+        .static_method(Self::parse, 1)
+        .static_method(Self::utc, 7)
+        .method(Self::get_date::<true>, 0)
+        .method(Self::get_day::<true>, 0)
+        .method(Self::get_full_year::<true>, 0)
+        .method(Self::get_hours::<true>, 0)
+        .method(Self::get_milliseconds::<true>, 0)
+        .method(Self::get_minutes::<true>, 0)
+        .method(Self::get_month::<true>, 0)
+        .method(Self::get_seconds::<true>, 0)
+        .method(Self::get_time, 0)
+        .method(Self::get_timezone_offset, 0)
+        .method(Self::get_date::<false>, 0)
+        .method(Self::get_day::<false>, 0)
+        .method(Self::get_full_year::<false>, 0)
+        .method(Self::get_hours::<false>, 0)
+        .method(Self::get_milliseconds::<false>, 0)
+        .method(Self::get_minutes::<false>, 0)
+        .method(Self::get_month::<false>, 0)
+        .method(Self::get_seconds::<false>, 0)
+        .method(Self::get_year, 0)
+        .method(Self::set_date::<true>, 1)
+        .method(Self::set_full_year::<true>, 3)
+        .method(Self::set_hours::<true>, 4)
+        .method(Self::set_milliseconds::<true>, 1)
+        .method(Self::set_minutes::<true>, 3)
+        .method(Self::set_month::<true>, 2)
+        .method(Self::set_seconds::<true>, 2)
+        .method(Self::set_time, 1)
+        .method(Self::set_date::<false>, 1)
+        .method(Self::set_full_year::<false>, 3)
+        .method(Self::set_hours::<false>, 4)
+        .method(Self::set_milliseconds::<false>, 1)
+        .method(Self::set_minutes::<false>, 3)
+        .method(Self::set_month::<false>, 2)
+        .method(Self::set_seconds::<false>, 2)
+        .method(Self::set_year, 1)
+        .method(Self::to_date_string, 0)
+        .method(Self::to_iso_string, 0)
+        .method(Self::to_json, 1)
+        .method(Self::to_locale_date_string, 0)
+        .method(Self::to_locale_string, 0)
+        .method(Self::to_locale_time_string, 0)
+        .method(Self::to_string, 0)
+        .method(Self::to_time_string, 0)
+        .method(Self::value_of, 0)
+        .property(to_utc_string.clone())
+        .property(to_utc_string)
+        .property(to_primitive)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/aggregate.rs b/boa_engine/src/builtins/error/aggregate.rs
index f9ce1fd70fd..0adbdf20d7e 100644
--- a/boa_engine/src/builtins/error/aggregate.rs
+++ b/boa_engine/src/builtins/error/aggregate.rs
@@ -14,10 +14,10 @@ use crate::{
     },
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::{Attribute, PropertyDescriptorBuilder},
+    property::PropertyDescriptorBuilder,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -30,13 +30,16 @@ impl IntrinsicObject for AggregateError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/eval.rs b/boa_engine/src/builtins/error/eval.rs
index ac3d915ed5f..d59ff8c2eed 100644
--- a/boa_engine/src/builtins/error/eval.rs
+++ b/boa_engine/src/builtins/error/eval.rs
@@ -15,10 +15,9 @@ use crate::{
     builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -32,13 +31,16 @@ impl IntrinsicObject for EvalError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/mod.rs b/boa_engine/src/builtins/error/mod.rs
index 0430ddd26f0..4f77430e2ce 100644
--- a/boa_engine/src/builtins/error/mod.rs
+++ b/boa_engine/src/builtins/error/mod.rs
@@ -16,7 +16,6 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
     Context, JsArgs, JsResult, JsValue,
@@ -131,12 +130,15 @@ impl IntrinsicObject for Error {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .method(Self::to_string, "toString", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(Self::NAME)
+        .property(js_string!(""))
+        .method(Self::to_string, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/range.rs b/boa_engine/src/builtins/error/range.rs
index 36c657b9c68..921c3c9140d 100644
--- a/boa_engine/src/builtins/error/range.rs
+++ b/boa_engine/src/builtins/error/range.rs
@@ -13,10 +13,9 @@ use crate::{
     builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -30,13 +29,16 @@ impl IntrinsicObject for RangeError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/reference.rs b/boa_engine/src/builtins/error/reference.rs
index e72dd09883b..dad820a4a05 100644
--- a/boa_engine/src/builtins/error/reference.rs
+++ b/boa_engine/src/builtins/error/reference.rs
@@ -13,10 +13,9 @@ use crate::{
     builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -29,13 +28,16 @@ impl IntrinsicObject for ReferenceError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/syntax.rs b/boa_engine/src/builtins/error/syntax.rs
index 444e32a3d78..6ede2d51b45 100644
--- a/boa_engine/src/builtins/error/syntax.rs
+++ b/boa_engine/src/builtins/error/syntax.rs
@@ -15,10 +15,9 @@ use crate::{
     builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -32,13 +31,16 @@ impl IntrinsicObject for SyntaxError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/type.rs b/boa_engine/src/builtins/error/type.rs
index 87cdc6fae5e..ed2e2cca8e0 100644
--- a/boa_engine/src/builtins/error/type.rs
+++ b/boa_engine/src/builtins/error/type.rs
@@ -26,7 +26,7 @@ use crate::{
     property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue, NativeFunction,
+    Context, JsArgs, JsResult, JsString, JsValue, NativeFunction,
 };
 use boa_profiler::Profiler;
 
@@ -40,13 +40,16 @@ impl IntrinsicObject for TypeError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/error/uri.rs b/boa_engine/src/builtins/error/uri.rs
index 34a7514d6cf..4b8aed9416d 100644
--- a/boa_engine/src/builtins/error/uri.rs
+++ b/boa_engine/src/builtins/error/uri.rs
@@ -14,10 +14,9 @@ use crate::{
     builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    Context, JsArgs, JsResult, JsValue,
+    Context, JsArgs, JsResult, JsString, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -31,13 +30,16 @@ impl IntrinsicObject for UriError {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .prototype(realm.intrinsics().constructors().error().constructor())
-            .inherits(Some(realm.intrinsics().constructors().error().prototype()))
-            .property(utf16!("name"), Self::NAME, attribute)
-            .property(utf16!("message"), "", attribute)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NATIVE_ERROR_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NATIVE_ERROR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(realm.intrinsics().constructors().error().constructor())
+        .inherits(Some(realm.intrinsics().constructors().error().prototype()))
+        .property(Self::NAME)
+        .property(JsString::default())
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/escape/mod.rs b/boa_engine/src/builtins/escape/mod.rs
index a8897142079..d5357245cf8 100644
--- a/boa_engine/src/builtins/escape/mod.rs
+++ b/boa_engine/src/builtins/escape/mod.rs
@@ -23,7 +23,7 @@ pub(crate) struct Escape;
 
 impl IntrinsicObject for Escape {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, escape)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, escape)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -95,7 +95,7 @@ pub(crate) struct Unescape;
 
 impl IntrinsicObject for Unescape {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, unescape)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, unescape)
             .name(Self::NAME)
             .length(1)
             .build();
diff --git a/boa_engine/src/builtins/eval/mod.rs b/boa_engine/src/builtins/eval/mod.rs
index 0a4f0b38159..7862f30a702 100644
--- a/boa_engine/src/builtins/eval/mod.rs
+++ b/boa_engine/src/builtins/eval/mod.rs
@@ -35,7 +35,7 @@ impl IntrinsicObject for Eval {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, Self::eval)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, Self::eval)
             .name(Self::NAME)
             .length(1)
             .build();
diff --git a/boa_engine/src/builtins/function/mod.rs b/boa_engine/src/builtins/function/mod.rs
index 2eeb1ab8649..c5c9cfc16a9 100644
--- a/boa_engine/src/builtins/function/mod.rs
+++ b/boa_engine/src/builtins/function/mod.rs
@@ -19,12 +19,14 @@ use crate::{
     error::JsNativeError,
     js_string,
     native_function::NativeFunction,
-    object::{internal_methods::get_prototype_from_constructor, JsObject, Object, ObjectData},
-    object::{JsFunction, PrivateElement, PrivateName},
-    property::{Attribute, PropertyDescriptor, PropertyKey},
+    object::{
+        internal_methods::get_prototype_from_constructor, JsObject, Object, ObjectData, ObjectKind,
+        PrivateName,
+    },
+    object::{JsFunction, PrivateElement},
+    property::{PropertyDescriptor, PropertyKey},
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     value::IntegerOrInfinity,
     vm::{ActiveRunnable, CodeBlock},
     Context, JsArgs, JsResult, JsString, JsValue,
@@ -468,33 +470,65 @@ impl IntrinsicObject for BuiltInFunctionObject {
 
         let throw_type_error = realm.intrinsics().objects().throw_type_error();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .method(Self::apply, "apply", 2)
-            .method(Self::bind, "bind", 1)
-            .method(Self::call, "call", 1)
-            .method(Self::to_string, "toString", 0)
-            .property(JsSymbol::has_instance(), has_instance, Attribute::default())
-            .accessor(
-                utf16!("caller"),
-                Some(throw_type_error.clone()),
-                Some(throw_type_error.clone()),
-                Attribute::CONFIGURABLE,
-            )
-            .accessor(
-                utf16!("arguments"),
-                Some(throw_type_error.clone()),
-                Some(throw_type_error),
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        // BuiltInBuilder::from_standard_constructor::<Self>(realm)
+        //     .method(Self::apply, "apply", 2)
+        //     .method(Self::bind, "bind", 1)
+        //     .method(Self::call, "call", 1)
+        //     .method(Self::to_string, "toString", 0)
+        //     .property(JsSymbol::has_instance(), has_instance, Attribute::default())
+        //     .accessor(
+        //         utf16!("caller"),
+        //         Some(throw_type_error.clone()),
+        //         Some(throw_type_error.clone()),
+        //         Attribute::CONFIGURABLE,
+        //     )
+        //     .accessor(
+        //         utf16!("arguments"),
+        //         Some(throw_type_error.clone()),
+        //         Some(throw_type_error),
+        //         Attribute::CONFIGURABLE,
+        //     )
+        //     .build();
+
+        // BuiltInBuilder::callable_with_object(realm, prototype.clone(), Self::prototype)
+        //     .name("")
+        //     .length(0)
+        //     .build();
+
+        // prototype.set_prototype(Some(realm.intrinsics().constructors().object().prototype()));
+
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::FUNCTION_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::FUNCTION_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(0)
+        .property("")
+        .method(Self::apply, 2)
+        .method(Self::bind, 1)
+        .method(Self::call, 1)
+        .method(Self::to_string, 0)
+        .property(has_instance)
+        .accessor(
+            Some(throw_type_error.clone()),
+            Some(throw_type_error.clone()),
+        )
+        .accessor(Some(throw_type_error.clone()), Some(throw_type_error))
+        .build();
 
         let prototype = realm.intrinsics().constructors().function().prototype();
-
-        BuiltInBuilder::callable_with_object(realm, prototype.clone(), Self::prototype)
-            .name("")
-            .length(0)
-            .build();
-
+        {
+            let mut prototype = prototype.borrow_mut();
+            let function = Function::new(
+                FunctionKind::Native {
+                    function: NativeFunction::from_fn_ptr(Self::prototype),
+                    constructor: (true).then_some(ConstructorKind::Base),
+                },
+                realm.clone(),
+            );
+            *prototype.kind_mut() = ObjectKind::Function(function);
+        }
+        // TODO: improve this, because it's converting the static shape into a unique one, on initialization.
         prototype.set_prototype(Some(realm.intrinsics().constructors().object().prototype()));
     }
 
@@ -1013,6 +1047,7 @@ impl BuiltInFunctionObject {
         Ok(JsValue::ordinary_has_instance(this, args.get_or_undefined(0), context)?.into())
     }
 
+    #[allow(dead_code)]
     #[allow(clippy::unnecessary_wraps)]
     fn prototype(_: &JsValue, _: &[JsValue], _: &mut Context<'_>) -> JsResult<JsValue> {
         Ok(JsValue::undefined())
diff --git a/boa_engine/src/builtins/generator_function/mod.rs b/boa_engine/src/builtins/generator_function/mod.rs
index 90d2fb951d4..efaf0831873 100644
--- a/boa_engine/src/builtins/generator_function/mod.rs
+++ b/boa_engine/src/builtins/generator_function/mod.rs
@@ -13,10 +13,7 @@
 use crate::{
     builtins::{function::BuiltInFunctionObject, BuiltInObject},
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
-    object::PROTOTYPE,
-    property::Attribute,
     realm::Realm,
-    symbol::JsSymbol,
     value::JsValue,
     Context, JsResult,
 };
@@ -32,22 +29,17 @@ impl IntrinsicObject for GeneratorFunction {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .inherits(Some(
-                realm.intrinsics().constructors().function().prototype(),
-            ))
-            .constructor_attributes(Attribute::CONFIGURABLE)
-            .property(
-                PROTOTYPE,
-                realm.intrinsics().objects().generator(),
-                Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::GENERATOR_FUNCTION_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::GENERATOR_FUNCTION_PROTOTYPE_STATIC_SHAPE,
+        )
+        .inherits(Some(
+            realm.intrinsics().constructors().function().prototype(),
+        ))
+        .property(realm.intrinsics().objects().generator())
+        .property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> crate::object::JsObject {
diff --git a/boa_engine/src/builtins/intl/segmenter/iterator.rs b/boa_engine/src/builtins/intl/segmenter/iterator.rs
index 18dca851310..0781d2ddb0e 100644
--- a/boa_engine/src/builtins/intl/segmenter/iterator.rs
+++ b/boa_engine/src/builtins/intl/segmenter/iterator.rs
@@ -9,9 +9,8 @@ use crate::{
     context::intrinsics::Intrinsics,
     js_string,
     object::ObjectData,
-    property::Attribute,
     realm::Realm,
-    Context, JsNativeError, JsObject, JsResult, JsString, JsSymbol, JsValue,
+    Context, JsNativeError, JsObject, JsResult, JsString, JsValue,
 };
 
 use super::create_segment_data_object;
@@ -57,14 +56,13 @@ impl IntrinsicObject for SegmentIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("%SegmentIteratorPrototype%", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                js_string!("Segmenter String Iterator"),
-                Attribute::CONFIGURABLE,
-            )
-            .static_method(Self::next, js_string!("next"), 0)
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method(Self::next, 0)
+        .static_property(js_string!("Segmenter String Iterator"))
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs b/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs
index 5557b7427d3..3e7b0600bc9 100644
--- a/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs
+++ b/boa_engine/src/builtins/iterable/async_from_sync_iterator.rs
@@ -30,18 +30,21 @@ impl IntrinsicObject for AsyncFromSyncIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("AsyncFromSyncIteratorPrototype", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .async_iterator(),
-            )
-            .static_method(Self::next, "next", 1)
-            .static_method(Self::r#return, "return", 1)
-            .static_method(Self::throw, "throw", 1)
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::ASYNC_FROM_SYNC_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .async_iterator(),
+        )
+        .static_method(Self::next, 1)
+        .static_method(Self::r#return, 1)
+        .static_method(Self::throw, 1)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/iterable/mod.rs b/boa_engine/src/builtins/iterable/mod.rs
index e6dddab4da5..0717f2ca5ab 100644
--- a/boa_engine/src/builtins/iterable/mod.rs
+++ b/boa_engine/src/builtins/iterable/mod.rs
@@ -40,7 +40,7 @@ macro_rules! if_abrupt_close_iterator {
 pub(crate) use if_abrupt_close_iterator;
 
 /// The built-in iterator prototypes.
-#[derive(Debug, Default, Trace, Finalize)]
+#[derive(Debug, Trace, Finalize)]
 pub struct IteratorPrototypes {
     /// The `IteratorPrototype` object.
     iterator: JsObject,
@@ -74,6 +74,24 @@ pub struct IteratorPrototypes {
     segment: JsObject,
 }
 
+impl Default for IteratorPrototypes {
+    fn default() -> Self {
+        Self {
+            array: JsObject::default_with_static_shape(),
+            iterator: JsObject::default_with_static_shape(),
+            async_iterator: JsObject::default_with_static_shape(),
+            async_from_sync_iterator: JsObject::default_with_static_shape(),
+            set: JsObject::default_with_static_shape(),
+            string: JsObject::default_with_static_shape(),
+            regexp_string: JsObject::default_with_static_shape(),
+            map: JsObject::default_with_static_shape(),
+            for_in: JsObject::default_with_static_shape(),
+            #[cfg(feature = "intl")]
+            segment: JsObject::default_with_static_shape(),
+        }
+    }
+}
+
 impl IteratorPrototypes {
     /// Returns the `ArrayIteratorPrototype` object.
     #[inline]
@@ -150,13 +168,12 @@ impl IntrinsicObject for Iterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("Iterator Prototype", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_method(
-                |v, _, _| Ok(v.clone()),
-                (JsSymbol::iterator(), js_string!("[Symbol.iterator]")),
-                0,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method_with_name(|v, _, _| Ok(v.clone()), js_string!("[Symbol.iterator]"), 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
@@ -176,16 +193,16 @@ impl IntrinsicObject for AsyncIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("AsyncIteratorPrototype", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_method(
-                |v, _, _| Ok(v.clone()),
-                (
-                    JsSymbol::async_iterator(),
-                    js_string!("[Symbol.asyncIterator]"),
-                ),
-                0,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::ASYNC_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method_with_name(
+            |v, _, _| Ok(v.clone()),
+            js_string!("[Symbol.asyncIterator]"),
+            0,
+        )
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/json/mod.rs b/boa_engine/src/builtins/json/mod.rs
index 20b80fef102..5badff62833 100644
--- a/boa_engine/src/builtins/json/mod.rs
+++ b/boa_engine/src/builtins/json/mod.rs
@@ -24,10 +24,9 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::JsObject,
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
     string::{utf16, CodePoint},
-    symbol::JsSymbol,
     value::IntegerOrInfinity,
     vm::CallFrame,
     Context, JsArgs, JsResult, JsString, JsValue,
@@ -50,14 +49,14 @@ impl IntrinsicObject for Json {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let to_string_tag = JsSymbol::to_string_tag();
-        let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE;
-
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_method(Self::parse, "parse", 2)
-            .static_method(Self::stringify, "stringify", 3)
-            .static_property(to_string_tag, Self::NAME, attribute)
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::JSON_OBJECT_STATIC_SHAPE,
+        )
+        .static_method(Self::parse, 2)
+        .static_method(Self::stringify, 3)
+        .static_property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/map/map_iterator.rs b/boa_engine/src/builtins/map/map_iterator.rs
index 4d531d5bfc2..70cd916f4c9 100644
--- a/boa_engine/src/builtins/map/map_iterator.rs
+++ b/boa_engine/src/builtins/map/map_iterator.rs
@@ -13,9 +13,8 @@ use crate::{
     context::intrinsics::Intrinsics,
     error::JsNativeError,
     object::{JsObject, ObjectData},
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsResult,
 };
 use boa_gc::{Finalize, Trace};
@@ -40,21 +39,20 @@ impl IntrinsicObject for MapIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("MapIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                "Map Iterator",
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .static_property("Map Iterator")
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/map/mod.rs b/boa_engine/src/builtins/map/mod.rs
index f8d04e4fc19..e93b7faa520 100644
--- a/boa_engine/src/builtins/map/mod.rs
+++ b/boa_engine/src/builtins/map/mod.rs
@@ -15,10 +15,9 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     Context, JsArgs, JsResult, JsValue,
 };
 use boa_profiler::Profiler;
@@ -53,43 +52,25 @@ impl IntrinsicObject for Map {
             .name("entries")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .property(
-                utf16!("entries"),
-                entries_function.clone(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::iterator(),
-                entries_function,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .method(Self::clear, "clear", 0)
-            .method(Self::delete, "delete", 1)
-            .method(Self::for_each, "forEach", 1)
-            .method(Self::get, "get", 1)
-            .method(Self::has, "has", 1)
-            .method(Self::keys, "keys", 0)
-            .method(Self::set, "set", 2)
-            .method(Self::values, "values", 0)
-            .accessor(
-                utf16!("size"),
-                Some(get_size),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::MAP_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::MAP_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_accessor(Some(get_species), None)
+        .property(entries_function.clone())
+        .property(entries_function)
+        .property(Self::NAME)
+        .method(Self::clear, 0)
+        .method(Self::delete, 1)
+        .method(Self::for_each, 1)
+        .method(Self::get, 1)
+        .method(Self::has, 1)
+        .method(Self::keys, 0)
+        .method(Self::set, 2)
+        .method(Self::values, 0)
+        .accessor(Some(get_size), None)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/math/mod.rs b/boa_engine/src/builtins/math/mod.rs
index 406661c5ff6..78c259b76a6 100644
--- a/boa_engine/src/builtins/math/mod.rs
+++ b/boa_engine/src/builtins/math/mod.rs
@@ -12,9 +12,8 @@
 //! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
 
 use crate::{
-    builtins::BuiltInObject, context::intrinsics::Intrinsics, object::JsObject,
-    property::Attribute, realm::Realm, string::utf16, symbol::JsSymbol, Context, JsArgs, JsResult,
-    JsValue,
+    builtins::BuiltInObject, context::intrinsics::Intrinsics, object::JsObject, realm::Realm,
+    Context, JsArgs, JsResult, JsValue,
 };
 use boa_profiler::Profiler;
 
@@ -31,61 +30,55 @@ impl IntrinsicObject for Math {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_property(utf16!("E"), std::f64::consts::E, attribute)
-            .static_property(utf16!("LN10"), std::f64::consts::LN_10, attribute)
-            .static_property(utf16!("LN2"), std::f64::consts::LN_2, attribute)
-            .static_property(utf16!("LOG10E"), std::f64::consts::LOG10_E, attribute)
-            .static_property(utf16!("LOG2E"), std::f64::consts::LOG2_E, attribute)
-            .static_property(utf16!("PI"), std::f64::consts::PI, attribute)
-            .static_property(
-                utf16!("SQRT1_2"),
-                std::f64::consts::FRAC_1_SQRT_2,
-                attribute,
-            )
-            .static_property(utf16!("SQRT2"), std::f64::consts::SQRT_2, attribute)
-            .static_method(Self::abs, "abs", 1)
-            .static_method(Self::acos, "acos", 1)
-            .static_method(Self::acosh, "acosh", 1)
-            .static_method(Self::asin, "asin", 1)
-            .static_method(Self::asinh, "asinh", 1)
-            .static_method(Self::atan, "atan", 1)
-            .static_method(Self::atanh, "atanh", 1)
-            .static_method(Self::atan2, "atan2", 2)
-            .static_method(Self::cbrt, "cbrt", 1)
-            .static_method(Self::ceil, "ceil", 1)
-            .static_method(Self::clz32, "clz32", 1)
-            .static_method(Self::cos, "cos", 1)
-            .static_method(Self::cosh, "cosh", 1)
-            .static_method(Self::exp, "exp", 1)
-            .static_method(Self::expm1, "expm1", 1)
-            .static_method(Self::floor, "floor", 1)
-            .static_method(Self::fround, "fround", 1)
-            .static_method(Self::hypot, "hypot", 2)
-            .static_method(Self::imul, "imul", 2)
-            .static_method(Self::log, "log", 1)
-            .static_method(Self::log1p, "log1p", 1)
-            .static_method(Self::log10, "log10", 1)
-            .static_method(Self::log2, "log2", 1)
-            .static_method(Self::max, "max", 2)
-            .static_method(Self::min, "min", 2)
-            .static_method(Self::pow, "pow", 2)
-            .static_method(Self::random, "random", 0)
-            .static_method(Self::round, "round", 1)
-            .static_method(Self::sign, "sign", 1)
-            .static_method(Self::sin, "sin", 1)
-            .static_method(Self::sinh, "sinh", 1)
-            .static_method(Self::sqrt, "sqrt", 1)
-            .static_method(Self::tan, "tan", 1)
-            .static_method(Self::tanh, "tanh", 1)
-            .static_method(Self::trunc, "trunc", 1)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::MATH_OBJECT_STATIC_SHAPE,
+        )
+        .static_property(std::f64::consts::E)
+        .static_property(std::f64::consts::LN_10)
+        .static_property(std::f64::consts::LN_2)
+        .static_property(std::f64::consts::LOG10_E)
+        .static_property(std::f64::consts::LOG2_E)
+        .static_property(std::f64::consts::PI)
+        .static_property(std::f64::consts::FRAC_1_SQRT_2)
+        .static_property(std::f64::consts::SQRT_2)
+        .static_method(Self::abs, 1)
+        .static_method(Self::acos, 1)
+        .static_method(Self::acosh, 1)
+        .static_method(Self::asin, 1)
+        .static_method(Self::asinh, 1)
+        .static_method(Self::atan, 1)
+        .static_method(Self::atanh, 1)
+        .static_method(Self::atan2, 2)
+        .static_method(Self::cbrt, 1)
+        .static_method(Self::ceil, 1)
+        .static_method(Self::clz32, 1)
+        .static_method(Self::cos, 1)
+        .static_method(Self::cosh, 1)
+        .static_method(Self::exp, 1)
+        .static_method(Self::expm1, 1)
+        .static_method(Self::floor, 1)
+        .static_method(Self::fround, 1)
+        .static_method(Self::hypot, 2)
+        .static_method(Self::imul, 2)
+        .static_method(Self::log, 1)
+        .static_method(Self::log1p, 1)
+        .static_method(Self::log10, 1)
+        .static_method(Self::log2, 1)
+        .static_method(Self::max, 2)
+        .static_method(Self::min, 2)
+        .static_method(Self::pow, 2)
+        .static_method(Self::random, 0)
+        .static_method(Self::round, 1)
+        .static_method(Self::sign, 1)
+        .static_method(Self::sin, 1)
+        .static_method(Self::sinh, 1)
+        .static_method(Self::sqrt, 1)
+        .static_method(Self::tan, 1)
+        .static_method(Self::tanh, 1)
+        .static_method(Self::trunc, 1)
+        .static_property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/mod.rs b/boa_engine/src/builtins/mod.rs
index 798f8d70b8e..a061ca37bde 100644
--- a/boa_engine/src/builtins/mod.rs
+++ b/boa_engine/src/builtins/mod.rs
@@ -39,6 +39,8 @@ pub mod escape;
 #[cfg(feature = "intl")]
 pub mod intl;
 
+use boa_builtins::StaticShape as RawStaticShape;
+
 pub(crate) use self::{
     array::Array,
     async_function::AsyncFunction,
@@ -95,7 +97,9 @@ use crate::{
     js_string,
     native_function::{NativeFunction, NativeFunctionPointer},
     object::{
-        shape::{property_table::PropertyTableInner, slot::SlotAttributes},
+        shape::{
+            property_table::PropertyTableInner, slot::SlotAttributes, static_shape::StaticShape,
+        },
         FunctionBinding, JsFunction, JsObject, JsPrototype, Object, ObjectData, ObjectKind,
         CONSTRUCTOR, PROTOTYPE,
     },
@@ -587,19 +591,334 @@ struct BuiltInBuilder<'ctx, Kind> {
     prototype: JsObject,
 }
 
-impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
-    // fn new(realm: &'ctx Realm) -> BuiltInBuilder<'ctx, OrdinaryObject> {
-    //     BuiltInBuilder {
-    //         realm,
-    //         object: BuiltInObjectInitializer::Unique {
-    //             object: Object::default(),
-    //             data: ObjectData::ordinary(),
-    //         },
-    //         kind: OrdinaryObject,
-    //         prototype: realm.intrinsics().constructors().object().prototype(),
-    //     }
-    // }
+struct BuiltInBuilderCallableIntrinsic<'ctx> {
+    realm: &'ctx Realm,
+    function: NativeFunctionPointer,
+    object: JsObject,
+    name: JsString,
+    length: usize,
+}
+
+impl BuiltInBuilderCallableIntrinsic<'_> {
+    fn name<N: Into<JsString>>(mut self, name: N) -> Self {
+        self.name = name.into();
+        self
+    }
+    /// Specify how many arguments the constructor function takes.
+    ///
+    /// Default is `0`.
+    const fn length(mut self, length: usize) -> Self {
+        self.length = length;
+        self
+    }
+    fn build(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 mut object = self.object.borrow_mut();
+        object.properties_mut().shape = self
+            .realm
+            .intrinsics()
+            .templates()
+            .function()
+            .shape()
+            .clone()
+            .into();
+        object.properties_mut().storage = vec![self.length.into(), self.name.into()];
+        *object.kind_mut() = ObjectKind::Function(function);
+    }
+}
+
+struct BuiltInBuilderConstructorStaticShape<'ctx> {
+    realm: &'ctx Realm,
+    function: NativeFunctionPointer,
+
+    constructor_property_index: usize,
+    constructor_object: JsObject,
+    constructor_shape: &'static RawStaticShape,
+    constructor_storage: Vec<JsValue>,
+
+    prototype_property_index: usize,
+    prototype_object: JsObject,
+    prototype_shape: &'static RawStaticShape,
+    prototype_storage: Vec<JsValue>,
+
+    __proto__: JsPrototype,
+    inherits: Option<JsObject>,
+}
+
+impl<'ctx> BuiltInBuilder<'ctx, Callable<Constructor>> {
+    fn from_standard_constructor_static_shape<SC: BuiltInConstructor>(
+        realm: &'ctx Realm,
+        constructor_shape: &'static RawStaticShape,
+        prototype_shape: &'static RawStaticShape,
+    ) -> BuiltInBuilderConstructorStaticShape<'ctx> {
+        let constructor = SC::STANDARD_CONSTRUCTOR(realm.intrinsics().constructors());
+        // println!("{constructor_shape:#?}");
+        // println!("{prototype_shape:#?}");
+        let mut this = BuiltInBuilderConstructorStaticShape {
+            realm,
+            function: SC::constructor,
+
+            constructor_property_index: 0,
+            constructor_shape,
+            constructor_storage: Vec::with_capacity(constructor_shape.storage_len),
+            constructor_object: constructor.constructor(),
+
+            prototype_property_index: 0,
+            prototype_shape,
+            prototype_storage: Vec::with_capacity(prototype_shape.storage_len),
+            prototype_object: constructor.prototype(),
+
+            __proto__: Some(realm.intrinsics().constructors().function().prototype()),
+            inherits: Some(realm.intrinsics().constructors().object().prototype()),
+        };
+
+        this.constructor_storage.push(SC::LENGTH.into());
+        this.constructor_storage.push(js_string!(SC::NAME).into());
+        this.constructor_storage
+            .push(this.prototype_object.clone().into());
+        this.constructor_property_index += 3;
+
+        this.prototype_storage
+            .push(this.constructor_object.clone().into());
+        this.prototype_property_index += 1;
+
+        this
+    }
+}
+
+#[allow(dead_code)]
+impl BuiltInBuilderConstructorStaticShape<'_> {
+    /// Adds a new static method to the builtin object.
+    fn static_method(mut self, function: NativeFunctionPointer, length: usize) -> Self {
+        let name = self
+            .constructor_shape
+            .get_string_key_expect(self.constructor_property_index);
+
+        let function = BuiltInBuilder::callable(self.realm, function)
+            .name(name)
+            .length(length)
+            .build();
+
+        self.constructor_storage.push(function.into());
+        self.constructor_property_index += 1;
+        self
+    }
+
+    /// Adds a new static data property to the builtin object.
+    fn static_property<V>(mut self, value: V) -> Self
+    where
+        V: Into<JsValue>,
+    {
+        self.constructor_storage.push(value.into());
+        self.constructor_property_index += 1;
+        self
+    }
+
+    /// Specify the `[[Prototype]]` internal field of the builtin object.
+    ///
+    /// Default is `Function.prototype` for constructors and `Object.prototype` for statics.
+    fn prototype(mut self, prototype: JsObject) -> Self {
+        self.__proto__ = Some(prototype);
+        self
+    }
+
+    /// Adds a new method to the constructor's prototype.
+    fn method(mut self, function: NativeFunctionPointer, length: usize) -> Self {
+        let name = self
+            .prototype_shape
+            .get_string_key_expect(self.prototype_property_index);
+
+        let function = BuiltInBuilder::callable(self.realm, function)
+            .name(name)
+            .length(length)
+            .build();
+
+        self.prototype_storage.push(function.into());
+        self.prototype_property_index += 1;
+        self
+    }
+
+    fn method_with_name(
+        mut self,
+        function: NativeFunctionPointer,
+        name: JsString,
+        length: usize,
+    ) -> Self {
+        let function = BuiltInBuilder::callable(self.realm, function)
+            .name(name)
+            .length(length)
+            .build();
+
+        self.prototype_storage.push(function.into());
+        self.prototype_property_index += 1;
+        self
+    }
+
+    /// Adds a new data property to the constructor's prototype.
+    fn property<V>(mut self, value: V) -> Self
+    where
+        V: Into<JsValue>,
+    {
+        self.prototype_storage.push(value.into());
+        self.prototype_property_index += 1;
+        self
+    }
+
+    /// Adds new accessor property to the constructor's prototype.
+    fn accessor(mut self, get: Option<JsFunction>, set: Option<JsFunction>) -> Self {
+        self.prototype_storage.extend([
+            get.map(JsValue::new).unwrap_or_default(),
+            set.map(JsValue::new).unwrap_or_default(),
+        ]);
+        self.prototype_property_index += 1;
+        self
+    }
+
+    fn static_accessor(mut self, get: Option<JsFunction>, set: Option<JsFunction>) -> Self {
+        self.constructor_storage.extend([
+            get.map(JsValue::new).unwrap_or_default(),
+            set.map(JsValue::new).unwrap_or_default(),
+        ]);
+        self.constructor_property_index += 1;
+        self
+    }
+
+    /// Specifies the parent prototype which objects created by this constructor inherit from.
+    ///
+    /// Default is `Object.prototype`.
+    #[allow(clippy::missing_const_for_fn)]
+    fn inherits(mut self, prototype: JsPrototype) -> Self {
+        self.inherits = prototype;
+        self
+    }
+
+    fn build(mut self) {
+        debug_assert_eq!(
+            self.constructor_storage.len() + 1,
+            self.constructor_shape.storage_len
+        );
+        debug_assert_eq!(
+            self.constructor_storage.capacity(),
+            self.constructor_shape.storage_len
+        );
+
+        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 mut object = self.constructor_object.borrow_mut();
+        *object.kind_mut() = ObjectKind::Function(function);
+        object.properties_mut().shape = StaticShape::new(self.constructor_shape).into();
+        self.constructor_storage.push(
+            self.__proto__
+                .unwrap_or_else(|| {
+                    self.realm
+                        .intrinsics()
+                        .constructors()
+                        .function()
+                        .prototype()
+                })
+                .into(),
+        );
+        object.properties_mut().storage = self.constructor_storage;
+
+        debug_assert_eq!(
+            self.prototype_storage.len() + 1,
+            self.prototype_shape.storage_len
+        );
+        debug_assert_eq!(
+            self.prototype_storage.capacity(),
+            self.prototype_shape.storage_len
+        );
+        let mut prototype = self.prototype_object.borrow_mut();
+        prototype.properties_mut().shape = StaticShape::new(self.prototype_shape).into();
+        self.prototype_storage
+            .push(self.inherits.map(JsValue::new).unwrap_or_default());
+        prototype.properties_mut().storage = self.prototype_storage;
+    }
+}
+
+struct BuiltInBuilderStaticShape<'ctx> {
+    realm: &'ctx Realm,
+    shape: &'static RawStaticShape,
+    object: JsObject,
+    property_index: usize,
+    storage: Vec<JsValue>,
+    prototype: JsObject,
+}
+
+impl BuiltInBuilderStaticShape<'_> {
+    fn prototype(mut self, prototype: JsObject) -> Self {
+        self.prototype = prototype;
+        self
+    }
+
+    /// Adds a new static method to the builtin object.
+    fn static_method(mut self, function: NativeFunctionPointer, length: usize) -> Self {
+        let name = self.shape.get_string_key_expect(self.property_index);
+
+        let function = BuiltInBuilder::callable(self.realm, function)
+            .name(name)
+            .length(length)
+            .build();
+
+        self.storage.push(function.into());
+        self.property_index += 1;
+        self
+    }
 
+    /// Adds a new static method to the builtin object with name.
+    fn static_method_with_name(
+        mut self,
+        function: NativeFunctionPointer,
+        name: JsString,
+        length: usize,
+    ) -> Self {
+        let function = BuiltInBuilder::callable(self.realm, function)
+            .name(name)
+            .length(length)
+            .build();
+
+        self.storage.push(function.into());
+        self.property_index += 1;
+        self
+    }
+
+    /// Adds a new static data property to the builtin object.
+    fn static_property<V>(mut self, value: V) -> Self
+    where
+        V: Into<JsValue>,
+    {
+        self.storage.push(value.into());
+        self.property_index += 1;
+        self
+    }
+
+    fn build(mut self) {
+        debug_assert_eq!(self.storage.len(), self.shape.len());
+
+        debug_assert_eq!(self.storage.len() + 1, self.shape.storage_len);
+        debug_assert_eq!(self.storage.capacity(), self.shape.storage_len);
+
+        let mut object = self.object.borrow_mut();
+        object.properties_mut().shape = StaticShape::new(self.shape).into();
+        self.storage.push(self.prototype.into());
+        object.properties_mut().storage = self.storage;
+    }
+}
+
+impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
     fn with_intrinsic<I: IntrinsicObject>(
         realm: &'ctx Realm,
     ) -> BuiltInBuilder<'ctx, OrdinaryObject> {
@@ -610,6 +929,20 @@ impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
             prototype: realm.intrinsics().constructors().object().prototype(),
         }
     }
+
+    fn with_intrinsic_static_shape<I: IntrinsicObject>(
+        realm: &'ctx Realm,
+        shape: &'static boa_builtins::StaticShape,
+    ) -> BuiltInBuilderStaticShape<'ctx> {
+        BuiltInBuilderStaticShape {
+            realm,
+            shape,
+            object: I::get(realm.intrinsics()),
+            storage: Vec::with_capacity(shape.storage_len),
+            property_index: 0,
+            prototype: realm.intrinsics().constructors().object().prototype(),
+        }
+    }
 }
 
 struct BuiltInConstructorWithPrototype<'ctx> {
@@ -625,6 +958,7 @@ struct BuiltInConstructorWithPrototype<'ctx> {
     prototype_property_table: PropertyTableInner,
     prototype_storage: Vec<JsValue>,
     prototype: JsObject,
+
     __proto__: JsPrototype,
     inherits: Option<JsObject>,
     attributes: Attribute,
@@ -943,21 +1277,16 @@ impl<'ctx> BuiltInBuilder<'ctx, OrdinaryObject> {
         }
     }
 
-    fn callable_with_intrinsic<I: IntrinsicObject>(
+    fn callable_intrinsic<I: IntrinsicObject>(
         realm: &'ctx Realm,
         function: NativeFunctionPointer,
-    ) -> BuiltInBuilder<'ctx, Callable<OrdinaryFunction>> {
-        BuiltInBuilder {
+    ) -> BuiltInBuilderCallableIntrinsic<'ctx> {
+        BuiltInBuilderCallableIntrinsic {
             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(),
+            function,
+            object: I::get(realm.intrinsics()),
+            name: JsString::default(),
+            length: 0,
         }
     }
 
@@ -1057,15 +1386,6 @@ impl<T> BuiltInBuilder<'_, T> {
 }
 
 impl<FnTyp> BuiltInBuilder<'_, Callable<FnTyp>> {
-    /// Specify how many arguments the constructor function takes.
-    ///
-    /// Default is `0`.
-    #[inline]
-    const fn length(mut self, length: usize) -> Self {
-        self.kind.length = length;
-        self
-    }
-
     /// Specify the name of the constructor function.
     ///
     /// Default is `""`
diff --git a/boa_engine/src/builtins/number/globals.rs b/boa_engine/src/builtins/number/globals.rs
index 15ae25b6f47..33f4a457f48 100644
--- a/boa_engine/src/builtins/number/globals.rs
+++ b/boa_engine/src/builtins/number/globals.rs
@@ -38,7 +38,7 @@ pub(crate) struct IsFinite;
 
 impl IntrinsicObject for IsFinite {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, is_finite)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, is_finite)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -84,7 +84,7 @@ pub(crate) struct IsNaN;
 
 impl IntrinsicObject for IsNaN {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, is_nan)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, is_nan)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -225,7 +225,7 @@ pub(crate) struct ParseInt;
 
 impl IntrinsicObject for ParseInt {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, parse_int)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, parse_int)
             .name(Self::NAME)
             .length(2)
             .build();
@@ -298,7 +298,7 @@ pub(crate) struct ParseFloat;
 
 impl IntrinsicObject for ParseFloat {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, parse_float)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, parse_float)
             .name(Self::NAME)
             .length(1)
             .build();
diff --git a/boa_engine/src/builtins/number/mod.rs b/boa_engine/src/builtins/number/mod.rs
index d87e2b2732b..2e3985a1fb7 100644
--- a/boa_engine/src/builtins/number/mod.rs
+++ b/boa_engine/src/builtins/number/mod.rs
@@ -18,9 +18,7 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
-    string::utf16,
     value::{AbstractRelation, IntegerOrInfinity, JsValue},
     Context, JsArgs, JsResult,
 };
@@ -49,46 +47,32 @@ impl IntrinsicObject for Number {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
-
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_property(utf16!("EPSILON"), f64::EPSILON, attribute)
-            .static_property(
-                utf16!("MAX_SAFE_INTEGER"),
-                Self::MAX_SAFE_INTEGER,
-                attribute,
-            )
-            .static_property(
-                utf16!("MIN_SAFE_INTEGER"),
-                Self::MIN_SAFE_INTEGER,
-                attribute,
-            )
-            .static_property(utf16!("MAX_VALUE"), Self::MAX_VALUE, attribute)
-            .static_property(utf16!("MIN_VALUE"), Self::MIN_VALUE, attribute)
-            .static_property(utf16!("NEGATIVE_INFINITY"), f64::NEG_INFINITY, attribute)
-            .static_property(utf16!("POSITIVE_INFINITY"), f64::INFINITY, attribute)
-            .static_property(utf16!("NaN"), f64::NAN, attribute)
-            .static_property(
-                utf16!("parseInt"),
-                realm.intrinsics().objects().parse_int(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .static_property(
-                utf16!("parseFloat"),
-                realm.intrinsics().objects().parse_float(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .static_method(Self::number_is_finite, "isFinite", 1)
-            .static_method(Self::number_is_nan, "isNaN", 1)
-            .static_method(Self::is_safe_integer, "isSafeInteger", 1)
-            .static_method(Self::number_is_integer, "isInteger", 1)
-            .method(Self::to_exponential, "toExponential", 1)
-            .method(Self::to_fixed, "toFixed", 1)
-            .method(Self::to_locale_string, "toLocaleString", 0)
-            .method(Self::to_precision, "toPrecision", 1)
-            .method(Self::to_string, "toString", 1)
-            .method(Self::value_of, "valueOf", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::NUMBER_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::NUMBER_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_property(f64::EPSILON)
+        .static_property(Self::MAX_SAFE_INTEGER)
+        .static_property(Self::MIN_SAFE_INTEGER)
+        .static_property(Self::MAX_VALUE)
+        .static_property(Self::MIN_VALUE)
+        .static_property(f64::NEG_INFINITY)
+        .static_property(f64::INFINITY)
+        .static_property(f64::NAN)
+        .static_property(realm.intrinsics().objects().parse_int())
+        .static_property(realm.intrinsics().objects().parse_float())
+        .static_method(Self::number_is_finite, 1)
+        .static_method(Self::number_is_nan, 1)
+        .static_method(Self::is_safe_integer, 1)
+        .static_method(Self::number_is_integer, 1)
+        .method(Self::to_exponential, 1)
+        .method(Self::to_fixed, 1)
+        .method(Self::to_locale_string, 0)
+        .method(Self::to_precision, 1)
+        .method(Self::to_string, 1)
+        .method(Self::value_of, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/object/for_in_iterator.rs b/boa_engine/src/builtins/object/for_in_iterator.rs
index 44af9f42f1c..b4be2580422 100644
--- a/boa_engine/src/builtins/object/for_in_iterator.rs
+++ b/boa_engine/src/builtins/object/for_in_iterator.rs
@@ -41,16 +41,19 @@ impl IntrinsicObject for ForInIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("ForInIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::FOR_IN_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/object/mod.rs b/boa_engine/src/builtins/object/mod.rs
index 4c4fc5202a1..d1abf0ba49d 100644
--- a/boa_engine/src/builtins/object/mod.rs
+++ b/boa_engine/src/builtins/object/mod.rs
@@ -26,7 +26,7 @@ use crate::{
         internal_methods::get_prototype_from_constructor, FunctionObjectBuilder, IntegrityLevel,
         JsObject, ObjectData, ObjectKind,
     },
-    property::{Attribute, PropertyDescriptor, PropertyKey, PropertyNameKind},
+    property::{PropertyDescriptor, PropertyKey, PropertyNameKind},
     realm::Realm,
     string::utf16,
     symbol::JsSymbol,
@@ -56,55 +56,46 @@ impl IntrinsicObject for Object {
             .name("set __proto__")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .inherits(None)
-            .accessor(
-                utf16!("__proto__"),
-                Some(legacy_proto_getter),
-                Some(legacy_setter_proto),
-                Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .method(Self::has_own_property, "hasOwnProperty", 1)
-            .method(Self::property_is_enumerable, "propertyIsEnumerable", 1)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::to_locale_string, "toLocaleString", 0)
-            .method(Self::value_of, "valueOf", 0)
-            .method(Self::is_prototype_of, "isPrototypeOf", 1)
-            .method(Self::legacy_define_getter, "__defineGetter__", 2)
-            .method(Self::legacy_define_setter, "__defineSetter__", 2)
-            .method(Self::legacy_lookup_getter, "__lookupGetter__", 1)
-            .method(Self::legacy_lookup_setter, "__lookupSetter__", 1)
-            .static_method(Self::create, "create", 2)
-            .static_method(Self::set_prototype_of, "setPrototypeOf", 2)
-            .static_method(Self::get_prototype_of, "getPrototypeOf", 1)
-            .static_method(Self::define_property, "defineProperty", 3)
-            .static_method(Self::define_properties, "defineProperties", 2)
-            .static_method(Self::assign, "assign", 2)
-            .static_method(Self::is, "is", 2)
-            .static_method(Self::keys, "keys", 1)
-            .static_method(Self::values, "values", 1)
-            .static_method(Self::entries, "entries", 1)
-            .static_method(Self::seal, "seal", 1)
-            .static_method(Self::is_sealed, "isSealed", 1)
-            .static_method(Self::freeze, "freeze", 1)
-            .static_method(Self::is_frozen, "isFrozen", 1)
-            .static_method(Self::prevent_extensions, "preventExtensions", 1)
-            .static_method(Self::is_extensible, "isExtensible", 1)
-            .static_method(
-                Self::get_own_property_descriptor,
-                "getOwnPropertyDescriptor",
-                2,
-            )
-            .static_method(
-                Self::get_own_property_descriptors,
-                "getOwnPropertyDescriptors",
-                1,
-            )
-            .static_method(Self::get_own_property_names, "getOwnPropertyNames", 1)
-            .static_method(Self::get_own_property_symbols, "getOwnPropertySymbols", 1)
-            .static_method(Self::has_own, "hasOwn", 2)
-            .static_method(Self::from_entries, "fromEntries", 1)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::OBJECT_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::OBJECT_PROTOTYPE_STATIC_SHAPE,
+        )
+        .inherits(None)
+        .accessor(Some(legacy_proto_getter), Some(legacy_setter_proto))
+        .method(Self::has_own_property, 1)
+        .method(Self::property_is_enumerable, 1)
+        .method(Self::to_string, 0)
+        .method(Self::to_locale_string, 0)
+        .method(Self::value_of, 0)
+        .method(Self::is_prototype_of, 1)
+        .method(Self::legacy_define_getter, 2)
+        .method(Self::legacy_define_setter, 2)
+        .method(Self::legacy_lookup_getter, 1)
+        .method(Self::legacy_lookup_setter, 1)
+        .static_method(Self::create, 2)
+        .static_method(Self::set_prototype_of, 2)
+        .static_method(Self::get_prototype_of, 1)
+        .static_method(Self::define_property, 3)
+        .static_method(Self::define_properties, 2)
+        .static_method(Self::assign, 2)
+        .static_method(Self::is, 2)
+        .static_method(Self::keys, 1)
+        .static_method(Self::values, 1)
+        .static_method(Self::entries, 1)
+        .static_method(Self::seal, 1)
+        .static_method(Self::is_sealed, 1)
+        .static_method(Self::freeze, 1)
+        .static_method(Self::is_frozen, 1)
+        .static_method(Self::prevent_extensions, 1)
+        .static_method(Self::is_extensible, 1)
+        .static_method(Self::get_own_property_descriptor, 2)
+        .static_method(Self::get_own_property_descriptors, 1)
+        .static_method(Self::get_own_property_names, 1)
+        .static_method(Self::get_own_property_symbols, 1)
+        .static_method(Self::has_own, 2)
+        .static_method(Self::from_entries, 1)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/promise/mod.rs b/boa_engine/src/builtins/promise/mod.rs
index 7ced9a8848c..91efd33fd24 100644
--- a/boa_engine/src/builtins/promise/mod.rs
+++ b/boa_engine/src/builtins/promise/mod.rs
@@ -14,10 +14,8 @@ use crate::{
         internal_methods::get_prototype_from_constructor, FunctionObjectBuilder, JsFunction,
         JsObject, ObjectData, CONSTRUCTOR,
     },
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     value::JsValue,
     Context, JsArgs, JsError, JsResult,
 };
@@ -324,29 +322,24 @@ impl IntrinsicObject for Promise {
             .name("get [Symbol.species]")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_method(Self::all, "all", 1)
-            .static_method(Self::all_settled, "allSettled", 1)
-            .static_method(Self::any, "any", 1)
-            .static_method(Self::race, "race", 1)
-            .static_method(Self::reject, "reject", 1)
-            .static_method(Self::resolve, "resolve", 1)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .method(Self::then, "then", 2)
-            .method(Self::catch, "catch", 1)
-            .method(Self::finally, "finally", 1)
-            // <https://tc39.es/ecma262/#sec-promise.prototype-@@tostringtag>
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::PROMISE_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::PROMISE_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method(Self::all, 1)
+        .static_method(Self::all_settled, 1)
+        .static_method(Self::any, 1)
+        .static_method(Self::race, 1)
+        .static_method(Self::reject, 1)
+        .static_method(Self::resolve, 1)
+        .static_accessor(Some(get_species), None)
+        .method(Self::then, 2)
+        .method(Self::catch, 1)
+        .method(Self::finally, 1)
+        // <https://tc39.es/ecma262/#sec-promise.prototype-@@tostringtag>
+        .property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/reflect/mod.rs b/boa_engine/src/builtins/reflect/mod.rs
index a0b2807fe0d..38fb3d25905 100644
--- a/boa_engine/src/builtins/reflect/mod.rs
+++ b/boa_engine/src/builtins/reflect/mod.rs
@@ -16,9 +16,7 @@ use crate::{
     context::intrinsics::Intrinsics,
     error::JsNativeError,
     object::JsObject,
-    property::Attribute,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsArgs, JsResult, JsValue,
 };
 use boa_profiler::Profiler;
@@ -34,32 +32,25 @@ impl IntrinsicObject for Reflect {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let to_string_tag = JsSymbol::to_string_tag();
-
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .static_method(Self::apply, "apply", 3)
-            .static_method(Self::construct, "construct", 2)
-            .static_method(Self::define_property, "defineProperty", 3)
-            .static_method(Self::delete_property, "deleteProperty", 2)
-            .static_method(Self::get, "get", 2)
-            .static_method(
-                Self::get_own_property_descriptor,
-                "getOwnPropertyDescriptor",
-                2,
-            )
-            .static_method(Self::get_prototype_of, "getPrototypeOf", 1)
-            .static_method(Self::has, "has", 2)
-            .static_method(Self::is_extensible, "isExtensible", 1)
-            .static_method(Self::own_keys, "ownKeys", 1)
-            .static_method(Self::prevent_extensions, "preventExtensions", 1)
-            .static_method(Self::set, "set", 3)
-            .static_method(Self::set_prototype_of, "setPrototypeOf", 2)
-            .static_property(
-                to_string_tag,
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::REFLECT_OBJECT_STATIC_SHAPE,
+        )
+        .static_method(Self::apply, 3)
+        .static_method(Self::construct, 2)
+        .static_method(Self::define_property, 3)
+        .static_method(Self::delete_property, 2)
+        .static_method(Self::get, 2)
+        .static_method(Self::get_own_property_descriptor, 2)
+        .static_method(Self::get_prototype_of, 1)
+        .static_method(Self::has, 2)
+        .static_method(Self::is_extensible, 1)
+        .static_method(Self::own_keys, 1)
+        .static_method(Self::prevent_extensions, 1)
+        .static_method(Self::set, 3)
+        .static_method(Self::set_prototype_of, 2)
+        .static_property(Self::NAME)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/regexp/mod.rs b/boa_engine/src/builtins/regexp/mod.rs
index 7db76a671b8..4894e6947b6 100644
--- a/boa_engine/src/builtins/regexp/mod.rs
+++ b/boa_engine/src/builtins/regexp/mod.rs
@@ -18,7 +18,7 @@ use crate::{
         internal_methods::get_prototype_from_constructor, JsObject, ObjectData, ObjectKind,
         CONSTRUCTOR,
     },
-    property::{Attribute, PropertyDescriptorBuilder},
+    property::PropertyDescriptorBuilder,
     realm::Realm,
     string::{utf16, CodePoint},
     symbol::JsSymbol,
@@ -55,8 +55,6 @@ impl IntrinsicObject for RegExp {
             .name("get [Symbol.species]")
             .build();
 
-        let flag_attributes = Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE;
-
         let get_has_indices = BuiltInBuilder::callable(realm, Self::get_has_indices)
             .name("get hasIndices")
             .build();
@@ -84,53 +82,34 @@ impl IntrinsicObject for RegExp {
         let get_source = BuiltInBuilder::callable(realm, Self::get_source)
             .name("get source")
             .build();
-        let regexp = BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .property(utf16!("lastIndex"), 0, Attribute::all())
-            .method(Self::test, "test", 1)
-            .method(Self::exec, "exec", 1)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::r#match, (JsSymbol::r#match(), "[Symbol.match]"), 1)
-            .method(
-                Self::match_all,
-                (JsSymbol::match_all(), "[Symbol.matchAll]"),
-                1,
-            )
-            .method(Self::replace, (JsSymbol::replace(), "[Symbol.replace]"), 2)
-            .method(Self::search, (JsSymbol::search(), "[Symbol.search]"), 1)
-            .method(Self::split, (JsSymbol::split(), "[Symbol.split]"), 2)
-            .accessor(
-                utf16!("hasIndices"),
-                Some(get_has_indices),
-                None,
-                flag_attributes,
-            )
-            .accessor(utf16!("global"), Some(get_global), None, flag_attributes)
-            .accessor(
-                utf16!("ignoreCase"),
-                Some(get_ignore_case),
-                None,
-                flag_attributes,
-            )
-            .accessor(
-                utf16!("multiline"),
-                Some(get_multiline),
-                None,
-                flag_attributes,
-            )
-            .accessor(utf16!("dotAll"), Some(get_dot_all), None, flag_attributes)
-            .accessor(utf16!("unicode"), Some(get_unicode), None, flag_attributes)
-            .accessor(utf16!("sticky"), Some(get_sticky), None, flag_attributes)
-            .accessor(utf16!("flags"), Some(get_flags), None, flag_attributes)
-            .accessor(utf16!("source"), Some(get_source), None, flag_attributes);
+
+        let regexp = BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::REGEXP_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::REGEXP_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_accessor(Some(get_species), None)
+        .property(0)
+        .method(Self::test, 1)
+        .method(Self::exec, 1)
+        .method(Self::to_string, 0)
+        .method_with_name(Self::r#match, js_string!("[Symbol.match]"), 1)
+        .method_with_name(Self::match_all, js_string!("[Symbol.matchAll]"), 1)
+        .method_with_name(Self::replace, js_string!("[Symbol.replace]"), 2)
+        .method_with_name(Self::search, js_string!("[Symbol.search]"), 1)
+        .method_with_name(Self::split, js_string!("[Symbol.split]"), 2)
+        .accessor(Some(get_has_indices), None)
+        .accessor(Some(get_global), None)
+        .accessor(Some(get_ignore_case), None)
+        .accessor(Some(get_multiline), None)
+        .accessor(Some(get_dot_all), None)
+        .accessor(Some(get_unicode), None)
+        .accessor(Some(get_sticky), None)
+        .accessor(Some(get_flags), None)
+        .accessor(Some(get_source), None);
 
         #[cfg(feature = "annex-b")]
-        let regexp = regexp.method(Self::compile, "compile", 2);
+        let regexp = regexp.method(Self::compile, 2);
 
         regexp.build();
     }
diff --git a/boa_engine/src/builtins/regexp/regexp_string_iterator.rs b/boa_engine/src/builtins/regexp/regexp_string_iterator.rs
index 0a16d673cf7..08bcc62a90a 100644
--- a/boa_engine/src/builtins/regexp/regexp_string_iterator.rs
+++ b/boa_engine/src/builtins/regexp/regexp_string_iterator.rs
@@ -15,10 +15,8 @@ use crate::{
     context::intrinsics::Intrinsics,
     error::JsNativeError,
     object::{JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     Context, JsResult, JsString, JsValue,
 };
 use boa_gc::{Finalize, Trace};
@@ -44,21 +42,20 @@ impl IntrinsicObject for RegExpStringIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("RegExpStringIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                "RegExp String Iterator",
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .static_property("RegExp String Iterator")
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/set/mod.rs b/boa_engine/src/builtins/set/mod.rs
index 656f27c89ed..24ec6cbe8b6 100644
--- a/boa_engine/src/builtins/set/mod.rs
+++ b/boa_engine/src/builtins/set/mod.rs
@@ -23,10 +23,9 @@ use crate::{
     context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
     error::JsNativeError,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     Context, JsArgs, JsResult, JsValue,
 };
 use boa_profiler::Profiler;
@@ -56,46 +55,24 @@ impl IntrinsicObject for Set {
             .name("values")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .method(Self::add, "add", 1)
-            .method(Self::clear, "clear", 0)
-            .method(Self::delete, "delete", 1)
-            .method(Self::entries, "entries", 0)
-            .method(Self::for_each, "forEach", 1)
-            .method(Self::has, "has", 1)
-            .property(
-                utf16!("keys"),
-                values_function.clone(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .accessor(
-                utf16!("size"),
-                Some(size_getter),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .property(
-                utf16!("values"),
-                values_function.clone(),
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::iterator(),
-                values_function,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::SET_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::SET_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_accessor(Some(get_species), None)
+        .method(Self::add, 1)
+        .method(Self::clear, 0)
+        .method(Self::delete, 1)
+        .method(Self::entries, 0)
+        .method(Self::for_each, 1)
+        .method(Self::has, 1)
+        .property(values_function.clone())
+        .accessor(Some(size_getter), None)
+        .property(values_function.clone())
+        .property(values_function)
+        .property(Self::NAME)
+        .build();
     }
 }
 
diff --git a/boa_engine/src/builtins/set/set_iterator.rs b/boa_engine/src/builtins/set/set_iterator.rs
index f49eab2a46d..c24acc4513e 100644
--- a/boa_engine/src/builtins/set/set_iterator.rs
+++ b/boa_engine/src/builtins/set/set_iterator.rs
@@ -13,9 +13,8 @@ use crate::{
     context::intrinsics::Intrinsics,
     error::JsNativeError,
     object::{JsObject, ObjectData},
-    property::{Attribute, PropertyNameKind},
+    property::PropertyNameKind,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsResult,
 };
 use boa_gc::{Finalize, Trace};
@@ -40,21 +39,20 @@ impl IntrinsicObject for SetIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("SetIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                "Set Iterator",
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .static_property("Set Iterator")
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/string/mod.rs b/boa_engine/src/builtins/string/mod.rs
index 3b88d2131e1..e1b5c853856 100644
--- a/boa_engine/src/builtins/string/mod.rs
+++ b/boa_engine/src/builtins/string/mod.rs
@@ -15,7 +15,7 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
-    property::{Attribute, PropertyDescriptor},
+    property::PropertyDescriptor,
     realm::Realm,
     string::utf16,
     string::{CodePoint, Utf16Trim},
@@ -78,8 +78,6 @@ impl IntrinsicObject for String {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
 
-        let symbol_iterator = JsSymbol::iterator();
-
         let trim_start = BuiltInBuilder::callable(realm, Self::trim_start)
             .length(0)
             .name("trimStart")
@@ -96,81 +94,68 @@ impl IntrinsicObject for String {
         #[cfg(feature = "annex-b")]
         let trim_right = trim_end.clone();
 
-        let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
-        let builder = BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .property(utf16!("length"), 0, attribute)
-            .property(
-                utf16!("trimStart"),
-                trim_start,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                utf16!("trimEnd"),
-                trim_end,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .static_method(Self::raw, "raw", 1)
-            .static_method(Self::from_char_code, "fromCharCode", 1)
-            .static_method(Self::from_code_point, "fromCodePoint", 1)
-            .method(Self::char_at, "charAt", 1)
-            .method(Self::char_code_at, "charCodeAt", 1)
-            .method(Self::code_point_at, "codePointAt", 1)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::concat, "concat", 1)
-            .method(Self::repeat, "repeat", 1)
-            .method(Self::slice, "slice", 2)
-            .method(Self::starts_with, "startsWith", 1)
-            .method(Self::ends_with, "endsWith", 1)
-            .method(Self::includes, "includes", 1)
-            .method(Self::index_of, "indexOf", 1)
-            .method(Self::last_index_of, "lastIndexOf", 1)
-            .method(Self::locale_compare, "localeCompare", 1)
-            .method(Self::r#match, "match", 1)
-            .method(Self::normalize, "normalize", 0)
-            .method(Self::pad_end, "padEnd", 1)
-            .method(Self::pad_start, "padStart", 1)
-            .method(Self::trim, "trim", 0)
-            .method(Self::to_case::<false>, "toLowerCase", 0)
-            .method(Self::to_case::<true>, "toUpperCase", 0)
-            .method(Self::to_locale_case::<false>, "toLocaleLowerCase", 0)
-            .method(Self::to_locale_case::<true>, "toLocaleUpperCase", 0)
-            .method(Self::substring, "substring", 2)
-            .method(Self::split, "split", 2)
-            .method(Self::value_of, "valueOf", 0)
-            .method(Self::match_all, "matchAll", 1)
-            .method(Self::replace, "replace", 2)
-            .method(Self::replace_all, "replaceAll", 2)
-            .method(Self::iterator, (symbol_iterator, "[Symbol.iterator]"), 0)
-            .method(Self::search, "search", 1)
-            .method(Self::at, "at", 1);
+        let builder = BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::STRING_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::STRING_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(0)
+        .property(trim_start)
+        .property(trim_end)
+        .static_method(Self::raw, 1)
+        .static_method(Self::from_char_code, 1)
+        .static_method(Self::from_code_point, 1)
+        .method(Self::char_at, 1)
+        .method(Self::char_code_at, 1)
+        .method(Self::code_point_at, 1)
+        .method(Self::to_string, 0)
+        .method(Self::concat, 1)
+        .method(Self::repeat, 1)
+        .method(Self::slice, 2)
+        .method(Self::starts_with, 1)
+        .method(Self::ends_with, 1)
+        .method(Self::includes, 1)
+        .method(Self::index_of, 1)
+        .method(Self::last_index_of, 1)
+        .method(Self::locale_compare, 1)
+        .method(Self::r#match, 1)
+        .method(Self::normalize, 0)
+        .method(Self::pad_end, 1)
+        .method(Self::pad_start, 1)
+        .method(Self::trim, 0)
+        .method(Self::to_case::<false>, 0)
+        .method(Self::to_case::<true>, 0)
+        .method(Self::to_locale_case::<false>, 0)
+        .method(Self::to_locale_case::<true>, 0)
+        .method(Self::substring, 2)
+        .method(Self::split, 2)
+        .method(Self::value_of, 0)
+        .method(Self::match_all, 1)
+        .method(Self::replace, 2)
+        .method(Self::replace_all, 2)
+        .method_with_name(Self::iterator, js_string!("[Symbol.iterator]"), 0)
+        .method(Self::search, 1)
+        .method(Self::at, 1);
 
         #[cfg(feature = "annex-b")]
         {
             builder
-                .property(
-                    utf16!("trimLeft"),
-                    trim_left,
-                    Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-                )
-                .property(
-                    utf16!("trimRight"),
-                    trim_right,
-                    Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-                )
-                .method(Self::substr, "substr", 2)
-                .method(Self::anchor, "anchor", 1)
-                .method(Self::big, "big", 0)
-                .method(Self::blink, "blink", 0)
-                .method(Self::bold, "bold", 0)
-                .method(Self::fixed, "fixed", 0)
-                .method(Self::fontcolor, "fontcolor", 1)
-                .method(Self::fontsize, "fontsize", 1)
-                .method(Self::italics, "italics", 0)
-                .method(Self::link, "link", 1)
-                .method(Self::small, "small", 0)
-                .method(Self::strike, "strike", 0)
-                .method(Self::sub, "sub", 0)
-                .method(Self::sup, "sup", 0)
+                .property(trim_left)
+                .property(trim_right)
+                .method(Self::substr, 2)
+                .method(Self::anchor, 1)
+                .method(Self::big, 0)
+                .method(Self::blink, 0)
+                .method(Self::bold, 0)
+                .method(Self::fixed, 0)
+                .method(Self::fontcolor, 1)
+                .method(Self::fontsize, 1)
+                .method(Self::italics, 0)
+                .method(Self::link, 1)
+                .method(Self::small, 0)
+                .method(Self::strike, 0)
+                .method(Self::sub, 0)
+                .method(Self::sup, 0)
                 .build();
         }
 
diff --git a/boa_engine/src/builtins/string/string_iterator.rs b/boa_engine/src/builtins/string/string_iterator.rs
index 52a8083a338..b218d6c2f7e 100644
--- a/boa_engine/src/builtins/string/string_iterator.rs
+++ b/boa_engine/src/builtins/string/string_iterator.rs
@@ -11,9 +11,7 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::{JsObject, ObjectData},
-    property::Attribute,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsResult, JsString, JsValue,
 };
 use boa_gc::{Finalize, Trace};
@@ -35,21 +33,20 @@ impl IntrinsicObject for StringIterator {
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event("StringIterator", "init");
 
-        BuiltInBuilder::with_intrinsic::<Self>(realm)
-            .prototype(
-                realm
-                    .intrinsics()
-                    .objects()
-                    .iterator_prototypes()
-                    .iterator(),
-            )
-            .static_method(Self::next, "next", 0)
-            .static_property(
-                JsSymbol::to_string_tag(),
-                "String Iterator",
-                Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::with_intrinsic_static_shape::<Self>(
+            realm,
+            &boa_builtins::COMMON_ITERATOR_PROTOTYPE_STATIC_SHAPE,
+        )
+        .prototype(
+            realm
+                .intrinsics()
+                .objects()
+                .iterator_prototypes()
+                .iterator(),
+        )
+        .static_method(Self::next, 0)
+        .static_property("String Iterator")
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/symbol/mod.rs b/boa_engine/src/builtins/symbol/mod.rs
index 64a5a56632e..3dd9d070329 100644
--- a/boa_engine/src/builtins/symbol/mod.rs
+++ b/boa_engine/src/builtins/symbol/mod.rs
@@ -26,9 +26,7 @@ use crate::{
     error::JsNativeError,
     js_string,
     object::JsObject,
-    property::Attribute,
     realm::Realm,
-    string::utf16,
     symbol::JsSymbol,
     value::JsValue,
     Context, JsArgs, JsResult, JsString,
@@ -109,8 +107,6 @@ impl IntrinsicObject for Symbol {
         let symbol_to_string_tag = JsSymbol::to_string_tag();
         let symbol_unscopables = JsSymbol::unscopables();
 
-        let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
-
         let to_primitive = BuiltInBuilder::callable(realm, Self::to_primitive)
             .name("[Symbol.toPrimitive]")
             .length(1)
@@ -120,53 +116,32 @@ impl IntrinsicObject for Symbol {
             .name("get description")
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_method(Self::for_, "for", 1)
-            .static_method(Self::key_for, "keyFor", 1)
-            .static_property(utf16!("asyncIterator"), symbol_async_iterator, attribute)
-            .static_property(utf16!("hasInstance"), symbol_has_instance, attribute)
-            .static_property(
-                utf16!("isConcatSpreadable"),
-                symbol_is_concat_spreadable,
-                attribute,
-            )
-            .static_property(utf16!("iterator"), symbol_iterator, attribute)
-            .static_property(utf16!("match"), symbol_match, attribute)
-            .static_property(utf16!("matchAll"), symbol_match_all, attribute)
-            .static_property(utf16!("replace"), symbol_replace, attribute)
-            .static_property(utf16!("search"), symbol_search, attribute)
-            .static_property(utf16!("species"), symbol_species, attribute)
-            .static_property(utf16!("split"), symbol_split, attribute)
-            .static_property(
-                utf16!("toPrimitive"),
-                symbol_to_primitive.clone(),
-                attribute,
-            )
-            .static_property(
-                utf16!("toStringTag"),
-                symbol_to_string_tag.clone(),
-                attribute,
-            )
-            .static_property(utf16!("unscopables"), symbol_unscopables, attribute)
-            .method(Self::to_string, "toString", 0)
-            .method(Self::value_of, "valueOf", 0)
-            .accessor(
-                utf16!("description"),
-                Some(get_description),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .property(
-                symbol_to_string_tag,
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .property(
-                symbol_to_primitive,
-                to_primitive,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::SYMBOL_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::SYMBOL_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_method(Self::for_, 1)
+        .static_method(Self::key_for, 1)
+        .static_property(symbol_async_iterator)
+        .static_property(symbol_has_instance)
+        .static_property(symbol_is_concat_spreadable)
+        .static_property(symbol_iterator)
+        .static_property(symbol_match)
+        .static_property(symbol_match_all)
+        .static_property(symbol_replace)
+        .static_property(symbol_search)
+        .static_property(symbol_species)
+        .static_property(symbol_split)
+        .static_property(symbol_to_primitive)
+        .static_property(symbol_to_string_tag)
+        .static_property(symbol_unscopables)
+        .method(Self::to_string, 0)
+        .method(Self::value_of, 0)
+        .accessor(Some(get_description), None)
+        .property(Self::NAME)
+        .property(to_primitive)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/typed_array/mod.rs b/boa_engine/src/builtins/typed_array/mod.rs
index e80ec6054b1..9b4bb202306 100644
--- a/boa_engine/src/builtins/typed_array/mod.rs
+++ b/boa_engine/src/builtins/typed_array/mod.rs
@@ -26,7 +26,6 @@ use crate::{
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData, ObjectKind},
     property::{Attribute, PropertyNameKind},
     realm::Realm,
-    string::utf16,
     symbol::JsSymbol,
     value::{IntegerOrInfinity, JsValue},
     Context, JsArgs, JsResult,
@@ -55,34 +54,25 @@ macro_rules! typed_array {
                     .name("get [Symbol.species]")
                     .build();
 
-                BuiltInBuilder::from_standard_constructor::<Self>(realm)
-                    .prototype(
-                        realm
-                            .intrinsics()
-                            .constructors()
-                            .typed_array()
-                            .constructor(),
-                    )
-                    .inherits(Some(
-                        realm.intrinsics().constructors().typed_array().prototype(),
-                    ))
-                    .static_accessor(
-                        JsSymbol::species(),
-                        Some(get_species),
-                        None,
-                        Attribute::CONFIGURABLE,
-                    )
-                    .property(
-                        utf16!("BYTES_PER_ELEMENT"),
-                        TypedArrayKind::$variant.element_size(),
-                        Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
-                    )
-                    .static_property(
-                        utf16!("BYTES_PER_ELEMENT"),
-                        TypedArrayKind::$variant.element_size(),
-                        Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
-                    )
-                    .build();
+                BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+                    realm,
+                    &boa_builtins::TYPED_ARRAY_INSTANCE_CONSTRUCTOR_STATIC_SHAPE,
+                    &boa_builtins::TYPED_ARRAY_INSTANCE_PROTOTYPE_STATIC_SHAPE,
+                )
+                .prototype(
+                    realm
+                        .intrinsics()
+                        .constructors()
+                        .typed_array()
+                        .constructor(),
+                )
+                .inherits(Some(
+                    realm.intrinsics().constructors().typed_array().prototype(),
+                ))
+                .static_accessor(Some(get_species), None)
+                .property(TypedArrayKind::$variant.element_size())
+                .static_property(TypedArrayKind::$variant.element_size())
+                .build();
             }
         }
 
@@ -269,79 +259,49 @@ impl IntrinsicObject for TypedArray {
             .length(0)
             .build();
 
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .static_accessor(
-                JsSymbol::species(),
-                Some(get_species),
-                None,
-                Attribute::CONFIGURABLE,
-            )
-            .property(
-                JsSymbol::iterator(),
-                values_function,
-                Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .accessor(
-                utf16!("buffer"),
-                Some(get_buffer),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .accessor(
-                utf16!("byteLength"),
-                Some(get_byte_length),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .accessor(
-                utf16!("byteOffset"),
-                Some(get_byte_offset),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .accessor(
-                utf16!("length"),
-                Some(get_length),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .accessor(
-                JsSymbol::to_string_tag(),
-                Some(get_to_string_tag),
-                None,
-                Attribute::CONFIGURABLE | Attribute::NON_ENUMERABLE,
-            )
-            .static_method(Self::from, "from", 1)
-            .static_method(Self::of, "of", 0)
-            .method(Self::at, "at", 1)
-            .method(Self::copy_within, "copyWithin", 2)
-            .method(Self::entries, "entries", 0)
-            .method(Self::every, "every", 1)
-            .method(Self::fill, "fill", 1)
-            .method(Self::filter, "filter", 1)
-            .method(Self::find, "find", 1)
-            .method(Self::findindex, "findIndex", 1)
-            .method(Self::foreach, "forEach", 1)
-            .method(Self::includes, "includes", 1)
-            .method(Self::index_of, "indexOf", 1)
-            .method(Self::join, "join", 1)
-            .method(Self::keys, "keys", 0)
-            .method(Self::last_index_of, "lastIndexOf", 1)
-            .method(Self::map, "map", 1)
-            .method(Self::reduce, "reduce", 1)
-            .method(Self::reduceright, "reduceRight", 1)
-            .method(Self::reverse, "reverse", 0)
-            .method(Self::set, "set", 1)
-            .method(Self::slice, "slice", 2)
-            .method(Self::some, "some", 1)
-            .method(Self::sort, "sort", 1)
-            .method(Self::subarray, "subarray", 2)
-            .method(Self::values, "values", 0)
-            // 23.2.3.29 %TypedArray%.prototype.toString ( )
-            // The initial value of the %TypedArray%.prototype.toString data property is the same
-            // built-in function object as the Array.prototype.toString method defined in 23.1.3.30.
-            .method(Array::to_string, "toString", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::TYPED_ARRAY_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::TYPED_ARRAY_PROTOTYPE_STATIC_SHAPE,
+        )
+        .static_accessor(Some(get_species), None)
+        .property(values_function)
+        .accessor(Some(get_buffer), None)
+        .accessor(Some(get_byte_length), None)
+        .accessor(Some(get_byte_offset), None)
+        .accessor(Some(get_length), None)
+        .accessor(Some(get_to_string_tag), None)
+        .static_method(Self::from, 1)
+        .static_method(Self::of, 0)
+        .method(Self::at, 1)
+        .method(Self::copy_within, 2)
+        .method(Self::entries, 0)
+        .method(Self::every, 1)
+        .method(Self::fill, 1)
+        .method(Self::filter, 1)
+        .method(Self::find, 1)
+        .method(Self::findindex, 1)
+        .method(Self::foreach, 1)
+        .method(Self::includes, 1)
+        .method(Self::index_of, 1)
+        .method(Self::join, 1)
+        .method(Self::keys, 0)
+        .method(Self::last_index_of, 1)
+        .method(Self::map, 1)
+        .method(Self::reduce, 1)
+        .method(Self::reduceright, 1)
+        .method(Self::reverse, 0)
+        .method(Self::set, 1)
+        .method(Self::slice, 2)
+        .method(Self::some, 1)
+        .method(Self::sort, 1)
+        .method(Self::subarray, 2)
+        .method(Self::values, 0)
+        // 23.2.3.29 %TypedArray%.prototype.toString ( )
+        // The initial value of the %TypedArray%.prototype.toString data property is the same
+        // built-in function object as the Array.prototype.toString method defined in 23.1.3.30.
+        .method(Array::to_string, 0)
+        .build();
     }
 
     fn get(intrinsics: &Intrinsics) -> JsObject {
diff --git a/boa_engine/src/builtins/uri/mod.rs b/boa_engine/src/builtins/uri/mod.rs
index d059fa98468..0c506cb94c5 100644
--- a/boa_engine/src/builtins/uri/mod.rs
+++ b/boa_engine/src/builtins/uri/mod.rs
@@ -50,10 +50,10 @@ pub struct UriFunctions {
 impl Default for UriFunctions {
     fn default() -> Self {
         Self {
-            decode_uri: JsFunction::empty_intrinsic_function(false),
-            decode_uri_component: JsFunction::empty_intrinsic_function(false),
-            encode_uri: JsFunction::empty_intrinsic_function(false),
-            encode_uri_component: JsFunction::empty_intrinsic_function(false),
+            decode_uri: JsFunction::empty_intrinsic_function_static_shape(false),
+            decode_uri_component: JsFunction::empty_intrinsic_function_static_shape(false),
+            encode_uri: JsFunction::empty_intrinsic_function_static_shape(false),
+            encode_uri_component: JsFunction::empty_intrinsic_function_static_shape(false),
         }
     }
 }
@@ -82,7 +82,7 @@ pub(crate) struct DecodeUri;
 
 impl IntrinsicObject for DecodeUri {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, decode_uri)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, decode_uri)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -100,7 +100,7 @@ pub(crate) struct DecodeUriComponent;
 
 impl IntrinsicObject for DecodeUriComponent {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, decode_uri_component)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, decode_uri_component)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -122,7 +122,7 @@ pub(crate) struct EncodeUri;
 
 impl IntrinsicObject for EncodeUri {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, encode_uri)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, encode_uri)
             .name(Self::NAME)
             .length(1)
             .build();
@@ -139,7 +139,7 @@ pub(crate) struct EncodeUriComponent;
 
 impl IntrinsicObject for EncodeUriComponent {
     fn init(realm: &Realm) {
-        BuiltInBuilder::callable_with_intrinsic::<Self>(realm, encode_uri_component)
+        BuiltInBuilder::callable_intrinsic::<Self>(realm, encode_uri_component)
             .name(Self::NAME)
             .length(1)
             .build();
diff --git a/boa_engine/src/builtins/weak/weak_ref.rs b/boa_engine/src/builtins/weak/weak_ref.rs
index 4ec3bbe1cee..e126f7f23ff 100644
--- a/boa_engine/src/builtins/weak/weak_ref.rs
+++ b/boa_engine/src/builtins/weak/weak_ref.rs
@@ -1,4 +1,5 @@
 use boa_gc::{Finalize, Trace, WeakGc};
+use boa_macros::utf16;
 use boa_profiler::Profiler;
 
 use crate::{
@@ -7,7 +8,6 @@ use crate::{
     object::{internal_methods::get_prototype_from_constructor, JsObject, ObjectData},
     property::Attribute,
     realm::Realm,
-    symbol::JsSymbol,
     Context, JsArgs, JsNativeError, JsResult, JsValue,
 };
 
@@ -31,14 +31,14 @@ impl IntrinsicObject for WeakRef {
 
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .property(
-                JsSymbol::to_string_tag(),
-                "WeakRef",
-                Attribute::CONFIGURABLE,
-            )
-            .method(Self::deref, "deref", 0)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::WEAK_REF_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::WEAK_REF_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(utf16!("WeakRef"))
+        .method(Self::deref, 0)
+        .build();
     }
 }
 
diff --git a/boa_engine/src/builtins/weak_map/mod.rs b/boa_engine/src/builtins/weak_map/mod.rs
index 66f5e5aed42..8d4b6f688c8 100644
--- a/boa_engine/src/builtins/weak_map/mod.rs
+++ b/boa_engine/src/builtins/weak_map/mod.rs
@@ -17,7 +17,6 @@ use crate::{
     property::Attribute,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     Context, JsArgs, JsNativeError, JsResult, JsValue,
 };
 use boa_gc::{Finalize, Trace};
@@ -33,17 +32,17 @@ impl IntrinsicObject for WeakMap {
 
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .method(Self::delete, "delete", 1)
-            .method(Self::get, "get", 1)
-            .method(Self::has, "has", 1)
-            .method(Self::set, "set", 2)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::WEAK_MAP_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::WEAK_MAP_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(Self::NAME)
+        .method(Self::delete, 1)
+        .method(Self::get, 1)
+        .method(Self::has, 1)
+        .method(Self::set, 2)
+        .build();
     }
 }
 
diff --git a/boa_engine/src/builtins/weak_set/mod.rs b/boa_engine/src/builtins/weak_set/mod.rs
index 13304a39f8e..885f5556b8c 100644
--- a/boa_engine/src/builtins/weak_set/mod.rs
+++ b/boa_engine/src/builtins/weak_set/mod.rs
@@ -14,7 +14,6 @@ use crate::{
     property::Attribute,
     realm::Realm,
     string::utf16,
-    symbol::JsSymbol,
     Context, JsArgs, JsNativeError, JsResult, JsValue,
 };
 use boa_gc::{Finalize, Trace, WeakMap};
@@ -30,16 +29,16 @@ impl IntrinsicObject for WeakSet {
 
     fn init(realm: &Realm) {
         let _timer = Profiler::global().start_event(Self::NAME, "init");
-        BuiltInBuilder::from_standard_constructor::<Self>(realm)
-            .property(
-                JsSymbol::to_string_tag(),
-                Self::NAME,
-                Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
-            )
-            .method(Self::add, "add", 1)
-            .method(Self::delete, "delete", 1)
-            .method(Self::has, "has", 1)
-            .build();
+        BuiltInBuilder::from_standard_constructor_static_shape::<Self>(
+            realm,
+            &boa_builtins::WEAK_SET_CONSTRUCTOR_STATIC_SHAPE,
+            &boa_builtins::WEAK_SET_PROTOTYPE_STATIC_SHAPE,
+        )
+        .property(Self::NAME)
+        .method(Self::add, 1)
+        .method(Self::delete, 1)
+        .method(Self::has, 1)
+        .build();
     }
 }
 
diff --git a/boa_engine/src/context/intrinsics.rs b/boa_engine/src/context/intrinsics.rs
index 92d3c825d5c..228fb0a091f 100644
--- a/boa_engine/src/context/intrinsics.rs
+++ b/boa_engine/src/context/intrinsics.rs
@@ -75,11 +75,18 @@ impl StandardConstructor {
     /// Build a constructor with a defined prototype.
     fn with_prototype(prototype: JsObject) -> Self {
         Self {
-            constructor: JsFunction::empty_intrinsic_function(true),
+            constructor: JsFunction::empty_intrinsic_function_static_shape(true),
             prototype,
         }
     }
 
+    fn default_static_shape() -> Self {
+        Self {
+            constructor: JsFunction::empty_intrinsic_function_static_shape(true),
+            prototype: JsObject::default_with_static_shape(),
+        }
+    }
+
     /// Return the prototype of the constructor object.
     ///
     /// This is the same as `Object.prototype`, `Array.prototype`, etc
@@ -156,67 +163,62 @@ pub struct StandardConstructors {
 impl Default for StandardConstructors {
     fn default() -> Self {
         Self {
-            object: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
-                None,
-                ObjectData::object_prototype(),
-            )),
+            object: StandardConstructor::with_prototype(
+                JsObject::from_data_and_empty_static_shape(ObjectData::object_prototype()),
+            ),
             async_generator_function: StandardConstructor::default(),
             proxy: StandardConstructor::default(),
-            date: StandardConstructor::default(),
+            date: StandardConstructor::default_static_shape(),
             function: StandardConstructor {
-                constructor: JsFunction::empty_intrinsic_function(true),
-                prototype: JsFunction::empty_intrinsic_function(false).into(),
+                constructor: JsFunction::empty_intrinsic_function_static_shape(true),
+                prototype: JsFunction::empty_intrinsic_function_static_shape(false).into(),
             },
             async_function: StandardConstructor::default(),
-            generator_function: StandardConstructor::default(),
-            array: StandardConstructor::with_prototype(JsObject::from_proto_and_data(
-                None,
+            generator_function: StandardConstructor::default_static_shape(),
+            array: StandardConstructor::with_prototype(JsObject::from_data_and_empty_static_shape(
                 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(),
+            bigint: StandardConstructor::default_static_shape(),
+            number: StandardConstructor::with_prototype(
+                JsObject::from_data_and_empty_static_shape(ObjectData::number(0.0)),
+            ),
+            boolean: StandardConstructor::with_prototype(
+                JsObject::from_data_and_empty_static_shape(ObjectData::boolean(false)),
+            ),
+            string: StandardConstructor::with_prototype(
+                JsObject::from_data_and_empty_static_shape(ObjectData::string("".into())),
+            ),
+            regexp: StandardConstructor::default_static_shape(),
+            symbol: StandardConstructor::default_static_shape(),
+            error: StandardConstructor::default_static_shape(),
+            type_error: StandardConstructor::default_static_shape(),
+            reference_error: StandardConstructor::default_static_shape(),
+            range_error: StandardConstructor::default_static_shape(),
+            syntax_error: StandardConstructor::default_static_shape(),
+            eval_error: StandardConstructor::default_static_shape(),
+            uri_error: StandardConstructor::default_static_shape(),
+            aggregate_error: StandardConstructor::default_static_shape(),
+            map: StandardConstructor::default_static_shape(),
+            set: StandardConstructor::default_static_shape(),
+            typed_array: StandardConstructor::default_static_shape(),
+            typed_int8_array: StandardConstructor::default_static_shape(),
+            typed_uint8_array: StandardConstructor::default_static_shape(),
+            typed_uint8clamped_array: StandardConstructor::default_static_shape(),
+            typed_int16_array: StandardConstructor::default_static_shape(),
+            typed_uint16_array: StandardConstructor::default_static_shape(),
+            typed_int32_array: StandardConstructor::default_static_shape(),
+            typed_uint32_array: StandardConstructor::default_static_shape(),
+            typed_bigint64_array: StandardConstructor::default_static_shape(),
+            typed_biguint64_array: StandardConstructor::default_static_shape(),
+            typed_float32_array: StandardConstructor::default_static_shape(),
+            typed_float64_array: StandardConstructor::default_static_shape(),
+            array_buffer: StandardConstructor::default_static_shape(),
+            data_view: StandardConstructor::default_static_shape(),
             date_time_format: StandardConstructor::default(),
-            promise: StandardConstructor::default(),
-            weak_ref: StandardConstructor::default(),
-            weak_map: StandardConstructor::default(),
-            weak_set: StandardConstructor::default(),
+            promise: StandardConstructor::default_static_shape(),
+            weak_ref: StandardConstructor::default_static_shape(),
+            weak_map: StandardConstructor::default_static_shape(),
+            weak_set: StandardConstructor::default_static_shape(),
             #[cfg(feature = "intl")]
             collator: StandardConstructor::default(),
             #[cfg(feature = "intl")]
@@ -817,24 +819,24 @@ pub struct IntrinsicObjects {
 impl Default for IntrinsicObjects {
     fn default() -> Self {
         Self {
-            reflect: JsObject::default(),
-            math: JsObject::default(),
-            json: JsObject::default(),
+            reflect: JsObject::default_with_static_shape(),
+            math: JsObject::default_with_static_shape(),
+            json: JsObject::default_with_static_shape(),
             throw_type_error: JsFunction::empty_intrinsic_function(false),
-            array_prototype_values: JsFunction::empty_intrinsic_function(false),
+            array_prototype_values: JsFunction::empty_intrinsic_function_static_shape(false),
             iterator_prototypes: IteratorPrototypes::default(),
             generator: JsObject::default(),
             async_generator: JsObject::default(),
-            eval: JsFunction::empty_intrinsic_function(false),
+            eval: JsFunction::empty_intrinsic_function_static_shape(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),
+            is_finite: JsFunction::empty_intrinsic_function_static_shape(false),
+            is_nan: JsFunction::empty_intrinsic_function_static_shape(false),
+            parse_float: JsFunction::empty_intrinsic_function_static_shape(false),
+            parse_int: JsFunction::empty_intrinsic_function_static_shape(false),
             #[cfg(feature = "annex-b")]
-            escape: JsFunction::empty_intrinsic_function(false),
+            escape: JsFunction::empty_intrinsic_function_static_shape(false),
             #[cfg(feature = "annex-b")]
-            unescape: JsFunction::empty_intrinsic_function(false),
+            unescape: JsFunction::empty_intrinsic_function_static_shape(false),
             #[cfg(feature = "intl")]
             intl: JsObject::default(),
             #[cfg(feature = "intl")]
diff --git a/boa_engine/src/object/builtins/jsfunction.rs b/boa_engine/src/object/builtins/jsfunction.rs
index 522242acc69..26a5fa6b988 100644
--- a/boa_engine/src/object/builtins/jsfunction.rs
+++ b/boa_engine/src/object/builtins/jsfunction.rs
@@ -40,6 +40,19 @@ impl JsFunction {
         }
     }
 
+    pub(crate) fn empty_intrinsic_function_static_shape(constructor: bool) -> Self {
+        Self {
+            inner: JsObject::from_object_and_vtable(
+                Object::with_empty_shape(),
+                if constructor {
+                    &CONSTRUCTOR_INTERNAL_METHODS
+                } else {
+                    &FUNCTION_INTERNAL_METHODS
+                },
+            ),
+        }
+    }
+
     /// Creates a [`JsFunction`] from a [`JsObject`], or returns `None` if the object is not a function.
     ///
     /// This does not clone the fields of the function, it only does a shallow clone of the object.
diff --git a/boa_engine/src/object/jsobject.rs b/boa_engine/src/object/jsobject.rs
index 56eed871442..26f54e066c6 100644
--- a/boa_engine/src/object/jsobject.rs
+++ b/boa_engine/src/object/jsobject.rs
@@ -4,7 +4,7 @@
 
 use super::{
     internal_methods::{InternalObjectMethods, ARRAY_EXOTIC_INTERNAL_METHODS},
-    shape::RootShape,
+    shape::{static_shape::StaticShape, RootShape},
     JsPrototype, NativeObject, Object, PrivateName, PropertyMap,
 };
 use crate::{
@@ -60,6 +60,12 @@ impl Default for JsObject {
 }
 
 impl JsObject {
+    /// TODO: doc
+    pub(crate) fn default_with_static_shape() -> Self {
+        let data = ObjectData::ordinary();
+        Self::from_object_and_vtable(Object::with_empty_shape(), data.internal_methods)
+    }
+
     /// Creates a new `JsObject` from its inner object and its vtable.
     pub(crate) fn from_object_and_vtable(
         object: Object,
@@ -120,6 +126,23 @@ impl JsObject {
         }
     }
 
+    pub(crate) fn from_data_and_empty_static_shape(data: ObjectData) -> Self {
+        Self {
+            inner: Gc::new(VTableObject {
+                object: GcRefCell::new(Object {
+                    kind: data.kind,
+                    properties: PropertyMap::new(
+                        StaticShape::new(&boa_builtins::EMPTY_OBJECT_STATIC_SHAPE).into(),
+                        ThinVec::default(),
+                    ),
+                    extensible: true,
+                    private_elements: ThinVec::new(),
+                }),
+                vtable: data.internal_methods,
+            }),
+        }
+    }
+
     /// Creates a new object with the provided prototype and object data.
     ///
     /// This is equivalent to calling the specification's abstract operation [`OrdinaryObjectCreate`],
diff --git a/boa_engine/src/object/mod.rs b/boa_engine/src/object/mod.rs
index 74f123105ac..8e6df742a99 100644
--- a/boa_engine/src/object/mod.rs
+++ b/boa_engine/src/object/mod.rs
@@ -26,7 +26,7 @@ use self::{
         string::STRING_EXOTIC_INTERNAL_METHODS,
         InternalObjectMethods, ORDINARY_INTERNAL_METHODS,
     },
-    shape::Shape,
+    shape::{static_shape::StaticShape, Shape},
 };
 #[cfg(feature = "intl")]
 use crate::builtins::intl::{
@@ -873,6 +873,18 @@ impl Debug for ObjectKind {
 }
 
 impl Object {
+    fn with_empty_shape() -> Self {
+        Self {
+            kind: ObjectKind::Ordinary,
+            properties: PropertyMap::new(
+                StaticShape::new(&boa_builtins::EMPTY_OBJECT_STATIC_SHAPE).into(),
+                ThinVec::default(),
+            ),
+            extensible: true,
+            private_elements: ThinVec::new(),
+        }
+    }
+
     /// Returns a mutable reference to the kind of an object.
     pub(crate) fn kind_mut(&mut self) -> &mut ObjectKind {
         &mut self.kind
@@ -1524,6 +1536,12 @@ impl Object {
     /// Gets the prototype instance of this object.
     #[inline]
     pub fn prototype(&self) -> JsPrototype {
+        // If it is static then the prototype is stored on the (len - 1) position.
+        if self.properties.shape.is_static() {
+            return self.properties.storage[self.properties.storage.len() - 1]
+                .as_object()
+                .cloned();
+        }
         self.properties.shape.prototype()
     }
 
@@ -1536,7 +1554,14 @@ impl Object {
     pub fn set_prototype<O: Into<JsPrototype>>(&mut self, prototype: O) -> bool {
         let prototype = prototype.into();
         if self.extensible {
-            self.properties.shape = self.properties.shape.change_prototype_transition(prototype);
+            if let Some(shape) = self.properties.shape.as_static() {
+                self.properties.storage.pop();
+                self.properties.shape = shape.to_unique(prototype).into();
+            } else {
+                self.properties.shape =
+                    self.properties.shape.change_prototype_transition(prototype);
+            }
+
             true
         } else {
             // If target is non-extensible, [[SetPrototypeOf]] must return false
diff --git a/boa_engine/src/object/property_map.rs b/boa_engine/src/object/property_map.rs
index 9a06080a130..9ee225e0daa 100644
--- a/boa_engine/src/object/property_map.rs
+++ b/boa_engine/src/object/property_map.rs
@@ -314,7 +314,21 @@ impl PropertyMap {
                     property_key: key.clone(),
                     attributes,
                 };
-                let transition = self.shape.change_attributes_transition(key);
+
+                let transition = if let Some(shape) = self.shape.as_static() {
+                    let prototype = self
+                        .storage
+                        .pop()
+                        .as_ref()
+                        .and_then(JsValue::as_object)
+                        .cloned();
+                    shape
+                        .to_unique(prototype)
+                        .change_attributes_transition(&key)
+                } else {
+                    self.shape.change_attributes_transition(key)
+                };
+
                 self.shape = transition.shape;
                 match transition.action {
                     ChangeTransitionAction::Nothing => {}
@@ -349,6 +363,17 @@ impl PropertyMap {
             return true;
         }
 
+        // TODO: optimization, we could inline `insert_property_transition` to avoid the check
+        if let Some(shape) = self.shape.as_static() {
+            let prototype = self
+                .storage
+                .pop()
+                .as_ref()
+                .and_then(JsValue::as_object)
+                .cloned();
+            self.shape = shape.to_unique(prototype).into();
+        }
+
         let transition_key = TransitionKey {
             property_key: key.clone(),
             attributes,
@@ -393,6 +418,17 @@ impl PropertyMap {
             return self.indexed_properties.remove(*index);
         }
         if let Some(slot) = self.shape.lookup(key) {
+            if let Some(shape) = self.shape.as_static() {
+                let prototype = self
+                    .storage
+                    .pop()
+                    .as_ref()
+                    .and_then(JsValue::as_object)
+                    .cloned();
+
+                self.shape = shape.to_unique(prototype).into();
+            }
+
             // shift all elements when removing.
             if slot.attributes.is_accessor_descriptor() {
                 self.storage.remove(slot.index as usize + 1);
diff --git a/boa_engine/src/object/shape/mod.rs b/boa_engine/src/object/shape/mod.rs
index 352ca91567c..afbb477c059 100644
--- a/boa_engine/src/object/shape/mod.rs
+++ b/boa_engine/src/object/shape/mod.rs
@@ -4,6 +4,7 @@ pub(crate) mod property_table;
 mod root_shape;
 pub(crate) mod shared_shape;
 pub(crate) mod slot;
+pub(crate) mod static_shape;
 pub(crate) mod unique_shape;
 
 pub use root_shape::RootShape;
@@ -16,7 +17,7 @@ use boa_gc::{Finalize, Trace};
 
 use crate::property::PropertyKey;
 
-use self::{shared_shape::TransitionKey, slot::Slot};
+use self::{shared_shape::TransitionKey, slot::Slot, static_shape::StaticShape};
 
 use super::JsPrototype;
 
@@ -56,6 +57,7 @@ pub(crate) struct ChangeTransition<T> {
 enum Inner {
     Unique(UniqueShape),
     Shared(SharedShape),
+    Static(StaticShape),
 }
 
 /// Represents the shape of an object.
@@ -84,12 +86,26 @@ impl Shape {
         matches!(self.inner, Inner::Shared(_))
     }
 
+    /// Returns `true` if it's a static shape, `false` otherwise.
+    pub(crate) const fn as_static(&self) -> Option<&StaticShape> {
+        if let Inner::Static(shape) = &self.inner {
+            return Some(shape);
+        }
+        None
+    }
+
     /// Returns `true` if it's a unique shape, `false` otherwise.
     #[inline]
     pub const fn is_unique(&self) -> bool {
         matches!(self.inner, Inner::Unique(_))
     }
 
+    /// Returns `true` if it's a static shape, `false` otherwise.
+    #[inline]
+    pub const fn is_static(&self) -> bool {
+        matches!(self.inner, Inner::Static(_))
+    }
+
     pub(crate) const fn as_unique(&self) -> Option<&UniqueShape> {
         if let Inner::Unique(shape) = &self.inner {
             return Some(shape);
@@ -110,6 +126,7 @@ impl Shape {
                 shape.into()
             }
             Inner::Unique(shape) => shape.insert_property_transition(key).into(),
+            Inner::Static(shape) => shape.insert_property_transition(key).into(),
         }
     }
 
@@ -136,6 +153,7 @@ impl Shape {
                 }
             }
             Inner::Unique(shape) => shape.change_attributes_transition(&key),
+            Inner::Static(shape) => shape.change_attributes_transition(&key),
         }
     }
 
@@ -152,6 +170,7 @@ impl Shape {
                 shape.into()
             }
             Inner::Unique(shape) => shape.remove_property_transition(key).into(),
+            Inner::Static(shape) => shape.remove_property_transition(key).into(),
         }
     }
 
@@ -166,14 +185,16 @@ impl Shape {
                 shape.into()
             }
             Inner::Unique(shape) => shape.change_prototype_transition(prototype).into(),
+            Inner::Static(shape) => shape.change_prototype_transition(prototype).into(),
         }
     }
 
     /// Get the [`JsPrototype`] of the [`Shape`].
-    pub fn prototype(&self) -> JsPrototype {
+    pub(crate) fn prototype(&self) -> JsPrototype {
         match &self.inner {
             Inner::Shared(shape) => shape.prototype(),
             Inner::Unique(shape) => shape.prototype(),
+            Inner::Static(_) => unreachable!("Static shapes don't have prototypes in them"),
         }
     }
 
@@ -183,6 +204,7 @@ impl Shape {
         match &self.inner {
             Inner::Shared(shape) => shape.lookup(key),
             Inner::Unique(shape) => shape.lookup(key),
+            Inner::Static(shape) => shape.lookup(key),
         }
     }
 
@@ -192,6 +214,7 @@ impl Shape {
         match &self.inner {
             Inner::Shared(shape) => shape.keys(),
             Inner::Unique(shape) => shape.keys(),
+            Inner::Static(shape) => shape.keys(),
         }
     }
 
@@ -201,6 +224,7 @@ impl Shape {
         match &self.inner {
             Inner::Shared(shape) => shape.to_addr_usize(),
             Inner::Unique(shape) => shape.to_addr_usize(),
+            Inner::Static(shape) => shape.to_addr_usize(),
         }
     }
 }
@@ -220,3 +244,11 @@ impl From<SharedShape> for Shape {
         }
     }
 }
+
+impl From<StaticShape> for Shape {
+    fn from(shape: StaticShape) -> Self {
+        Self {
+            inner: Inner::Static(shape),
+        }
+    }
+}
diff --git a/boa_engine/src/object/shape/slot.rs b/boa_engine/src/object/shape/slot.rs
index 64fb3c8f43f..16800b72dce 100644
--- a/boa_engine/src/object/shape/slot.rs
+++ b/boa_engine/src/object/shape/slot.rs
@@ -42,7 +42,7 @@ impl SlotAttributes {
 ///
 /// Slots can have different width depending on its attributes, accessors properties have width `2`,
 /// while data properties have width `1`.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub(crate) struct Slot {
     pub(crate) index: SlotIndex,
     pub(crate) attributes: SlotAttributes,
diff --git a/boa_engine/src/object/shape/static_shape.rs b/boa_engine/src/object/shape/static_shape.rs
new file mode 100644
index 00000000000..0277ef4d745
--- /dev/null
+++ b/boa_engine/src/object/shape/static_shape.rs
@@ -0,0 +1,149 @@
+// Temp allow
+#![allow(dead_code)]
+#![allow(clippy::needless_pass_by_value)]
+
+use std::fmt::Debug;
+
+use boa_builtins::{EncodedStaticPropertyKey, StaticPropertyKey};
+use boa_gc::{Finalize, Trace};
+
+use crate::{
+    object::shape::property_table::PropertyTableInner, property::PropertyKey, symbol::WellKnown,
+    JsString, 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(index) => {
+            PropertyKey::String(unsafe { JsString::from_index(index) })
+        }
+        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_static_string_index()?)),
+        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)?;
+
+        let (index, attributes) = self.inner.get(key)?;
+
+        Some(Slot {
+            index: u32::from(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
+            .property_table
+            .keys()
+            .map(EncodedStaticPropertyKey::decode)
+            .map(from_static_property_key)
+            .collect()
+    }
+
+    /// TODO: doc
+    pub(crate) fn to_unique(&self, prototype: JsPrototype) -> UniqueShape {
+        // TODO: optimization, preallocate capacity.
+        // TODO: optimization, direct iniitialize the map.
+        let mut property_table = PropertyTableInner::default();
+        for (key, (_, slot_attributes)) in &self.inner.property_table {
+            property_table.insert(
+                from_static_property_key(key.decode()),
+                SlotAttributes::from_bits_retain(slot_attributes.bits()),
+            );
+        }
+        UniqueShape::new(prototype, property_table)
+    }
+
+    /// Return location in memory of the [`UniqueShape`].
+    pub(crate) fn to_addr_usize(&self) -> usize {
+        let ptr: *const _ = self.inner;
+        ptr as usize
+    }
+}
diff --git a/boa_engine/src/string/common.rs b/boa_engine/src/string/common.rs
index 50a3b711e89..3fabd2f543e 100644
--- a/boa_engine/src/string/common.rs
+++ b/boa_engine/src/string/common.rs
@@ -6,6 +6,8 @@ use super::JsString;
 use boa_macros::utf16;
 use rustc_hash::{FxHashMap, FxHasher};
 
+use boa_builtins::RAW_STATICS;
+
 macro_rules! well_known_statics {
     ( $( $(#[$attr:meta])* ($name:ident, $string:literal) ),+$(,)? ) => {
         $(
@@ -134,466 +136,3 @@ thread_local! {
         constants
     };
 }
-
-/// Array of raw static strings that aren't reference counted.
-///
-/// The macro `static_strings` automatically sorts the array of strings, making it faster
-/// for searches by using `binary_search`.
-const RAW_STATICS: &[&[u16]] = &[
-    utf16!(""),
-    // Misc
-    utf16!(","),
-    utf16!(":"),
-    // Generic use
-    utf16!("name"),
-    utf16!("length"),
-    utf16!("arguments"),
-    utf16!("prototype"),
-    utf16!("constructor"),
-    utf16!("return"),
-    utf16!("throw"),
-    utf16!("global"),
-    utf16!("globalThis"),
-    // typeof
-    utf16!("null"),
-    utf16!("undefined"),
-    utf16!("number"),
-    utf16!("string"),
-    utf16!("symbol"),
-    utf16!("bigint"),
-    utf16!("object"),
-    utf16!("function"),
-    // Property descriptor
-    utf16!("value"),
-    utf16!("get"),
-    utf16!("set"),
-    utf16!("writable"),
-    utf16!("enumerable"),
-    utf16!("configurable"),
-    // Object object
-    utf16!("Object"),
-    utf16!("assign"),
-    utf16!("create"),
-    utf16!("toString"),
-    utf16!("valueOf"),
-    utf16!("is"),
-    utf16!("seal"),
-    utf16!("isSealed"),
-    utf16!("freeze"),
-    utf16!("isFrozen"),
-    utf16!("isExtensible"),
-    utf16!("hasOwnProperty"),
-    utf16!("isPrototypeOf"),
-    utf16!("setPrototypeOf"),
-    utf16!("getPrototypeOf"),
-    utf16!("defineProperty"),
-    utf16!("defineProperties"),
-    utf16!("deleteProperty"),
-    utf16!("construct"),
-    utf16!("hasOwn"),
-    utf16!("ownKeys"),
-    utf16!("keys"),
-    utf16!("values"),
-    utf16!("entries"),
-    utf16!("fromEntries"),
-    // Function object
-    utf16!("Function"),
-    utf16!("apply"),
-    utf16!("bind"),
-    utf16!("call"),
-    // Generator object
-    utf16!("Generator"),
-    // Array object
-    utf16!("Array"),
-    utf16!("at"),
-    utf16!("from"),
-    utf16!("isArray"),
-    utf16!("of"),
-    utf16!("copyWithin"),
-    utf16!("every"),
-    utf16!("fill"),
-    utf16!("filter"),
-    utf16!("find"),
-    utf16!("findIndex"),
-    utf16!("findLast"),
-    utf16!("findLastIndex"),
-    utf16!("flat"),
-    utf16!("flatMap"),
-    utf16!("forEach"),
-    utf16!("includes"),
-    utf16!("indexOf"),
-    utf16!("join"),
-    utf16!("map"),
-    utf16!("next"),
-    utf16!("reduce"),
-    utf16!("reduceRight"),
-    utf16!("reverse"),
-    utf16!("shift"),
-    utf16!("slice"),
-    utf16!("splice"),
-    utf16!("some"),
-    utf16!("sort"),
-    utf16!("unshift"),
-    utf16!("push"),
-    utf16!("pop"),
-    // String object
-    utf16!("String"),
-    utf16!("charAt"),
-    utf16!("charCodeAt"),
-    utf16!("codePointAt"),
-    utf16!("concat"),
-    utf16!("endsWith"),
-    utf16!("fromCharCode"),
-    utf16!("fromCodePoint"),
-    utf16!("lastIndexOf"),
-    utf16!("match"),
-    utf16!("matchAll"),
-    utf16!("normalize"),
-    utf16!("padEnd"),
-    utf16!("padStart"),
-    utf16!("raw"),
-    utf16!("repeat"),
-    utf16!("replace"),
-    utf16!("replaceAll"),
-    utf16!("search"),
-    utf16!("split"),
-    utf16!("startsWith"),
-    utf16!("substr"),
-    utf16!("substring"),
-    utf16!("toLocaleString"),
-    utf16!("toLowerCase"),
-    utf16!("toUpperCase"),
-    utf16!("trim"),
-    utf16!("trimEnd"),
-    utf16!("trimStart"),
-    // Number object
-    utf16!("Number"),
-    utf16!("Infinity"),
-    utf16!("NaN"),
-    utf16!("parseInt"),
-    utf16!("parseFloat"),
-    utf16!("isFinite"),
-    utf16!("isNaN"),
-    utf16!("EPSILON"),
-    utf16!("MAX_SAFE_INTEGER"),
-    utf16!("MIN_SAFE_INTEGER"),
-    utf16!("MAX_VALUE"),
-    utf16!("MIN_VALUE"),
-    utf16!("isSafeInteger"),
-    utf16!("isInteger"),
-    utf16!("toExponential"),
-    utf16!("toFixed"),
-    utf16!("toPrecision"),
-    // Boolean object
-    utf16!("Boolean"),
-    // BigInt object
-    utf16!("BigInt"),
-    utf16!("asIntN"),
-    utf16!("asUintN"),
-    // RegExp object
-    utf16!("RegExp"),
-    utf16!("exec"),
-    utf16!("test"),
-    utf16!("flags"),
-    utf16!("index"),
-    utf16!("lastIndex"),
-    utf16!("hasIndices"),
-    utf16!("ignoreCase"),
-    utf16!("multiline"),
-    utf16!("dotAll"),
-    utf16!("unicode"),
-    utf16!("sticky"),
-    utf16!("source"),
-    utf16!("get hasIndices"),
-    utf16!("get global"),
-    utf16!("get ignoreCase"),
-    utf16!("get multiline"),
-    utf16!("get dotAll"),
-    utf16!("get unicode"),
-    utf16!("get sticky"),
-    utf16!("get flags"),
-    utf16!("get source"),
-    // Symbol object
-    utf16!("Symbol"),
-    utf16!("for"),
-    utf16!("keyFor"),
-    utf16!("description"),
-    utf16!("asyncIterator"),
-    utf16!("hasInstance"),
-    utf16!("species"),
-    utf16!("unscopables"),
-    utf16!("iterator"),
-    utf16!("toStringTag"),
-    utf16!("toPrimitive"),
-    utf16!("get description"),
-    // Map object
-    utf16!("Map"),
-    utf16!("clear"),
-    utf16!("delete"),
-    utf16!("has"),
-    utf16!("size"),
-    // Set object
-    utf16!("Set"),
-    utf16!("add"),
-    // Reflect object
-    utf16!("Reflect"),
-    // Proxy object
-    utf16!("Proxy"),
-    utf16!("revocable"),
-    // Error objects
-    utf16!("Error"),
-    utf16!("AggregateError"),
-    utf16!("TypeError"),
-    utf16!("RangeError"),
-    utf16!("SyntaxError"),
-    utf16!("ReferenceError"),
-    utf16!("EvalError"),
-    utf16!("ThrowTypeError"),
-    utf16!("URIError"),
-    utf16!("message"),
-    // Date object
-    utf16!("Date"),
-    utf16!("toJSON"),
-    utf16!("getDate"),
-    utf16!("getDay"),
-    utf16!("getFullYear"),
-    utf16!("getHours"),
-    utf16!("getMilliseconds"),
-    utf16!("getMinutes"),
-    utf16!("getMonth"),
-    utf16!("getSeconds"),
-    utf16!("getTime"),
-    utf16!("getYear"),
-    utf16!("getUTCDate"),
-    utf16!("getUTCDay"),
-    utf16!("getUTCFullYear"),
-    utf16!("getUTCHours"),
-    utf16!("getUTCMinutes"),
-    utf16!("getUTCMonth"),
-    utf16!("getUTCSeconds"),
-    utf16!("setDate"),
-    utf16!("setFullYear"),
-    utf16!("setHours"),
-    utf16!("setMilliseconds"),
-    utf16!("setMinutes"),
-    utf16!("setMonth"),
-    utf16!("setSeconds"),
-    utf16!("setYear"),
-    utf16!("setTime"),
-    utf16!("setUTCDate"),
-    utf16!("setUTCFullYear"),
-    utf16!("setUTCHours"),
-    utf16!("setUTCMinutes"),
-    utf16!("setUTCMonth"),
-    utf16!("setUTCSeconds"),
-    utf16!("toDateString"),
-    utf16!("toGMTString"),
-    utf16!("toISOString"),
-    utf16!("toTimeString"),
-    utf16!("toUTCString"),
-    utf16!("now"),
-    utf16!("UTC"),
-    // JSON object
-    utf16!("JSON"),
-    utf16!("parse"),
-    utf16!("stringify"),
-    // Iterator object
-    utf16!("Array Iterator"),
-    utf16!("Set Iterator"),
-    utf16!("String Iterator"),
-    utf16!("Map Iterator"),
-    utf16!("For In Iterator"),
-    // Math object
-    utf16!("Math"),
-    utf16!("LN10"),
-    utf16!("LN2"),
-    utf16!("LOG10E"),
-    utf16!("LOG2E"),
-    utf16!("PI"),
-    utf16!("SQRT1_2"),
-    utf16!("SQRT2"),
-    utf16!("abs"),
-    utf16!("acos"),
-    utf16!("acosh"),
-    utf16!("asin"),
-    utf16!("asinh"),
-    utf16!("atan"),
-    utf16!("atanh"),
-    utf16!("atan2"),
-    utf16!("cbrt"),
-    utf16!("ceil"),
-    utf16!("clz32"),
-    utf16!("cos"),
-    utf16!("cosh"),
-    utf16!("exp"),
-    utf16!("expm1"),
-    utf16!("floor"),
-    utf16!("fround"),
-    utf16!("hypot"),
-    utf16!("imul"),
-    utf16!("log"),
-    utf16!("log1p"),
-    utf16!("log10"),
-    utf16!("log2"),
-    utf16!("max"),
-    utf16!("min"),
-    utf16!("pow"),
-    utf16!("random"),
-    utf16!("round"),
-    utf16!("sign"),
-    utf16!("sin"),
-    utf16!("sinh"),
-    utf16!("sqrt"),
-    utf16!("tan"),
-    utf16!("tanh"),
-    utf16!("trunc"),
-    // Intl object
-    utf16!("Intl"),
-    utf16!("DateTimeFormat"),
-    // TypedArray object
-    utf16!("TypedArray"),
-    utf16!("ArrayBuffer"),
-    utf16!("Int8Array"),
-    utf16!("Uint8Array"),
-    utf16!("Int16Array"),
-    utf16!("Uint16Array"),
-    utf16!("Int32Array"),
-    utf16!("Uint32Array"),
-    utf16!("BigInt64Array"),
-    utf16!("BigUint64Array"),
-    utf16!("Float32Array"),
-    utf16!("Float64Array"),
-    utf16!("buffer"),
-    utf16!("byteLength"),
-    utf16!("byteOffset"),
-    utf16!("isView"),
-    utf16!("subarray"),
-    utf16!("get byteLength"),
-    utf16!("get buffer"),
-    utf16!("get byteOffset"),
-    utf16!("get size"),
-    utf16!("get length"),
-    // DataView object
-    utf16!("DataView"),
-    utf16!("getBigInt64"),
-    utf16!("getBigUint64"),
-    utf16!("getFloat32"),
-    utf16!("getFloat64"),
-    utf16!("getInt8"),
-    utf16!("getInt16"),
-    utf16!("getInt32"),
-    utf16!("getUint8"),
-    utf16!("getUint16"),
-    utf16!("getUint32"),
-    utf16!("setBigInt64"),
-    utf16!("setBigUint64"),
-    utf16!("setFloat32"),
-    utf16!("setFloat64"),
-    utf16!("setInt8"),
-    utf16!("setInt16"),
-    utf16!("setInt32"),
-    utf16!("setUint8"),
-    utf16!("setUint16"),
-    utf16!("setUint32"),
-    // Console object
-    utf16!("console"),
-    utf16!("assert"),
-    utf16!("debug"),
-    utf16!("error"),
-    utf16!("info"),
-    utf16!("trace"),
-    utf16!("warn"),
-    utf16!("exception"),
-    utf16!("count"),
-    utf16!("countReset"),
-    utf16!("group"),
-    utf16!("groupCollapsed"),
-    utf16!("groupEnd"),
-    utf16!("time"),
-    utf16!("timeLog"),
-    utf16!("timeEnd"),
-    utf16!("dir"),
-    utf16!("dirxml"),
-    // Minified name
-    utf16!("a"),
-    utf16!("b"),
-    utf16!("c"),
-    utf16!("d"),
-    utf16!("e"),
-    utf16!("f"),
-    utf16!("g"),
-    utf16!("h"),
-    utf16!("i"),
-    utf16!("j"),
-    utf16!("k"),
-    utf16!("l"),
-    utf16!("m"),
-    utf16!("n"),
-    utf16!("o"),
-    utf16!("p"),
-    utf16!("q"),
-    utf16!("r"),
-    utf16!("s"),
-    utf16!("t"),
-    utf16!("u"),
-    utf16!("v"),
-    utf16!("w"),
-    utf16!("x"),
-    utf16!("y"),
-    utf16!("z"),
-    utf16!("A"),
-    utf16!("B"),
-    utf16!("C"),
-    utf16!("D"),
-    utf16!("E"),
-    utf16!("F"),
-    utf16!("G"),
-    utf16!("H"),
-    utf16!("I"),
-    utf16!("J"),
-    utf16!("K"),
-    utf16!("L"),
-    utf16!("M"),
-    utf16!("N"),
-    utf16!("O"),
-    utf16!("P"),
-    utf16!("Q"),
-    utf16!("R"),
-    utf16!("S"),
-    utf16!("T"),
-    utf16!("U"),
-    utf16!("V"),
-    utf16!("W"),
-    utf16!("X"),
-    utf16!("Y"),
-    utf16!("Z"),
-    utf16!("_"),
-    utf16!("$"),
-    // Well known symbols
-    utf16!("Symbol.asyncIterator"),
-    utf16!("[Symbol.asyncIterator]"),
-    utf16!("Symbol.hasInstance"),
-    utf16!("[Symbol.hasInstance]"),
-    utf16!("Symbol.isConcatSpreadable"),
-    utf16!("[Symbol.isConcatSpreadable]"),
-    utf16!("Symbol.iterator"),
-    utf16!("[Symbol.iterator]"),
-    utf16!("Symbol.match"),
-    utf16!("[Symbol.match]"),
-    utf16!("Symbol.matchAll"),
-    utf16!("[Symbol.matchAll]"),
-    utf16!("Symbol.replace"),
-    utf16!("[Symbol.replace]"),
-    utf16!("Symbol.search"),
-    utf16!("[Symbol.search]"),
-    utf16!("Symbol.species"),
-    utf16!("[Symbol.species]"),
-    utf16!("Symbol.split"),
-    utf16!("[Symbol.split]"),
-    utf16!("Symbol.toPrimitive"),
-    utf16!("[Symbol.toPrimitive]"),
-    utf16!("Symbol.toStringTag"),
-    utf16!("[Symbol.toStringTag]"),
-    utf16!("Symbol.unscopables"),
-    utf16!("[Symbol.unscopables]"),
-];
diff --git a/boa_engine/src/string/mod.rs b/boa_engine/src/string/mod.rs
index 0efd535552d..1992311c5ce 100644
--- a/boa_engine/src/string/mod.rs
+++ b/boa_engine/src/string/mod.rs
@@ -28,6 +28,7 @@ use crate::{
     tagged::{Tagged, UnwrappedTagged},
     JsBigInt,
 };
+use boa_builtins::{StaticString, RAW_STATICS};
 use boa_gc::{empty_trace, Finalize, Trace};
 pub use boa_macros::utf16;
 
@@ -617,6 +618,27 @@ impl JsString {
             ptr: Tagged::from_non_null(ptr),
         }
     }
+
+    pub(crate) fn as_static_string_index(&self) -> Option<u16> {
+        if let UnwrappedTagged::Tag(index) = self.ptr.unwrap() {
+            return Some(index as u16);
+        }
+        None
+    }
+    pub(crate) const unsafe fn from_index(index: u16) -> Self {
+        debug_assert!((index as usize) < RAW_STATICS.len());
+        Self {
+            ptr: Tagged::from_tag(index as usize),
+        }
+    }
+}
+
+impl From<StaticString> for JsString {
+    fn from(string: StaticString) -> Self {
+        Self {
+            ptr: Tagged::from_tag(string.index() as usize),
+        }
+    }
 }
 
 impl AsRef<[u16]> for JsString {
diff --git a/boa_engine/src/symbol.rs b/boa_engine/src/symbol.rs
index 925dd6f9e03..423fed64626 100644
--- a/boa_engine/src/symbol.rs
+++ b/boa_engine/src/symbol.rs
@@ -61,7 +61,7 @@ fn get_id() -> Option<u64> {
 /// List of well known symbols.
 #[derive(Debug, Clone, Copy, TryFromPrimitive, IntoPrimitive)]
 #[repr(u8)]
-enum WellKnown {
+pub(crate) enum WellKnown {
     AsyncIterator,
     HasInstance,
     IsConcatSpreadable,
diff --git a/boa_engine/src/vm/opcode/set/property.rs b/boa_engine/src/vm/opcode/set/property.rs
index f71eab4a0b7..eefc6044974 100644
--- a/boa_engine/src/vm/opcode/set/property.rs
+++ b/boa_engine/src/vm/opcode/set/property.rs
@@ -94,9 +94,11 @@ impl Operation for SetPropertyByValue {
                             // Cannot use fast path if the [[prototype]] is a proxy object,
                             // because we have to the call prototypes [[set]] on non-existing property,
                             // and proxy objects can override [[set]].
-                            let prototype = shape.prototype();
-                            if prototype.map_or(false, |x| x.is_proxy()) {
-                                break 'fast_path;
+                            if !shape.is_static() {
+                                let prototype = shape.prototype();
+                                if prototype.map_or(false, |x| x.is_proxy()) {
+                                    break 'fast_path;
+                                }
                             }
 
                             dense_elements.push(value.clone());