Browse Source

Refactor Interner

refactor/interner
Haled Odat 1 year ago
parent
commit
753f22641e
  1. 4
      Cargo.lock
  2. 1
      boa_ast/Cargo.toml
  3. 11
      boa_ast/src/expression/identifier.rs
  4. 13
      boa_ast/src/expression/literal/template.rs
  5. 8
      boa_ast/src/function/class.rs
  6. 87
      boa_ast/src/keyword/mod.rs
  7. 127
      boa_ast/src/keyword/tests.rs
  8. 2
      boa_engine/src/bytecompiler/class.rs
  9. 4
      boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
  10. 9
      boa_engine/src/bytecompiler/declarations.rs
  11. 15
      boa_engine/src/bytecompiler/expression/mod.rs
  12. 5
      boa_engine/src/bytecompiler/mod.rs
  13. 5
      boa_engine/src/bytecompiler/module.rs
  14. 10
      boa_engine/src/context/mod.rs
  15. 51
      boa_engine/src/environments/runtime/mod.rs
  16. 16
      boa_engine/src/module/mod.rs
  17. 6
      boa_engine/src/module/source.rs
  18. 4
      boa_engine/src/module/synthetic.rs
  19. 10
      boa_engine/src/optimizer/pass/constant_folding.rs
  20. 5
      boa_engine/src/vm/opcode/call/mod.rs
  21. 2
      boa_interner/Cargo.toml
  22. 80
      boa_interner/src/fixed_string.rs
  23. 80
      boa_interner/src/interned_str.rs
  24. 306
      boa_interner/src/lib.rs
  25. 194
      boa_interner/src/raw.rs
  26. 55
      boa_interner/src/tests.rs
  27. 20
      boa_macros/src/lib.rs
  28. 1
      boa_parser/Cargo.toml
  29. 77
      boa_parser/src/lexer/tests.rs
  30. 57
      boa_parser/src/parser/cursor/buffered_lexer/tests.rs
  31. 12
      boa_parser/src/parser/expression/identifiers.rs
  32. 2
      boa_parser/src/parser/expression/left_hand_side/mod.rs
  33. 14
      boa_parser/src/parser/expression/left_hand_side/optional/tests.rs
  34. 9
      boa_parser/src/parser/expression/left_hand_side/tests.rs
  35. 3
      boa_parser/src/parser/expression/primary/array_initializer/tests.rs
  36. 7
      boa_parser/src/parser/expression/primary/async_function_expression/tests.rs
  37. 8
      boa_parser/src/parser/expression/primary/async_generator_expression/tests.rs
  38. 11
      boa_parser/src/parser/expression/primary/function_expression/tests.rs
  39. 5
      boa_parser/src/parser/expression/primary/generator_expression/tests.rs
  40. 16
      boa_parser/src/parser/expression/primary/object_initializer/mod.rs
  41. 128
      boa_parser/src/parser/expression/primary/object_initializer/tests.rs
  42. 3
      boa_parser/src/parser/expression/primary/tests.rs
  43. 213
      boa_parser/src/parser/expression/tests.rs
  44. 173
      boa_parser/src/parser/function/tests.rs
  45. 13
      boa_parser/src/parser/statement/block/tests.rs
  46. 9
      boa_parser/src/parser/statement/break_stm/tests.rs
  47. 9
      boa_parser/src/parser/statement/continue_stm/tests.rs
  48. 2
      boa_parser/src/parser/statement/declaration/export.rs
  49. 7
      boa_parser/src/parser/statement/declaration/hoistable/async_function_decl/tests.rs
  50. 3
      boa_parser/src/parser/statement/declaration/hoistable/async_generator_decl/tests.rs
  51. 10
      boa_parser/src/parser/statement/declaration/hoistable/class_decl/mod.rs
  52. 31
      boa_parser/src/parser/statement/declaration/hoistable/class_decl/tests.rs
  53. 13
      boa_parser/src/parser/statement/declaration/hoistable/function_decl/tests.rs
  54. 3
      boa_parser/src/parser/statement/declaration/hoistable/generator_decl/tests.rs
  55. 2
      boa_parser/src/parser/statement/declaration/import.rs
  56. 39
      boa_parser/src/parser/statement/declaration/tests.rs
  57. 61
      boa_parser/src/parser/statement/iteration/tests.rs
  58. 10
      boa_parser/src/parser/statement/mod.rs
  59. 13
      boa_parser/src/parser/statement/switch/tests.rs
  60. 3
      boa_parser/src/parser/statement/throw/tests.rs
  61. 39
      boa_parser/src/parser/statement/try_stm/tests.rs
  62. 72
      boa_parser/src/parser/tests/mod.rs
  63. 103
      boa_types/src/string/common.rs
  64. 6
      boa_types/src/string/mod.rs

4
Cargo.lock generated

@ -357,7 +357,6 @@ dependencies = [
"arbitrary", "arbitrary",
"bitflags 2.4.1", "bitflags 2.4.1",
"boa_interner", "boa_interner",
"boa_macros",
"indexmap 2.1.0", "indexmap 2.1.0",
"num-bigint", "num-bigint",
"rustc-hash", "rustc-hash",
@ -496,9 +495,9 @@ dependencies = [
"arbitrary", "arbitrary",
"boa_gc", "boa_gc",
"boa_macros", "boa_macros",
"boa_types",
"hashbrown 0.14.2", "hashbrown 0.14.2",
"indexmap 2.1.0", "indexmap 2.1.0",
"once_cell",
"phf", "phf",
"rustc-hash", "rustc-hash",
"serde", "serde",
@ -531,7 +530,6 @@ dependencies = [
"bitflags 2.4.1", "bitflags 2.4.1",
"boa_ast", "boa_ast",
"boa_interner", "boa_interner",
"boa_macros",
"boa_profiler", "boa_profiler",
"fast-float", "fast-float",
"icu_properties", "icu_properties",

1
boa_ast/Cargo.toml

@ -17,7 +17,6 @@ temporal = []
[dependencies] [dependencies]
boa_interner.workspace = true boa_interner.workspace = true
boa_macros.workspace = true
rustc-hash = { workspace = true, features = ["std"] } rustc-hash = { workspace = true, features = ["std"] }
bitflags.workspace = true bitflags.workspace = true
num-bigint.workspace = true num-bigint.workspace = true

11
boa_ast/src/expression/identifier.rs

@ -1,9 +1,6 @@
//! Local identifier Expression. //! Local identifier Expression.
use crate::{ use crate::visitor::{VisitWith, Visitor, VisitorMut};
visitor::{VisitWith, Visitor, VisitorMut},
ToStringEscaped,
};
use boa_interner::{Interner, Sym, ToInternedString}; use boa_interner::{Interner, Sym, ToInternedString};
use core::ops::ControlFlow; use core::ops::ControlFlow;
@ -83,11 +80,7 @@ impl Identifier {
impl ToInternedString for Identifier { impl ToInternedString for Identifier {
#[inline] #[inline]
fn to_interned_string(&self, interner: &Interner) -> String { fn to_interned_string(&self, interner: &Interner) -> String {
interner.resolve_expect(self.ident).join( interner.resolve_expect(self.ident).to_std_string_escaped()
String::from,
ToStringEscaped::to_string_escaped,
true,
)
} }
} }

13
boa_ast/src/expression/literal/template.rs

@ -1,15 +1,12 @@
//! Template literal Expression. //! Template literal Expression.
use core::ops::ControlFlow;
use std::borrow::Cow;
use boa_interner::{Interner, Sym, ToInternedString}; use boa_interner::{Interner, Sym, ToInternedString};
use core::ops::ControlFlow;
use crate::{ use crate::{
expression::Expression, expression::Expression,
try_break, try_break,
visitor::{VisitWith, Visitor, VisitorMut}, visitor::{VisitWith, Visitor, VisitorMut},
ToStringEscaped,
}; };
/// Template literals are string literals allowing embedded expressions. /// Template literals are string literals allowing embedded expressions.
@ -72,11 +69,9 @@ impl ToInternedString for TemplateLiteral {
for elt in &*self.elements { for elt in &*self.elements {
match elt { match elt {
TemplateElement::String(s) => buf.push_str(&interner.resolve_expect(*s).join( TemplateElement::String(s) => {
Cow::Borrowed, buf.push_str(&interner.resolve_expect(*s).to_std_string_escaped());
|utf16| Cow::Owned(utf16.to_string_escaped()), }
true,
)),
TemplateElement::Expr(n) => { TemplateElement::Expr(n) => {
buf.push_str(&format!("${{{}}}", n.to_interned_string(interner))); buf.push_str(&format!("${{{}}}", n.to_interned_string(interner)));
} }

8
boa_ast/src/function/class.rs

@ -6,7 +6,7 @@ use crate::{
property::{MethodDefinition, PropertyName}, property::{MethodDefinition, PropertyName},
try_break, try_break,
visitor::{VisitWith, Visitor, VisitorMut}, visitor::{VisitWith, Visitor, VisitorMut},
Declaration, ToStringEscaped, Declaration,
}; };
use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString}; use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
use core::ops::ControlFlow; use core::ops::ControlFlow;
@ -90,11 +90,7 @@ impl Class {
impl ToIndentedString for Class { impl ToIndentedString for Class {
fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String { fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
let class_name = self.name.map_or(Cow::Borrowed(""), |s| { let class_name = self.name.map_or(Cow::Borrowed(""), |s| {
interner.resolve_expect(s.sym()).join( Cow::Owned(interner.resolve_expect(s.sym()).to_std_string_escaped())
Cow::Borrowed,
|utf16| Cow::Owned(utf16.to_string_escaped()),
true,
)
}); });
if self.elements.is_empty() && self.constructor().is_none() { if self.elements.is_empty() && self.constructor().is_none() {
return format!( return format!(

87
boa_ast/src/keyword/mod.rs

@ -11,7 +11,6 @@
use crate::expression::operator::binary::{BinaryOp, RelationalOp}; use crate::expression::operator::binary::{BinaryOp, RelationalOp};
use boa_interner::Sym; use boa_interner::Sym;
use boa_macros::utf16;
use std::{convert::TryFrom, error, fmt, str::FromStr}; use std::{convert::TryFrom, error, fmt, str::FromStr};
#[cfg(test)] #[cfg(test)]
@ -491,49 +490,49 @@ impl Keyword {
/// Gets the keyword as a tuple of strings. /// Gets the keyword as a tuple of strings.
#[must_use] #[must_use]
pub const fn as_str(self) -> (&'static str, &'static [u16]) { pub const fn as_str(self) -> &'static str {
match self { match self {
Self::Await => ("await", utf16!("await")), Self::Await => "await",
Self::Async => ("async", utf16!("async")), Self::Async => "async",
Self::Break => ("break", utf16!("break")), Self::Break => "break",
Self::Case => ("case", utf16!("case")), Self::Case => "case",
Self::Catch => ("catch", utf16!("catch")), Self::Catch => "catch",
Self::Class => ("class", utf16!("class")), Self::Class => "class",
Self::Continue => ("continue", utf16!("continue")), Self::Continue => "continue",
Self::Const => ("const", utf16!("const")), Self::Const => "const",
Self::Debugger => ("debugger", utf16!("debugger")), Self::Debugger => "debugger",
Self::Default => ("default", utf16!("default")), Self::Default => "default",
Self::Delete => ("delete", utf16!("delete")), Self::Delete => "delete",
Self::Do => ("do", utf16!("do")), Self::Do => "do",
Self::Else => ("else", utf16!("else")), Self::Else => "else",
Self::Enum => ("enum", utf16!("enum")), Self::Enum => "enum",
Self::Extends => ("extends", utf16!("extends")), Self::Extends => "extends",
Self::Export => ("export", utf16!("export")), Self::Export => "export",
Self::False => ("false", utf16!("false")), Self::False => "false",
Self::Finally => ("finally", utf16!("finally")), Self::Finally => "finally",
Self::For => ("for", utf16!("for")), Self::For => "for",
Self::Function => ("function", utf16!("function")), Self::Function => "function",
Self::If => ("if", utf16!("if")), Self::If => "if",
Self::In => ("in", utf16!("in")), Self::In => "in",
Self::InstanceOf => ("instanceof", utf16!("instanceof")), Self::InstanceOf => "instanceof",
Self::Import => ("import", utf16!("import")), Self::Import => "import",
Self::Let => ("let", utf16!("let")), Self::Let => "let",
Self::New => ("new", utf16!("new")), Self::New => "new",
Self::Null => ("null", utf16!("null")), Self::Null => "null",
Self::Of => ("of", utf16!("of")), Self::Of => "of",
Self::Return => ("return", utf16!("return")), Self::Return => "return",
Self::Super => ("super", utf16!("super")), Self::Super => "super",
Self::Switch => ("switch", utf16!("switch")), Self::Switch => "switch",
Self::This => ("this", utf16!("this")), Self::This => "this",
Self::Throw => ("throw", utf16!("throw")), Self::Throw => "throw",
Self::True => ("true", utf16!("true")), Self::True => "true",
Self::Try => ("try", utf16!("try")), Self::Try => "try",
Self::TypeOf => ("typeof", utf16!("typeof")), Self::TypeOf => "typeof",
Self::Var => ("var", utf16!("var")), Self::Var => "var",
Self::Void => ("void", utf16!("void")), Self::Void => "void",
Self::While => ("while", utf16!("while")), Self::While => "while",
Self::With => ("with", utf16!("with")), Self::With => "with",
Self::Yield => ("yield", utf16!("yield")), Self::Yield => "yield",
} }
} }
@ -661,6 +660,6 @@ impl FromStr for Keyword {
impl fmt::Display for Keyword { impl fmt::Display for Keyword {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str().0, f) fmt::Display::fmt(self.as_str(), f)
} }
} }

127
boa_ast/src/keyword/tests.rs

@ -71,171 +71,130 @@ fn as_binary_op() {
fn as_str() { fn as_str() {
for k in all_keywords() { for k in all_keywords() {
match k.as_str() { match k.as_str() {
("await", utf16) => { "await" => {
assert_eq!(k, Keyword::Await); assert_eq!(k, Keyword::Await);
assert_eq!(utf16, utf16!("await"));
} }
("async", utf16) => { "async" => {
assert_eq!(k, Keyword::Async); assert_eq!(k, Keyword::Async);
assert_eq!(utf16, utf16!("async"));
} }
("break", utf16) => { "break" => {
assert_eq!(k, Keyword::Break); assert_eq!(k, Keyword::Break);
assert_eq!(utf16, utf16!("break"));
} }
("case", utf16) => { "case" => {
assert_eq!(k, Keyword::Case); assert_eq!(k, Keyword::Case);
assert_eq!(utf16, utf16!("case"));
} }
("catch", utf16) => { "catch" => {
assert_eq!(k, Keyword::Catch); assert_eq!(k, Keyword::Catch);
assert_eq!(utf16, utf16!("catch"));
} }
("class", utf16) => { "class" => {
assert_eq!(k, Keyword::Class); assert_eq!(k, Keyword::Class);
assert_eq!(utf16, utf16!("class"));
} }
("continue", utf16) => { "continue" => {
assert_eq!(k, Keyword::Continue); assert_eq!(k, Keyword::Continue);
assert_eq!(utf16, utf16!("continue"));
} }
("const", utf16) => { "const" => {
assert_eq!(k, Keyword::Const); assert_eq!(k, Keyword::Const);
assert_eq!(utf16, utf16!("const"));
} }
("debugger", utf16) => { "debugger" => {
assert_eq!(k, Keyword::Debugger); assert_eq!(k, Keyword::Debugger);
assert_eq!(utf16, utf16!("debugger"));
} }
("default", utf16) => { "default" => {
assert_eq!(k, Keyword::Default); assert_eq!(k, Keyword::Default);
assert_eq!(utf16, utf16!("default"));
} }
("delete", utf16) => { "delete" => {
assert_eq!(k, Keyword::Delete); assert_eq!(k, Keyword::Delete);
assert_eq!(utf16, utf16!("delete"));
} }
("do", utf16) => { "do" => {
assert_eq!(k, Keyword::Do); assert_eq!(k, Keyword::Do);
assert_eq!(utf16, utf16!("do"));
} }
("else", utf16) => { "else" => {
assert_eq!(k, Keyword::Else); assert_eq!(k, Keyword::Else);
assert_eq!(utf16, utf16!("else"));
} }
("enum", utf16) => { "enum" => {
assert_eq!(k, Keyword::Enum); assert_eq!(k, Keyword::Enum);
assert_eq!(utf16, utf16!("enum"));
} }
("extends", utf16) => { "extends" => {
assert_eq!(k, Keyword::Extends); assert_eq!(k, Keyword::Extends);
assert_eq!(utf16, utf16!("extends"));
} }
("export", utf16) => { "export" => {
assert_eq!(k, Keyword::Export); assert_eq!(k, Keyword::Export);
assert_eq!(utf16, utf16!("export"));
} }
("false", utf16) => { "false" => {
assert_eq!(k, Keyword::False); assert_eq!(k, Keyword::False);
assert_eq!(utf16, utf16!("false"));
} }
("finally", utf16) => { "finally" => {
assert_eq!(k, Keyword::Finally); assert_eq!(k, Keyword::Finally);
assert_eq!(utf16, utf16!("finally"));
} }
("for", utf16) => { "for" => {
assert_eq!(k, Keyword::For); assert_eq!(k, Keyword::For);
assert_eq!(utf16, utf16!("for"));
} }
("function", utf16) => { "function" => {
assert_eq!(k, Keyword::Function); assert_eq!(k, Keyword::Function);
assert_eq!(utf16, utf16!("function"));
} }
("if", utf16) => { "if" => {
assert_eq!(k, Keyword::If); assert_eq!(k, Keyword::If);
assert_eq!(utf16, utf16!("if"));
} }
("in", utf16) => { "in" => {
assert_eq!(k, Keyword::In); assert_eq!(k, Keyword::In);
assert_eq!(utf16, utf16!("in"));
} }
("instanceof", utf16) => { "instanceof" => {
assert_eq!(k, Keyword::InstanceOf); assert_eq!(k, Keyword::InstanceOf);
assert_eq!(utf16, utf16!("instanceof"));
} }
("import", utf16) => { "import" => {
assert_eq!(k, Keyword::Import); assert_eq!(k, Keyword::Import);
assert_eq!(utf16, utf16!("import"));
} }
("let", utf16) => { "let" => {
assert_eq!(k, Keyword::Let); assert_eq!(k, Keyword::Let);
assert_eq!(utf16, utf16!("let"));
} }
("new", utf16) => { "new" => {
assert_eq!(k, Keyword::New); assert_eq!(k, Keyword::New);
assert_eq!(utf16, utf16!("new"));
} }
("null", utf16) => { "null" => {
assert_eq!(k, Keyword::Null); assert_eq!(k, Keyword::Null);
assert_eq!(utf16, utf16!("null"));
} }
("of", utf16) => { "of" => {
assert_eq!(k, Keyword::Of); assert_eq!(k, Keyword::Of);
assert_eq!(utf16, utf16!("of"));
} }
("return", utf16) => { "return" => {
assert_eq!(k, Keyword::Return); assert_eq!(k, Keyword::Return);
assert_eq!(utf16, utf16!("return"));
} }
("super", utf16) => { "super" => {
assert_eq!(k, Keyword::Super); assert_eq!(k, Keyword::Super);
assert_eq!(utf16, utf16!("super"));
} }
("switch", utf16) => { "switch" => {
assert_eq!(k, Keyword::Switch); assert_eq!(k, Keyword::Switch);
assert_eq!(utf16, utf16!("switch"));
} }
("this", utf16) => { "this" => {
assert_eq!(k, Keyword::This); assert_eq!(k, Keyword::This);
assert_eq!(utf16, utf16!("this"));
} }
("throw", utf16) => { "throw" => {
assert_eq!(k, Keyword::Throw); assert_eq!(k, Keyword::Throw);
assert_eq!(utf16, utf16!("throw"));
} }
("true", utf16) => { "true" => {
assert_eq!(k, Keyword::True); assert_eq!(k, Keyword::True);
assert_eq!(utf16, utf16!("true"));
} }
("try", utf16) => { "try" => {
assert_eq!(k, Keyword::Try); assert_eq!(k, Keyword::Try);
assert_eq!(utf16, utf16!("try"));
} }
("typeof", utf16) => { "typeof" => {
assert_eq!(k, Keyword::TypeOf); assert_eq!(k, Keyword::TypeOf);
assert_eq!(utf16, utf16!("typeof"));
} }
("var", utf16) => { "var" => {
assert_eq!(k, Keyword::Var); assert_eq!(k, Keyword::Var);
assert_eq!(utf16, utf16!("var"));
} }
("void", utf16) => { "void" => {
assert_eq!(k, Keyword::Void); assert_eq!(k, Keyword::Void);
assert_eq!(utf16, utf16!("void"));
} }
("while", utf16) => { "while" => {
assert_eq!(k, Keyword::While); assert_eq!(k, Keyword::While);
assert_eq!(utf16, utf16!("while"));
} }
("with", utf16) => { "with" => {
assert_eq!(k, Keyword::With); assert_eq!(k, Keyword::With);
assert_eq!(utf16, utf16!("with"));
} }
("yield", utf16) => { "yield" => {
assert_eq!(k, Keyword::Yield); assert_eq!(k, Keyword::Yield);
assert_eq!(utf16, utf16!("yield"));
} }
(_, _) => unreachable!("unknown keyword {k:?} found"), _ => unreachable!("unknown keyword {k:?} found"),
} }
} }
} }
@ -341,7 +300,7 @@ fn try_into_binary_op() {
#[test] #[test]
fn from_str() { fn from_str() {
for k in all_keywords() { for k in all_keywords() {
let str = k.as_str().0; let str = k.as_str();
assert_eq!(str.parse::<Keyword>().unwrap(), k); assert_eq!(str.parse::<Keyword>().unwrap(), k);
} }

2
boa_engine/src/bytecompiler/class.rs

@ -269,7 +269,7 @@ impl ByteCompiler<'_, '_> {
match name { match name {
PropertyName::Literal(name) => { PropertyName::Literal(name) => {
self.emit_push_literal(Literal::String( self.emit_push_literal(Literal::String(
self.interner().resolve_expect(*name).into_common(false), self.interner().resolve_expect(*name).into(),
)); ));
} }
PropertyName::Computed(name) => { PropertyName::Computed(name) => {

4
boa_engine/src/bytecompiler/declaration/declaration_pattern.rs

@ -77,7 +77,7 @@ impl ByteCompiler<'_, '_> {
for key in excluded_keys { for key in excluded_keys {
self.emit_push_literal(Literal::String( self.emit_push_literal(Literal::String(
self.interner().resolve_expect(key.sym()).into_common(false), self.interner().resolve_expect(key.sym()).into(),
)); ));
} }
@ -98,7 +98,7 @@ impl ByteCompiler<'_, '_> {
self.emit_opcode(Opcode::PushEmptyObject); self.emit_opcode(Opcode::PushEmptyObject);
for key in excluded_keys { for key in excluded_keys {
self.emit_push_literal(Literal::String( self.emit_push_literal(Literal::String(
self.interner().resolve_expect(key.sym()).into_common(false), self.interner().resolve_expect(key.sym()).into(),
)); ));
} }
self.emit( self.emit(

9
boa_engine/src/bytecompiler/declarations.rs

@ -286,7 +286,7 @@ impl ByteCompiler<'_, '_> {
let function = create_function_object_fast(code, self.context); let function = create_function_object_fast(code, self.context);
// c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false). // c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false).
let name = js_string!(self.interner().resolve_expect(name.sym()).utf16()); let name = js_string!(self.interner().resolve_expect(name.sym()));
self.context self.context
.create_global_function_binding(name, function, false)?; .create_global_function_binding(name, function, false)?;
} }
@ -454,12 +454,7 @@ impl ByteCompiler<'_, '_> {
let private_identifiers = self.context.vm.environments.private_name_descriptions(); let private_identifiers = self.context.vm.environments.private_name_descriptions();
let private_identifiers = private_identifiers let private_identifiers = private_identifiers
.into_iter() .into_iter()
.map(|ident| { .map(|ident| self.context.interner_mut().get_or_intern(ident.as_str()))
self.context
.interner()
.get(ident.as_str().as_str_ref())
.expect("string should be in interner")
})
.collect(); .collect();
// 7. If AllPrivateIdentifiersValid of body with argument privateIdentifiers is false, throw a SyntaxError exception. // 7. If AllPrivateIdentifiersValid of body with argument privateIdentifiers is false, throw a SyntaxError exception.

15
boa_engine/src/bytecompiler/expression/mod.rs

@ -22,9 +22,9 @@ use boa_ast::{
impl ByteCompiler<'_, '_> { impl ByteCompiler<'_, '_> {
fn compile_literal(&mut self, lit: &AstLiteral, use_expr: bool) { fn compile_literal(&mut self, lit: &AstLiteral, use_expr: bool) {
match lit { match lit {
AstLiteral::String(v) => self.emit_push_literal(Literal::String( AstLiteral::String(v) => {
self.interner().resolve_expect(*v).into_common(false), self.emit_push_literal(Literal::String(self.interner().resolve_expect(*v).into()));
)), }
AstLiteral::Int(v) => self.emit_push_integer(*v), AstLiteral::Int(v) => self.emit_push_integer(*v),
AstLiteral::Num(v) => self.emit_push_rational(*v), AstLiteral::Num(v) => self.emit_push_rational(*v),
AstLiteral::BigInt(v) => { AstLiteral::BigInt(v) => {
@ -58,9 +58,8 @@ impl ByteCompiler<'_, '_> {
fn compile_template_literal(&mut self, template_literal: &TemplateLiteral, use_expr: bool) { fn compile_template_literal(&mut self, template_literal: &TemplateLiteral, use_expr: bool) {
for element in template_literal.elements() { for element in template_literal.elements() {
match element { match element {
TemplateElement::String(s) => self.emit_push_literal(Literal::String( TemplateElement::String(s) => self
self.interner().resolve_expect(*s).into_common(false), .emit_push_literal(Literal::String(self.interner().resolve_expect(*s).into())),
)),
TemplateElement::Expr(expr) => { TemplateElement::Expr(expr) => {
self.compile_expr(expr, true); self.compile_expr(expr, true);
} }
@ -269,13 +268,13 @@ impl ByteCompiler<'_, '_> {
for (cooked, raw) in template.cookeds().iter().zip(template.raws()) { for (cooked, raw) in template.cookeds().iter().zip(template.raws()) {
if let Some(cooked) = cooked { if let Some(cooked) = cooked {
self.emit_push_literal(Literal::String( self.emit_push_literal(Literal::String(
self.interner().resolve_expect(*cooked).into_common(false), self.interner().resolve_expect(*cooked).into(),
)); ));
} else { } else {
self.emit_opcode(Opcode::PushUndefined); self.emit_opcode(Opcode::PushUndefined);
} }
self.emit_push_literal(Literal::String( self.emit_push_literal(Literal::String(
self.interner().resolve_expect(*raw).into_common(false), self.interner().resolve_expect(*raw).into(),
)); ));
} }

5
boa_engine/src/bytecompiler/mod.rs

@ -371,9 +371,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
return *index; return *index;
} }
let string = self.interner().resolve_expect(name.sym()).utf16(); let string = js_string!(self.interner().resolve_expect(name.sym()));
let index = self.constants.len() as u32; let index = self.constants.len() as u32;
self.constants.push(Constant::String(js_string!(string))); self.constants.push(Constant::String(string));
self.names_map.insert(name, index); self.names_map.insert(name, index);
index index
} }
@ -1453,7 +1453,6 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
.context .context
.interner() .interner()
.resolve_expect(self.function_name) .resolve_expect(self.function_name)
.utf16()
.into(); .into();
CodeBlock { CodeBlock {

5
boa_engine/src/bytecompiler/module.rs

@ -57,10 +57,7 @@ impl ByteCompiler<'_, '_> {
self.compile_expr(expr, true); self.compile_expr(expr, true);
if expr.is_anonymous_function_definition() { if expr.is_anonymous_function_definition() {
let default = self let default = self.interner().resolve_expect(Sym::DEFAULT).into();
.interner()
.resolve_expect(Sym::DEFAULT)
.into_common(false);
self.emit_push_literal(Literal::String(default)); self.emit_push_literal(Literal::String(default));
self.emit_opcode(Opcode::Swap); self.emit_opcode(Opcode::Swap);
self.emit(Opcode::SetFunctionName, &[Operand::U8(0)]); self.emit(Opcode::SetFunctionName, &[Operand::U8(0)]);

10
boa_engine/src/context/mod.rs

@ -617,7 +617,7 @@ impl Context<'_> {
let global_object = self.realm().global_object().clone(); let global_object = self.realm().global_object().clone();
// 3. Let existingProp be ? globalObject.[[GetOwnProperty]](N). // 3. Let existingProp be ? globalObject.[[GetOwnProperty]](N).
let name = self.interner().resolve_expect(name.sym()).utf16().into(); let name = JsString::from(self.interner().resolve_expect(name.sym())).into();
let existing_prop = global_object.__get_own_property__(&name, self)?; let existing_prop = global_object.__get_own_property__(&name, self)?;
// 4. If existingProp is undefined, return ? IsExtensible(globalObject). // 4. If existingProp is undefined, return ? IsExtensible(globalObject).
@ -654,7 +654,7 @@ impl Context<'_> {
let global_object = self.realm().global_object().clone(); let global_object = self.realm().global_object().clone();
// 3. Let hasProperty be ? HasOwnProperty(globalObject, N). // 3. Let hasProperty be ? HasOwnProperty(globalObject, N).
let name = PropertyKey::from(self.interner().resolve_expect(name.sym()).utf16()); let name = JsString::from(self.interner().resolve_expect(name.sym()));
let has_property = global_object.has_own_property(name, self)?; let has_property = global_object.has_own_property(name, self)?;
// 4. If hasProperty is true, return true. // 4. If hasProperty is true, return true.
@ -682,7 +682,7 @@ impl Context<'_> {
let global_object = self.realm().global_object().clone(); let global_object = self.realm().global_object().clone();
// 3. Let hasProperty be ? HasOwnProperty(globalObject, N). // 3. Let hasProperty be ? HasOwnProperty(globalObject, N).
let name = PropertyKey::from(self.interner().resolve_expect(name.sym()).utf16()); let name = JsString::from(self.interner().resolve_expect(name.sym()));
let has_property = global_object.has_own_property(name.clone(), self)?; let has_property = global_object.has_own_property(name.clone(), self)?;
// 4. Let extensible be ? IsExtensible(globalObject). // 4. Let extensible be ? IsExtensible(globalObject).
@ -773,8 +773,8 @@ impl Context<'_> {
let global_object = self.realm().global_object().clone(); let global_object = self.realm().global_object().clone();
// 3. Let existingProp be ? globalObject.[[GetOwnProperty]](N). // 3. Let existingProp be ? globalObject.[[GetOwnProperty]](N).
let name = PropertyKey::from(self.interner().resolve_expect(name.sym()).utf16()); let name = JsString::from(self.interner().resolve_expect(name.sym()));
let existing_prop = global_object.__get_own_property__(&name, self)?; let existing_prop = global_object.__get_own_property__(&name.into(), self)?;
// 4. If existingProp is undefined, return false. // 4. If existingProp is undefined, return false.
let Some(existing_prop) = existing_prop else { let Some(existing_prop) = existing_prop else {

51
boa_engine/src/environments/runtime/mod.rs

@ -401,12 +401,12 @@ impl EnvironmentStack {
} }
/// Return all private name descriptions in all private environments. /// Return all private name descriptions in all private environments.
pub(crate) fn private_name_descriptions(&self) -> Vec<&JsString> { pub(crate) fn private_name_descriptions(&self) -> Vec<JsString> {
let mut names = Vec::new(); let mut names = Vec::new();
for environment in self.private_stack.iter().rev() { for environment in self.private_stack.iter().rev() {
for name in environment.descriptions() { for name in environment.descriptions() {
if !names.contains(&name) { if !names.contains(name) {
names.push(name); names.push(name.clone());
} }
} }
} }
@ -523,10 +523,7 @@ impl Context<'_> {
} }
Environment::Object(o) => { Environment::Object(o) => {
let o = o.clone(); let o = o.clone();
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
if o.has_property(key.clone(), self)? { if o.has_property(key.clone(), self)? {
if let Some(unscopables) = o.get(JsSymbol::unscopables(), self)?.as_object() if let Some(unscopables) = o.get(JsSymbol::unscopables(), self)?.as_object()
{ {
@ -552,19 +549,13 @@ impl Context<'_> {
/// Panics if the environment or binding index are out of range. /// Panics if the environment or binding index are out of range.
pub(crate) fn is_initialized_binding(&mut self, locator: &BindingLocator) -> JsResult<bool> { pub(crate) fn is_initialized_binding(&mut self, locator: &BindingLocator) -> JsResult<bool> {
if locator.global { if locator.global {
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
self.global_object().has_property(key, self) self.global_object().has_property(key, self)
} else { } else {
match self.environment_expect(locator.environment_index) { match self.environment_expect(locator.environment_index) {
Environment::Declarative(env) => Ok(env.get(locator.binding_index).is_some()), Environment::Declarative(env) => Ok(env.get(locator.binding_index).is_some()),
Environment::Object(obj) => { Environment::Object(obj) => {
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
obj.clone().has_property(key, self) obj.clone().has_property(key, self)
} }
} }
@ -579,10 +570,7 @@ impl Context<'_> {
pub(crate) fn get_binding(&mut self, locator: BindingLocator) -> JsResult<Option<JsValue>> { pub(crate) fn get_binding(&mut self, locator: BindingLocator) -> JsResult<Option<JsValue>> {
if locator.global { if locator.global {
let global = self.global_object(); let global = self.global_object();
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
if global.has_property(key.clone(), self)? { if global.has_property(key.clone(), self)? {
global.get(key, self).map(Some) global.get(key, self).map(Some)
} else { } else {
@ -593,10 +581,7 @@ impl Context<'_> {
Environment::Declarative(env) => Ok(env.get(locator.binding_index)), Environment::Declarative(env) => Ok(env.get(locator.binding_index)),
Environment::Object(obj) => { Environment::Object(obj) => {
let obj = obj.clone(); let obj = obj.clone();
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
obj.get(key, self).map(Some) obj.get(key, self).map(Some)
} }
} }
@ -616,10 +601,7 @@ impl Context<'_> {
strict: bool, strict: bool,
) -> JsResult<()> { ) -> JsResult<()> {
if locator.global { if locator.global {
let key = self let key: JsString = self.interner().resolve_expect(locator.name().sym()).into();
.interner()
.resolve_expect(locator.name().sym())
.into_common::<JsString>(false);
self.global_object().set(key, value, strict, self)?; self.global_object().set(key, value, strict, self)?;
} else { } else {
@ -629,10 +611,7 @@ impl Context<'_> {
} }
Environment::Object(obj) => { Environment::Object(obj) => {
let obj = obj.clone(); let obj = obj.clone();
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
obj.set(key, value, strict, self)?; obj.set(key, value, strict, self)?;
} }
@ -651,20 +630,14 @@ impl Context<'_> {
/// Panics if the environment or binding index are out of range. /// Panics if the environment or binding index are out of range.
pub(crate) fn delete_binding(&mut self, locator: BindingLocator) -> JsResult<bool> { pub(crate) fn delete_binding(&mut self, locator: BindingLocator) -> JsResult<bool> {
if locator.is_global() { if locator.is_global() {
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name().sym()).into();
.interner()
.resolve_expect(locator.name().sym())
.into_common::<JsString>(false);
self.global_object().__delete__(&key.into(), self) self.global_object().__delete__(&key.into(), self)
} else { } else {
match self.environment_expect(locator.environment_index) { match self.environment_expect(locator.environment_index) {
Environment::Declarative(_) => Ok(false), Environment::Declarative(_) => Ok(false),
Environment::Object(obj) => { Environment::Object(obj) => {
let obj = obj.clone(); let obj = obj.clone();
let key: JsString = self let key: JsString = self.interner().resolve_expect(locator.name.sym()).into();
.interner()
.resolve_expect(locator.name.sym())
.into_common(false);
obj.__delete__(&key.into(), self) obj.__delete__(&key.into(), self)
} }

16
boa_engine/src/module/mod.rs

@ -181,11 +181,7 @@ impl Module {
) -> Self { ) -> Self {
let names: FxHashSet<Sym> = export_names let names: FxHashSet<Sym> = export_names
.iter() .iter()
.map(|string| { .map(|string| context.interner_mut().get_or_intern(string.as_str()))
context
.interner_mut()
.get_or_intern(string.as_str().as_str_ref())
})
.collect(); .collect();
let realm = realm.unwrap_or_else(|| context.realm().clone()); let realm = realm.unwrap_or_else(|| context.realm().clone());
let inner = Gc::new_cyclic(|weak| { let inner = Gc::new_cyclic(|weak| {
@ -594,15 +590,7 @@ impl ModuleNamespace {
// 6. Let sortedExports be a List whose elements are the elements of exports ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn. // 6. Let sortedExports be a List whose elements are the elements of exports ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn.
let mut exports = names let mut exports = names
.into_iter() .into_iter()
.map(|sym| { .map(|sym| (context.interner().resolve_expect(sym).into(), sym))
(
context
.interner()
.resolve_expect(sym)
.into_common::<JsString>(false),
sym,
)
})
.collect::<IndexMap<_, _, _>>(); .collect::<IndexMap<_, _, _>>();
exports.sort_keys(); exports.sort_keys();

6
boa_engine/src/module/source.rs

@ -436,10 +436,8 @@ impl SourceTextModule {
// 1. Perform HostLoadImportedModule(module, required, state.[[HostDefined]], state). // 1. Perform HostLoadImportedModule(module, required, state.[[HostDefined]], state).
// 2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters // 2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters
// the graph loading process through ContinueModuleLoading. // the graph loading process through ContinueModuleLoading.
let name_specifier: JsString = context let name_specifier: JsString =
.interner() context.interner().resolve_expect(required).into();
.resolve_expect(required)
.into_common(false);
let src = self.clone(); let src = self.clone();
let state = state.clone(); let state = state.clone();
context.module_loader().load_imported_module( context.module_loader().load_imported_module(

4
boa_engine/src/module/synthetic.rs

@ -359,9 +359,7 @@ impl SyntheticModule {
export_value: JsValue, export_value: JsValue,
context: &mut Context<'_>, context: &mut Context<'_>,
) -> JsResult<()> { ) -> JsResult<()> {
let identifier = context let identifier = context.interner_mut().get_or_intern(export_name.as_str());
.interner_mut()
.get_or_intern(export_name.as_str().as_str_ref());
let identifier = Identifier::new(identifier); let identifier = Identifier::new(identifier);
let environment = self let environment = self

10
boa_engine/src/optimizer/pass/constant_folding.rs

@ -15,9 +15,7 @@ use boa_ast::{
fn literal_to_js_value(literal: &Literal, context: &mut Context<'_>) -> JsValue { fn literal_to_js_value(literal: &Literal, context: &mut Context<'_>) -> JsValue {
match literal { match literal {
Literal::String(v) => JsValue::new(JsString::from( Literal::String(v) => JsValue::new(JsString::from(context.interner().resolve_expect(*v))),
context.interner().resolve_expect(*v).utf16(),
)),
Literal::Num(v) => JsValue::new(*v), Literal::Num(v) => JsValue::new(*v),
Literal::Int(v) => JsValue::new(*v), Literal::Int(v) => JsValue::new(*v),
Literal::BigInt(v) => JsValue::new(JsBigInt::new(v.clone())), Literal::BigInt(v) => JsValue::new(JsBigInt::new(v.clone())),
@ -32,11 +30,7 @@ fn js_value_to_literal(value: JsValue, context: &mut Context<'_>) -> Literal {
JsValue::Null => Literal::Null, JsValue::Null => Literal::Null,
JsValue::Undefined => Literal::Undefined, JsValue::Undefined => Literal::Undefined,
JsValue::Boolean(v) => Literal::Bool(v), JsValue::Boolean(v) => Literal::Bool(v),
JsValue::String(v) => Literal::String( JsValue::String(v) => Literal::String(context.interner_mut().get_or_intern(v.as_str())),
context
.interner_mut()
.get_or_intern(v.as_str().as_str_ref()),
),
JsValue::Rational(v) => Literal::Num(v), JsValue::Rational(v) => Literal::Num(v),
JsValue::Integer(v) => Literal::Int(v), JsValue::Integer(v) => Literal::Int(v),
JsValue::BigInt(v) => Literal::BigInt(Box::new(v.as_inner().clone())), JsValue::BigInt(v) => Literal::BigInt(Box::new(v.as_inner().clone())),

5
boa_engine/src/vm/opcode/call/mod.rs

@ -299,9 +299,8 @@ impl Operation for ImportCall {
panic!("referrer cannot be a synthetic module"); panic!("referrer cannot be a synthetic module");
}; };
let sym = context let sym =
.interner_mut() context.interner_mut().get_or_intern(specifier.as_str());
.get_or_intern(specifier.as_str().as_str_ref());
let mut loaded_modules = src.loaded_modules().borrow_mut(); let mut loaded_modules = src.loaded_modules().borrow_mut();

2
boa_interner/Cargo.toml

@ -17,10 +17,10 @@ arbitrary = ["dep:arbitrary"]
[dependencies] [dependencies]
boa_macros.workspace = true boa_macros.workspace = true
boa_gc.workspace = true boa_gc.workspace = true
boa_types.workspace = true
phf = { workspace = true, default-features = false, features = ["macros"] } phf = { workspace = true, default-features = false, features = ["macros"] }
rustc-hash = { workspace = true, default-features = false } rustc-hash = { workspace = true, default-features = false }
static_assertions.workspace = true static_assertions.workspace = true
once_cell = { workspace = true, features = ["std"]}
indexmap.workspace = true indexmap.workspace = true
serde = { workspace = true, features = ["derive"], optional = true } serde = { workspace = true, features = ["derive"], optional = true }
arbitrary = { workspace = true, features = ["derive"], optional = true } arbitrary = { workspace = true, features = ["derive"], optional = true }

80
boa_interner/src/fixed_string.rs

@ -1,80 +0,0 @@
use alloc::vec::Vec;
use crate::interned_str::InternedStr;
#[derive(Debug)]
pub(super) struct FixedString<Char> {
inner: Vec<Char>,
}
impl<Char> Default for FixedString<Char> {
fn default() -> Self {
Self {
inner: Vec::default(),
}
}
}
impl<Char> FixedString<Char> {
/// Creates a new, pinned [`FixedString`].
pub(super) fn new(capacity: usize) -> Self {
Self {
inner: Vec::with_capacity(capacity),
}
}
/// Gets the maximum capacity of the [`FixedString`].
pub(super) fn capacity(&self) -> usize {
self.inner.capacity()
}
/// Returns `true` if the [`FixedString`] has length zero,
/// and `false` otherwise.
pub(super) fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl<Char> FixedString<Char>
where
Char: Clone,
{
/// Tries to push `string` to the [`FixedString`], and returns
/// an [`InternedStr`] pointer to the stored `string`, or
/// `None` if the capacity is not enough to store `string`.
///
/// # Safety
///
/// The caller is responsible for ensuring `self` outlives the returned
/// [`InternedStr`].
pub(super) unsafe fn push(&mut self, string: &[Char]) -> Option<InternedStr<Char>> {
let capacity = self.inner.capacity();
(capacity >= self.inner.len() + string.len()).then(|| {
// SAFETY:
// The caller is responsible for extending the lifetime
// of `self` to outlive the return value.
unsafe { self.push_unchecked(string) }
})
}
/// Pushes `string` to the [`FixedString`], and returns
/// an [`InternedStr`] pointer to the stored `string`, without
/// checking if the total `capacity` is enough to store `string`,
/// and without checking if the string is correctly aligned.
///
/// # Safety
///
/// The caller is responsible for ensuring that `self` outlives the returned
/// [`InternedStr`] and that it has enough capacity to store `string` without
/// reallocating.
pub(super) unsafe fn push_unchecked(&mut self, string: &[Char]) -> InternedStr<Char> {
let old_len = self.inner.len();
self.inner.extend_from_slice(string);
// SAFETY: The caller is responsible for extending the lifetime
// of `self` to outlive the return value, and for ensuring
// the alignment of `string` is correct.
let ptr = &self.inner[old_len..self.inner.len()];
unsafe { InternedStr::new(ptr.into()) }
}
}

80
boa_interner/src/interned_str.rs

@ -1,80 +0,0 @@
use core::{hash::Hash, ptr::NonNull};
/// Wrapper for an interned str pointer, required to
/// quickly check using a hash if a string is inside an [`Interner`][`super::Interner`].
///
/// # Safety
///
/// This struct could cause Undefined Behaviour on:
/// - Use without ensuring the referenced memory is still allocated.
/// - Construction of an [`InternedStr`] from an invalid [`NonNull<Char>`] pointer.
/// - Construction of an [`InternedStr`] from a [`NonNull<Char>`] pointer
/// without checking if the pointed memory of the [`NonNull<Char>`] outlives
/// the [`InternedStr`].
///
/// In general, this should not be used outside of an [`Interner`][`super::Interner`].
#[derive(Debug)]
pub(super) struct InternedStr<Char> {
ptr: NonNull<[Char]>,
}
impl<Char> InternedStr<Char> {
/// Create a new interned string from the given `*const u8` pointer,
/// length and encoding kind
///
/// # Safety
///
/// Not maintaining the invariants specified on the struct definition
/// could cause Undefined Behaviour.
pub(super) const unsafe fn new(ptr: NonNull<[Char]>) -> Self {
Self { ptr }
}
/// Returns a shared reference to the underlying string.
///
/// # Safety
///
/// Not maintaining the invariants specified on the struct definition
/// could cause Undefined Behaviour.
pub(super) unsafe fn as_ref(&self) -> &[Char] {
// SAFETY:
// The caller must ensure `ptr` is still valid throughout the
// lifetime of `self`.
unsafe { self.ptr.as_ref() }
}
}
impl<Char> Clone for InternedStr<Char> {
fn clone(&self) -> Self {
*self
}
}
impl<Char> Copy for InternedStr<Char> {}
impl<Char> Eq for InternedStr<Char> where Char: Eq {}
impl<Char> PartialEq for InternedStr<Char>
where
Char: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
// SAFETY: The caller must verify the invariants
// specified in the struct definition.
unsafe { self.as_ref() == other.as_ref() }
}
}
impl<Char> Hash for InternedStr<Char>
where
Char: Hash,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
// SAFETY:
// The caller must ensure `ptr` is still valid throughout the
// lifetime of `self`.
unsafe {
self.as_ref().hash(state);
}
}
}

306
boa_interner/src/lib.rs

@ -77,19 +77,27 @@
extern crate alloc; extern crate alloc;
mod fixed_string;
mod interned_str;
mod raw;
mod sym; mod sym;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use alloc::{borrow::Cow, format, string::String}; use alloc::{format, string::String};
use raw::RawInterner; use boa_types::string::{
common::{StaticJsStrings, RAW_STATICS},
JsString, JsStringSlice,
};
use alloc::vec::Vec;
use core::hash::BuildHasherDefault;
use hashbrown::{hash_map::Entry, HashMap};
use rustc_hash::FxHasher;
pub use sym::*; pub use sym::*;
pub use boa_types::js_string;
type Map<T, U> = HashMap<T, U, BuildHasherDefault<FxHasher>>;
/// An enumeration of all slice types [`Interner`] can internally store. /// An enumeration of all slice types [`Interner`] can internally store.
/// ///
/// This struct allows us to intern either `UTF-8` or `UTF-16` str references, which are the two /// This struct allows us to intern either `UTF-8` or `UTF-16` str references, which are the two
@ -121,107 +129,47 @@ impl<'a, const N: usize> From<&'a [u16; N]> for JStrRef<'a> {
} }
} }
/// A double reference to an interned string inside [`Interner`]. #[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// pub struct JSInternedStrRef {
/// [`JSInternedStrRef::utf8`] returns an [`Option`], since not every `UTF-16` string is fully inner: JsString,
/// representable as a `UTF-8` string (because of unpaired surrogates). However, every `UTF-8`
/// string is representable as a `UTF-16` string, so `JSInternedStrRef::utf8` returns a
/// [<code>&\[u16\]</code>][core::slice].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct JSInternedStrRef<'a, 'b> {
utf8: Option<&'a str>,
utf16: &'b [u16],
} }
impl<'a, 'b> JSInternedStrRef<'a, 'b> { impl core::ops::Deref for JSInternedStrRef {
/// Returns the inner reference to the interned string in `UTF-8` encoding. type Target = JsString;
/// if the string is not representable in `UTF-8`, returns [`None`] fn deref(&self) -> &Self::Target {
#[inline] &self.inner
#[must_use]
pub const fn utf8(&self) -> Option<&'a str> {
self.utf8
}
/// Returns the inner reference to the interned string in `UTF-16` encoding.
#[inline]
#[must_use]
pub const fn utf16(&self) -> &'b [u16] {
self.utf16
}
/// Joins the result of both possible strings into a common type.
///
/// If `self` is representable by a `UTF-8` string and the `prioritize_utf8` argument is set,
/// it will prioritize calling `f`, and will only call `g` if `self` is only representable by a
/// `UTF-16` string. Otherwise, it will directly call `g`.
pub fn join<F, G, T>(self, f: F, g: G, prioritize_utf8: bool) -> T
where
F: FnOnce(&'a str) -> T,
G: FnOnce(&'b [u16]) -> T,
{
if prioritize_utf8 {
if let Some(str) = self.utf8 {
return f(str);
}
}
g(self.utf16)
} }
}
/// Same as [`join`][`JSInternedStrRef::join`], but where you can pass an additional context. impl From<JsString> for JSInternedStrRef {
/// fn from(value: JsString) -> Self {
/// Useful when you have a `&mut Context` context that cannot be borrowed by both closures at Self { inner: value }
/// the same time.
pub fn join_with_context<C, F, G, T>(self, f: F, g: G, ctx: C, prioritize_utf8: bool) -> T
where
F: FnOnce(&'a str, C) -> T,
G: FnOnce(&'b [u16], C) -> T,
{
if prioritize_utf8 {
if let Some(str) = self.utf8 {
return f(str, ctx);
}
}
g(self.utf16, ctx)
} }
}
/// Converts both string types into a common type `C`. impl From<JSInternedStrRef> for JsString {
/// fn from(value: JSInternedStrRef) -> Self {
/// If `self` is representable by a `UTF-8` string and the `prioritize_utf8` argument is set, it value.inner
/// will prioritize converting its `UTF-8` representation first, and will only convert its
/// `UTF-16` representation if it is only representable by a `UTF-16` string. Otherwise, it will
/// directly convert its `UTF-16` representation.
pub fn into_common<C>(self, prioritize_utf8: bool) -> C
where
C: From<&'a str> + From<&'b [u16]>,
{
self.join(Into::into, Into::into, prioritize_utf8)
} }
} }
impl core::fmt::Display for JSInternedStrRef<'_, '_> { impl core::fmt::Display for JSInternedStrRef {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.join_with_context( char::decode_utf16(self.inner.iter())
core::fmt::Display::fmt, .map(|r| match r {
|js, f| { Ok(c) => String::from(c),
char::decode_utf16(js.iter().copied()) Err(e) => format!("\\u{:04X}", e.unpaired_surrogate()),
.map(|r| match r { })
Ok(c) => String::from(c), .collect::<String>()
Err(e) => format!("\\u{:04X}", e.unpaired_surrogate()), .fmt(f)
})
.collect::<String>()
.fmt(f)
},
f,
true,
)
} }
} }
/// The string interner for Boa. /// The string interner for Boa.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Interner { pub struct Interner {
utf8_interner: RawInterner<u8>, symbol_cache: Map<JsString, usize>,
utf16_interner: RawInterner<u16>, full: Vec<JsString>,
} }
impl Interner { impl Interner {
@ -235,10 +183,10 @@ impl Interner {
/// Creates a new [`Interner`] with the specified capacity. /// Creates a new [`Interner`] with the specified capacity.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(_capacity: usize) -> Self {
Self { Self {
utf8_interner: RawInterner::with_capacity(capacity), symbol_cache: Map::default(),
utf16_interner: RawInterner::with_capacity(capacity), full: Vec::new(),
} }
} }
@ -246,37 +194,14 @@ impl Interner {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
// `utf16_interner.len()` == `utf8_interner.len()`, self.full.len()
// so we can use any of them.
COMMON_STRINGS_UTF8.len() + self.utf16_interner.len()
} }
/// Returns `true` if the [`Interner`] contains no interned strings. /// Returns `true` if the [`Interner`] contains no interned strings.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
COMMON_STRINGS_UTF8.is_empty() && self.utf16_interner.is_empty() self.full.is_empty()
}
/// Returns the symbol for the given string if any.
///
/// Can be used to query if a string has already been interned without interning.
pub fn get<'a, T>(&self, string: T) -> Option<Sym>
where
T: Into<JStrRef<'a>>,
{
let string = string.into();
Self::get_common(string).or_else(|| {
let index = match string {
JStrRef::Utf8(s) => self.utf8_interner.get(s.as_bytes()),
JStrRef::Utf16(s) => self.utf16_interner.get(s),
};
// SAFETY:
// `get_or_intern/get_or_intern_static` already have checks to avoid returning indices
// that could cause overflows, meaning the indices returned by
// `idx + 1 + COMMON_STRINGS_UTF8.len()` cannot cause overflows.
unsafe { index.map(|i| Sym::new_unchecked(i + 1 + COMMON_STRINGS_UTF8.len())) }
})
} }
/// Interns the given string. /// Interns the given string.
@ -288,116 +213,39 @@ impl Interner {
/// If the interner already interns the maximum number of strings possible by the chosen symbol type. /// If the interner already interns the maximum number of strings possible by the chosen symbol type.
pub fn get_or_intern<'a, T>(&mut self, string: T) -> Sym pub fn get_or_intern<'a, T>(&mut self, string: T) -> Sym
where where
T: Into<JStrRef<'a>>, T: Into<JsStringSlice<'a>>,
{ {
let string = string.into(); let string = JsString::from(string.into());
self.get(string).unwrap_or_else(|| { if let Some(index) = string.as_static() {
let (utf8, utf16) = match string { return Sym::new(index + 1).expect("should not be zero");
JStrRef::Utf8(s) => ( }
Some(Cow::Borrowed(s)), let next_index = self.full.len();
Cow::Owned(s.encode_utf16().collect()), match self.symbol_cache.entry(string.clone()) {
), Entry::Occupied(entry) => {
JStrRef::Utf16(s) => (String::from_utf16(s).ok().map(Cow::Owned), Cow::Borrowed(s)), return Sym::new(*entry.get() + 1 + RAW_STATICS.len()).expect("should not be zero");
}; }
Entry::Vacant(entry) => {
// We need a way to check for the strings that can be interned by `utf16_interner` but entry.insert(next_index);
// not by `utf8_interner` (since there are some UTF-16 strings with surrogates that are }
// not representable in UTF-8), so we use the sentinel value `""` as a marker indicating }
// that the `Sym` corresponding to that string is only available in `utf16_interner`.
//
// We don't need to worry about matches with `""` inside `get`, because
// `COMMON_STRINGS_UTF8` filters all the empty strings before interning.
let index = if let Some(utf8) = utf8 {
self.utf8_interner.intern(utf8.as_bytes())
} else {
self.utf8_interner.intern_static(b"")
};
let utf16_index = self.utf16_interner.intern(&utf16);
// Just to check everything is okay
assert_eq!(index, utf16_index);
index
.checked_add(1 + COMMON_STRINGS_UTF8.len())
.and_then(Sym::new)
.expect("Cannot intern new string: integer overflow")
})
}
/// Interns the given `'static` string. self.full.push(string);
///
/// Returns a symbol for resolution into the original string. Sym::new(next_index + 1 + RAW_STATICS.len()).expect("should not be zero")
///
/// # Note
///
/// This is more efficient than [`Interner::get_or_intern`], since it avoids allocating space
/// for one `string` inside the [`Interner`], with the disadvantage that you need to provide
/// both the `UTF-8` and the `UTF-16` representation of the string.
///
/// # Panics
///
/// If the interner already interns the maximum number of strings possible by the chosen symbol type.
pub fn get_or_intern_static(&mut self, utf8: &'static str, utf16: &'static [u16]) -> Sym {
// Uses the utf8 because it's quicker to check inside `COMMON_STRINGS_UTF8`
// (which is a perfect hash set) than to check inside `COMMON_STRINGS_UTF16`
// (which is a lazy static hash set).
self.get(utf8).unwrap_or_else(|| {
let index = self.utf8_interner.intern(utf8.as_bytes());
let utf16_index = self.utf16_interner.intern(utf16);
// Just to check everything is okay
debug_assert_eq!(index, utf16_index);
index
.checked_add(1 + COMMON_STRINGS_UTF8.len())
.and_then(Sym::new)
.expect("Cannot intern new string: integer overflow")
})
} }
/// Returns the string for the given symbol if any. /// Returns the string for the given symbol if any.
///
/// # Panics
///
/// Panics if the size of both statics is not equal or the interners do
/// not have the same size
#[must_use] #[must_use]
pub fn resolve(&self, symbol: Sym) -> Option<JSInternedStrRef<'_, '_>> { pub fn resolve(&self, sym: Sym) -> Option<JSInternedStrRef> {
let index = symbol.get() - 1; let index = sym.get() - 1;
if let Some(utf8) = COMMON_STRINGS_UTF8.index(index).copied() {
let utf16 = COMMON_STRINGS_UTF16
.get_index(index)
.copied()
.expect("The sizes of both statics must be equal");
return Some(JSInternedStrRef {
utf8: Some(utf8),
utf16,
});
}
let index = index - COMMON_STRINGS_UTF8.len(); if index < RAW_STATICS.len() {
return StaticJsStrings::get_string(StaticJsStrings::get(index)?).map(Into::into);
if let Some(utf16) = self.utf16_interner.index(index) {
let index = index - (self.utf16_interner.len() - self.utf8_interner.len());
// SAFETY:
// We only manipulate valid UTF-8 `str`s and convert them to `[u8]` for convenience,
// so converting back to a `str` is safe.
let utf8 = unsafe {
core::str::from_utf8_unchecked(
self.utf8_interner
.index(index)
.expect("both interners must have the same size"),
)
};
return Some(JSInternedStrRef {
utf8: if utf8.is_empty() { None } else { Some(utf8) },
utf16,
});
} }
None let index = index - RAW_STATICS.len();
self.full.get(index).cloned().map(Into::into)
} }
/// Returns the string for the given symbol. /// Returns the string for the given symbol.
@ -407,27 +255,9 @@ impl Interner {
/// If the interner cannot resolve the given symbol. /// If the interner cannot resolve the given symbol.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn resolve_expect(&self, symbol: Sym) -> JSInternedStrRef<'_, '_> { pub fn resolve_expect(&self, symbol: Sym) -> JSInternedStrRef {
self.resolve(symbol).expect("string disappeared") self.resolve(symbol).expect("string disappeared")
} }
/// Gets the symbol of the common string if one of them
fn get_common(string: JStrRef<'_>) -> Option<Sym> {
match string {
JStrRef::Utf8(s) => COMMON_STRINGS_UTF8.get_index(s).map(|idx| {
// SAFETY: `idx >= 0`, since it's an `usize`, and `idx + 1 > 0`.
// In this case, we don't need to worry about overflows because we have a static
// assertion in place checking that `COMMON_STRINGS.len() < usize::MAX`.
unsafe { Sym::new_unchecked(idx + 1) }
}),
JStrRef::Utf16(s) => COMMON_STRINGS_UTF16.get_index_of(&s).map(|idx| {
// SAFETY: `idx >= 0`, since it's an `usize`, and `idx + 1 > 0`.
// In this case, we don't need to worry about overflows because we have a static
// assertion in place checking that `COMMON_STRINGS.len() < usize::MAX`.
unsafe { Sym::new_unchecked(idx + 1) }
}),
}
}
} }
/// Implements the display formatting with indentation. /// Implements the display formatting with indentation.

194
boa_interner/src/raw.rs

@ -1,194 +0,0 @@
use crate::{fixed_string::FixedString, interned_str::InternedStr};
use alloc::vec::Vec;
use core::hash::{BuildHasherDefault, Hash};
use hashbrown::HashMap;
use rustc_hash::FxHasher;
type Map<T, U> = HashMap<T, U, BuildHasherDefault<FxHasher>>;
/// Raw string interner, generic by a char type.
#[derive(Debug)]
pub(super) struct RawInterner<Char> {
// COMMENT FOR DEVS:
// This interner works on the assumption that
// `head` won't ever be reallocated, since this could invalidate
// some of our stored pointers inside `spans`.
// This means that any operation on `head` and `full` should be carefully
// reviewed to not cause Undefined Behaviour.
// `intern` has a more thorough explanation on this.
//
// Also, if you want to implement `shrink_to_fit` (and friends),
// please check out https://github.com/Robbepop/string-interner/pull/47 first.
// This doesn't implement that method, since implementing it increases
// our memory footprint.
symbol_cache: Map<InternedStr<Char>, usize>,
spans: Vec<InternedStr<Char>>,
head: FixedString<Char>,
full: Vec<FixedString<Char>>,
}
impl<Char> Default for RawInterner<Char> {
fn default() -> Self {
Self {
symbol_cache: Map::default(),
spans: Vec::default(),
head: FixedString::default(),
full: Vec::default(),
}
}
}
impl<Char> RawInterner<Char> {
/// Creates a new `RawInterner` with the specified capacity.
pub(super) fn with_capacity(capacity: usize) -> Self {
Self {
symbol_cache: Map::default(),
spans: Vec::with_capacity(capacity),
head: FixedString::new(capacity),
full: Vec::new(),
}
}
/// Returns the number of strings interned by the interner.
pub(super) fn len(&self) -> usize {
self.spans.len()
}
/// Returns `true` if the interner contains no interned strings.
pub(super) fn is_empty(&self) -> bool {
self.spans.is_empty()
}
}
impl<Char> RawInterner<Char>
where
Char: Hash + Eq,
{
/// Returns the index position for the given string if any.
///
/// Can be used to query if a string has already been interned without interning.
pub(super) fn get(&self, string: &[Char]) -> Option<usize> {
// SAFETY:
// `string` is a valid slice that doesn't outlive the
// created `InternedStr`, so this is safe.
unsafe {
self.symbol_cache
.get(&InternedStr::new(string.into()))
.copied()
}
}
/// Interns the given `'static` string.
///
/// Returns the index of `string` within the interner.
///
/// # Note
///
/// This is more efficient than [`RawInterner::intern`], since it
/// avoids storing `string` inside the interner.
///
/// # Panics
///
/// If the interner already interns the maximum number of strings possible
/// by the chosen symbol type.
pub(super) fn intern_static(&mut self, string: &'static [Char]) -> usize {
// SAFETY:
// A static string reference is always valid, meaning it cannot outlive
// the lifetime of the created `InternedStr`. This makes this
// operation safe.
let string = unsafe { InternedStr::new(string.into()) };
// SAFETY:
// A `InternedStr` created from a static reference
// cannot be invalidated by allocations and deallocations,
// so this is safe.
unsafe { self.next_index(string) }
}
/// Returns the string for the given index if any.
pub(super) fn index(&self, index: usize) -> Option<&[Char]> {
self.spans.get(index).map(|ptr|
// SAFETY: We always ensure the stored `InternedStr`s always
// reference memory inside `head` and `full`
unsafe {ptr.as_ref()})
}
/// Inserts a new string pointer into `spans` and returns its index.
///
/// # Safety
///
/// The caller must ensure `string` points to a valid
/// memory inside `head` (or only valid in the case of statics)
/// and that it won't be invalidated by allocations and deallocations.
unsafe fn next_index(&mut self, string: InternedStr<Char>) -> usize {
let next = self.len();
self.spans.push(string);
self.symbol_cache.insert(string, next);
next
}
}
impl<Char> RawInterner<Char>
where
Char: Hash + Eq + Clone,
{
/// Interns the given string.
///
/// Returns the index of `string` within the interner.
///
/// # Panics
///
/// If the interner already interns the maximum number of strings possible by the chosen symbol type.
pub(super) fn intern(&mut self, string: &[Char]) -> usize {
// SAFETY:
//
// Firstly, this interner works on the assumption that the allocated
// memory by `head` won't ever be moved from its position on the heap,
// which is an important point to understand why manipulating it like
// this is safe.
//
// `String` (which is simply a `Vec<u8>` with additional invariants)
// is essentially a pointer to heap memory that can be moved without
// any problems, since copying a pointer cannot invalidate the memory
// that it points to.
//
// However, `String` CAN be invalidated when pushing, extending or
// shrinking it, since all those operations reallocate on the heap.
//
// To prevent that, we HAVE to ensure the capacity will succeed without
// having to reallocate, and the only way to do that without invalidating
// any other alive `InternedStr` is to create a brand new `head` with
// enough capacity and push the old `head` to `full` to keep it alive
// throughout the lifetime of the whole interner.
//
// `FixedString` encapsulates this by only allowing checked `push`es
// to the internal string, but we still have to ensure the memory
// of `head` is not deallocated until the whole interner deallocates,
// which we can do by moving it inside the interner itself, specifically
// on the `full` vector, where every other old `head` also lives.
let interned_str = unsafe {
self.head.push(string).unwrap_or_else(|| {
let new_cap =
(usize::max(self.head.capacity(), string.len()) + 1).next_power_of_two();
let new_head = FixedString::new(new_cap);
let old_head = core::mem::replace(&mut self.head, new_head);
// If the user creates an `Interner`
// with `Interner::with_capacity(BIG_NUMBER)` and
// the first interned string's length is bigger than `BIG_NUMBER`,
// `self.full.push(old_head)` would push a big, empty string of
// allocated size `BIG_NUMBER` into `full`.
// This prevents that case.
if !old_head.is_empty() {
self.full.push(old_head);
}
self.head.push_unchecked(string)
})
};
// SAFETY: We are obtaining a pointer to the internal memory of
// `head`, which is alive through the whole life of the interner, so
// this is safe.
unsafe { self.next_index(interned_str) }
}
}

55
boa_interner/src/tests.rs

@ -1,4 +1,4 @@
use crate::{Interner, Sym, COMMON_STRINGS_UTF16, COMMON_STRINGS_UTF8}; use crate::{Interner, Sym, COMMON_STRINGS_UTF8};
use boa_macros::utf16; use boa_macros::utf16;
#[track_caller] #[track_caller]
@ -34,13 +34,13 @@ fn check_resolve() {
for (s8, s16) in utf_8_strings.zip(utf_16_strings) { for (s8, s16) in utf_8_strings.zip(utf_16_strings) {
let sym = interner.get_or_intern(s8); let sym = interner.get_or_intern(s8);
let resolved = interner.resolve(sym).unwrap(); let resolved = interner.resolve(sym).unwrap();
assert_eq!(Some(s8), resolved.utf8()); assert_eq!(s8, &*resolved);
let new_sym = interner.get_or_intern(s8); let new_sym = interner.get_or_intern(s8);
assert_eq!(sym, new_sym); assert_eq!(sym, new_sym);
let sym = interner.get_or_intern(s16); let sym = interner.get_or_intern(s16);
let resolved = interner.resolve(sym).unwrap(); let resolved = interner.resolve(sym).unwrap();
assert_eq!(s16, resolved.utf16()); assert_eq!(s16, &*resolved);
let new_sym = interner.get_or_intern(s16); let new_sym = interner.get_or_intern(s16);
assert_eq!(sym, new_sym); assert_eq!(sym, new_sym);
} }
@ -50,26 +50,16 @@ fn check_resolve() {
fn check_static_resolve() { fn check_static_resolve() {
let mut interner = Interner::default(); let mut interner = Interner::default();
for (utf8, utf16) in COMMON_STRINGS_UTF8 for string in COMMON_STRINGS_UTF8
.into_iter() .into_iter()
.copied() .copied()
.zip(COMMON_STRINGS_UTF16.iter().copied()) .chain(["my test str", "hello world", ";"].into_iter())
.chain(
[
("my test str", utf16!("my test str")),
("hello world", utf16!("hello world")),
(";", utf16!(";")),
]
.into_iter(),
)
{ {
let sym = interner.get_or_intern_static(utf8, utf16); let sym = interner.get_or_intern(string);
let resolved = interner.resolve(sym).unwrap(); let resolved = interner.resolve(sym).unwrap();
assert_eq!(Some(utf8), resolved.utf8()); assert_eq!(string, &*resolved);
assert_eq!(utf16, resolved.utf16());
let new_sym = interner.get_or_intern(utf8);
let new_sym = interner.get_or_intern(string);
assert_eq!(sym, new_sym); assert_eq!(sym, new_sym);
} }
} }
@ -88,29 +78,18 @@ fn check_unpaired_surrogates() {
let sym = interner.get_or_intern("abc"); let sym = interner.get_or_intern("abc");
let sym2 = interner.get_or_intern("def"); let sym2 = interner.get_or_intern("def");
let sym3 = interner.get_or_intern(unp); let sym3 = interner.get_or_intern(&unp[..]);
let sym4 = interner.get_or_intern(utf16!("ghi")); let sym4 = interner.get_or_intern("ghi");
let sym5 = interner.get_or_intern(unp2); let sym5 = interner.get_or_intern(&unp2[..]);
let sym6 = interner.get_or_intern("jkl"); let sym6 = interner.get_or_intern("jkl");
assert_eq!(interner.resolve_expect(sym).utf8(), Some("abc")); assert_eq!(&*interner.resolve_expect(sym), "abc");
assert_eq!(interner.resolve_expect(sym).utf16(), utf16!("abc")); assert_eq!(&*interner.resolve_expect(sym2), "def");
assert_eq!(&*interner.resolve_expect(sym3), &unp[..]);
assert_eq!(interner.resolve_expect(sym2).utf8(), Some("def")); assert_eq!(&*interner.resolve_expect(sym4), "ghi");
assert_eq!(interner.resolve_expect(sym2).utf16(), utf16!("def")); assert_eq!(&*interner.resolve_expect(sym5), &unp2[..]);
assert_eq!(&*interner.resolve_expect(sym6), "jkl");
assert!(interner.resolve_expect(sym3).utf8().is_none());
assert_eq!(interner.resolve_expect(sym3).utf16(), unp);
assert_eq!(interner.resolve_expect(sym4).utf8(), Some("ghi"));
assert_eq!(interner.resolve_expect(sym4).utf16(), utf16!("ghi"));
assert!(interner.resolve_expect(sym5).utf8().is_none());
assert_eq!(interner.resolve_expect(sym5).utf16(), unp2);
assert_eq!(interner.resolve_expect(sym6).utf8(), Some("jkl"));
assert_eq!(interner.resolve_expect(sym6).utf16(), utf16!("jkl"));
} }
#[test] #[test]

20
boa_macros/src/lib.rs

@ -178,26 +178,6 @@ pub fn static_syms(input: TokenStream) -> TokenStream {
::static_assertions::const_assert!(COMMON_STRINGS.len() < usize::MAX); ::static_assertions::const_assert!(COMMON_STRINGS.len() < usize::MAX);
COMMON_STRINGS COMMON_STRINGS
}; };
/// Ordered set of commonly used static `UTF-16` strings.
///
/// # Note
///
/// `COMMON_STRINGS_UTF8`, `COMMON_STRINGS_UTF16` and the constants
/// defined in [`Sym`] must always be in sync.
// FIXME: use phf when const expressions are allowed.
// <https://github.com/rust-phf/rust-phf/issues/188>
pub(super) static COMMON_STRINGS_UTF16: ::once_cell::sync::Lazy<Set<&'static [u16]>> =
::once_cell::sync::Lazy::new(|| {
let mut set = Set::with_capacity_and_hasher(
COMMON_STRINGS_UTF8.len(),
::core::hash::BuildHasherDefault::default()
);
#(
set.insert(::boa_macros::utf16!(#literals));
)*
set
});
}; };
quote! { quote! {

1
boa_parser/Cargo.toml

@ -12,7 +12,6 @@ rust-version.workspace = true
[dependencies] [dependencies]
boa_interner.workspace = true boa_interner.workspace = true
boa_macros.workspace = true
boa_ast.workspace = true boa_ast.workspace = true
boa_profiler.workspace = true boa_profiler.workspace = true
rustc-hash = { workspace = true, features = ["std"] } rustc-hash = { workspace = true, features = ["std"] }

77
boa_parser/src/lexer/tests.rs

@ -7,7 +7,6 @@ use crate::lexer::{
}; };
use boa_ast::Keyword; use boa_ast::Keyword;
use boa_interner::Sym; use boa_interner::Sym;
use boa_macros::utf16;
use std::str; use std::str;
fn span(start: (u32, u32), end: (u32, u32)) -> Span { fn span(start: (u32, u32), end: (u32, u32)) -> Span {
@ -66,7 +65,7 @@ fn check_multi_line_comment() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("x", utf16!("x")); let sym = interner.get_or_intern("x");
let expected = [ let expected = [
TokenKind::Keyword((Keyword::Var, false)), TokenKind::Keyword((Keyword::Var, false)),
TokenKind::LineTerminator, TokenKind::LineTerminator,
@ -83,29 +82,18 @@ fn check_identifier() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let expected = [ let expected = [
TokenKind::identifier(interner.get_or_intern_static("x", utf16!("x"))), TokenKind::identifier(interner.get_or_intern("x")),
TokenKind::identifier(interner.get_or_intern_static("x1", utf16!("x1"))), TokenKind::identifier(interner.get_or_intern("x1")),
TokenKind::identifier(interner.get_or_intern_static("_x", utf16!("_x"))), TokenKind::identifier(interner.get_or_intern("_x")),
TokenKind::identifier(interner.get_or_intern_static("$x", utf16!("$x"))), TokenKind::identifier(interner.get_or_intern("$x")),
TokenKind::identifier(interner.get_or_intern_static("__", utf16!("__"))), TokenKind::identifier(interner.get_or_intern("__")),
TokenKind::identifier(interner.get_or_intern_static("$$", utf16!("$$"))), TokenKind::identifier(interner.get_or_intern("$$")),
TokenKind::identifier(interner.get_or_intern_static("Ѐ", utf16!("Ѐ"))), TokenKind::identifier(interner.get_or_intern("Ѐ")),
TokenKind::identifier(interner.get_or_intern_static("ЀЀ", utf16!("ЀЀ"))), TokenKind::identifier(interner.get_or_intern("ЀЀ")),
TokenKind::identifier( TokenKind::identifier(interner.get_or_intern("x\u{200C}\u{200D}")),
interner.get_or_intern_static("x\u{200C}\u{200D}", utf16!("x\u{200C}\u{200D}")), TokenKind::IdentifierName((interner.get_or_intern("x"), ContainsEscapeSequence(true))),
), TokenKind::IdentifierName((interner.get_or_intern("xx"), ContainsEscapeSequence(true))),
TokenKind::IdentifierName(( TokenKind::IdentifierName((interner.get_or_intern("xxx"), ContainsEscapeSequence(true))),
interner.get_or_intern_static("x", utf16!("x")),
ContainsEscapeSequence(true),
)),
TokenKind::IdentifierName((
interner.get_or_intern_static("xx", utf16!("xx")),
ContainsEscapeSequence(true),
)),
TokenKind::IdentifierName((
interner.get_or_intern_static("xxx", utf16!("xxx")),
ContainsEscapeSequence(true),
)),
]; ];
expect_tokens(&mut lexer, &expected, interner); expect_tokens(&mut lexer, &expected, interner);
@ -129,7 +117,7 @@ fn check_invalid_identifier_part() {
let invalid_identifier_parts = [" ", "\n", ".", "*", "😀", "\u{007F}"]; let invalid_identifier_parts = [" ", "\n", ".", "*", "😀", "\u{007F}"];
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("x", utf16!("x")); let sym = interner.get_or_intern("x");
for part in &invalid_identifier_parts { for part in &invalid_identifier_parts {
let s = String::from("x") + part; let s = String::from("x") + part;
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
@ -147,8 +135,8 @@ fn check_string() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a_sym = interner.get_or_intern_static("aaa", utf16!("aaa")); let a_sym = interner.get_or_intern("aaa");
let b_sym = interner.get_or_intern_static("bbb", utf16!("bbb")); let b_sym = interner.get_or_intern("bbb");
let expected = [ let expected = [
TokenKind::string_literal(a_sym, EscapeSequence::empty()), TokenKind::string_literal(a_sym, EscapeSequence::empty()),
TokenKind::string_literal(b_sym, EscapeSequence::empty()), TokenKind::string_literal(b_sym, EscapeSequence::empty()),
@ -163,8 +151,7 @@ fn check_template_literal_simple() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = let sym = interner.get_or_intern("I'm a template literal");
interner.get_or_intern_static("I'm a template literal", utf16!("I'm a template literal"));
assert_eq!( assert_eq!(
lexer.next(interner).unwrap().unwrap().kind(), lexer.next(interner).unwrap().unwrap().kind(),
@ -308,8 +295,8 @@ fn check_variable_definition_tokens() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a_sym = interner.get_or_intern_static("a", utf16!("a")); let a_sym = interner.get_or_intern("a");
let hello_sym = interner.get_or_intern_static("hello", utf16!("hello")); let hello_sym = interner.get_or_intern("hello");
let expected = [ let expected = [
TokenKind::Keyword((Keyword::Let, false)), TokenKind::Keyword((Keyword::Let, false)),
TokenKind::identifier(a_sym), TokenKind::identifier(a_sym),
@ -601,7 +588,7 @@ fn hexadecimal_edge_case() {
let mut lexer = Lexer::new(&b"0xffff.ff 0xffffff"[..]); let mut lexer = Lexer::new(&b"0xffff.ff 0xffffff"[..]);
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("ff", utf16!("ff")); let sym = interner.get_or_intern("ff");
let expected = [ let expected = [
TokenKind::numeric_literal(0xffff), TokenKind::numeric_literal(0xffff),
TokenKind::Punctuator(Punctuator::Dot), TokenKind::Punctuator(Punctuator::Dot),
@ -641,7 +628,7 @@ fn regex_literal() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let expected = [TokenKind::regular_expression_literal( let expected = [TokenKind::regular_expression_literal(
interner.get_or_intern_static("(?:)", utf16!("(?:)")), interner.get_or_intern("(?:)"),
Sym::EMPTY_STRING, Sym::EMPTY_STRING,
)]; )];
@ -655,12 +642,9 @@ fn regex_equals_following_assignment() {
let expected = [ let expected = [
TokenKind::Keyword((Keyword::Const, false)), TokenKind::Keyword((Keyword::Const, false)),
TokenKind::identifier(interner.get_or_intern_static("myRegex", utf16!("myRegex"))), TokenKind::identifier(interner.get_or_intern("myRegex")),
TokenKind::Punctuator(Punctuator::Assign), TokenKind::Punctuator(Punctuator::Assign),
TokenKind::regular_expression_literal( TokenKind::regular_expression_literal(interner.get_or_intern("="), Sym::EMPTY_STRING),
interner.get_or_intern_static("=", utf16!("=")),
Sym::EMPTY_STRING,
),
TokenKind::Punctuator(Punctuator::Semicolon), TokenKind::Punctuator(Punctuator::Semicolon),
]; ];
@ -673,8 +657,8 @@ fn regex_literal_flags() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let expected = [TokenKind::regular_expression_literal( let expected = [TokenKind::regular_expression_literal(
interner.get_or_intern_static("\\/[^\\/]*\\/*", utf16!("\\/[^\\/]*\\/*")), interner.get_or_intern("\\/[^\\/]*\\/*"),
interner.get_or_intern_static("gim", utf16!("gim")), interner.get_or_intern("gim"),
)]; )];
expect_tokens(&mut lexer, &expected, interner); expect_tokens(&mut lexer, &expected, interner);
@ -950,7 +934,7 @@ fn string_unicode() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("中文", utf16!("中文")); let sym = interner.get_or_intern("中文");
let expected = [ let expected = [
TokenKind::StringLiteral((sym, EscapeSequence::empty())), TokenKind::StringLiteral((sym, EscapeSequence::empty())),
TokenKind::Punctuator(Punctuator::Semicolon), TokenKind::Punctuator(Punctuator::Semicolon),
@ -964,8 +948,7 @@ fn string_unicode_escape_with_braces() {
let mut lexer = Lexer::new(&br"'{\u{20ac}\u{a0}\u{a0}}'"[..]); let mut lexer = Lexer::new(&br"'{\u{20ac}\u{a0}\u{a0}}'"[..]);
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = let sym = interner.get_or_intern("{\u{20ac}\u{a0}\u{a0}}");
interner.get_or_intern_static("{\u{20ac}\u{a0}\u{a0}}", utf16!("{\u{20ac}\u{a0}\u{a0}}"));
let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))]; let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))];
expect_tokens(&mut lexer, &expected, interner); expect_tokens(&mut lexer, &expected, interner);
@ -1000,7 +983,7 @@ fn string_unicode_escape_with_braces_2() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("\u{20ac}\u{a0}\u{a0}", utf16!("\u{20ac}\u{a0}\u{a0}")); let sym = interner.get_or_intern("\u{20ac}\u{a0}\u{a0}");
let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))]; let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))];
expect_tokens(&mut lexer, &expected, interner); expect_tokens(&mut lexer, &expected, interner);
@ -1013,7 +996,7 @@ fn string_with_single_escape() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("Б", utf16!("Б")); let sym = interner.get_or_intern("Б");
let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))]; let expected = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))];
expect_tokens(&mut lexer, &expected, interner); expect_tokens(&mut lexer, &expected, interner);
@ -1115,7 +1098,7 @@ fn string_line_continuation() {
let mut lexer = Lexer::new(s.as_bytes()); let mut lexer = Lexer::new(s.as_bytes());
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let sym = interner.get_or_intern_static("hello world", utf16!("hello world")); let sym = interner.get_or_intern("hello world");
let expected_tokens = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))]; let expected_tokens = [TokenKind::StringLiteral((sym, EscapeSequence::OTHER))];
expect_tokens(&mut lexer, &expected_tokens, interner); expect_tokens(&mut lexer, &expected_tokens, interner);

57
boa_parser/src/parser/cursor/buffered_lexer/tests.rs

@ -3,7 +3,6 @@ use crate::{
parser::cursor::BufferedLexer, parser::cursor::BufferedLexer,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn peek_skip_accending() { fn peek_skip_accending() {
@ -15,42 +14,42 @@ fn peek_skip_accending() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("b", utf16!("b"))) TokenKind::identifier(interner.get_or_intern("b"))
); );
assert_eq!( assert_eq!(
*cur.peek(2, false, interner) *cur.peek(2, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.peek(2, false, interner) *cur.peek(2, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("b", utf16!("b"))) TokenKind::identifier(interner.get_or_intern("b"))
); );
assert_eq!( assert_eq!(
*cur.peek(0, false, interner) *cur.peek(0, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
} }
@ -64,77 +63,77 @@ fn peek_skip_next() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("b", utf16!("b"))) TokenKind::identifier(interner.get_or_intern("b"))
); );
assert_eq!( assert_eq!(
*cur.peek(2, false, interner) *cur.peek(2, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("b", utf16!("b"))) TokenKind::identifier(interner.get_or_intern("b"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("d", utf16!("d"))) TokenKind::identifier(interner.get_or_intern("d"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("e", utf16!("e"))) TokenKind::identifier(interner.get_or_intern("e"))
); );
assert_eq!( assert_eq!(
*cur.peek(0, false, interner) *cur.peek(0, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("f", utf16!("f"))) TokenKind::identifier(interner.get_or_intern("f"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("g", utf16!("g"))) TokenKind::identifier(interner.get_or_intern("g"))
); );
assert_eq!( assert_eq!(
*cur.peek(2, false, interner) *cur.peek(2, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("h", utf16!("h"))) TokenKind::identifier(interner.get_or_intern("h"))
); );
} }
@ -148,49 +147,49 @@ fn peek_skip_next_alternating() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("a", utf16!("a"))) TokenKind::identifier(interner.get_or_intern("a"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("b", utf16!("b"))) TokenKind::identifier(interner.get_or_intern("b"))
); );
assert_eq!( assert_eq!(
*cur.peek(1, false, interner) *cur.peek(1, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("d", utf16!("d"))) TokenKind::identifier(interner.get_or_intern("d"))
); );
assert_eq!( assert_eq!(
*cur.next(false, interner) *cur.next(false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("c", utf16!("c"))) TokenKind::identifier(interner.get_or_intern("c"))
); );
assert_eq!( assert_eq!(
*cur.peek(2, false, interner) *cur.peek(2, false, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("f", utf16!("f"))) TokenKind::identifier(interner.get_or_intern("f"))
); );
} }
@ -244,14 +243,14 @@ fn skip_peeked_terminators() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("A", utf16!("A"))) TokenKind::identifier(interner.get_or_intern("A"))
); );
assert_eq!( assert_eq!(
*cur.peek(0, true, interner) *cur.peek(0, true, interner)
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("A", utf16!("A"))) TokenKind::identifier(interner.get_or_intern("A"))
); );
assert_eq!( assert_eq!(
@ -266,7 +265,7 @@ fn skip_peeked_terminators() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("B", utf16!("B"))) /* This value is after the line terminator */ TokenKind::identifier(interner.get_or_intern("B")) /* This value is after the line terminator */
); );
assert_eq!( assert_eq!(
@ -274,7 +273,7 @@ fn skip_peeked_terminators() {
.unwrap() .unwrap()
.expect("Some value expected") .expect("Some value expected")
.kind(), .kind(),
TokenKind::identifier(interner.get_or_intern_static("B", utf16!("B"))) TokenKind::identifier(interner.get_or_intern("B"))
); );
// End of stream // End of stream
assert!(cur.peek(2, true, interner).unwrap().is_none()); assert!(cur.peek(2, true, interner).unwrap().is_none());

12
boa_parser/src/parser/expression/identifiers.rs

@ -110,10 +110,8 @@ where
let ident = Identifier.parse(cursor, interner)?; let ident = Identifier.parse(cursor, interner)?;
match ident.sym() { match ident.sym() {
Sym::ARGUMENTS | Sym::EVAL if cursor.strict() => { Sym::ARGUMENTS | Sym::EVAL if cursor.strict() => {
let name = interner let name = interner.resolve_expect(ident.sym());
.resolve_expect(ident.sym()) name.as_str().as_ascii().expect("keyword must be utf-8");
.utf8()
.expect("keyword must be utf-8");
Err(Error::general( Err(Error::general(
format!("binding identifier `{name}` not allowed in strict mode"), format!("binding identifier `{name}` not allowed in strict mode"),
span.start(), span.start(),
@ -179,7 +177,8 @@ where
return Err(Error::unexpected( return Err(Error::unexpected(
interner interner
.resolve_expect(ident) .resolve_expect(ident)
.utf8() .as_str()
.as_ascii()
.expect("keyword must always be utf-8"), .expect("keyword must always be utf-8"),
tok.span(), tok.span(),
"strict reserved word cannot be an identifier", "strict reserved word cannot be an identifier",
@ -198,7 +197,8 @@ where
return Err(Error::unexpected( return Err(Error::unexpected(
interner interner
.resolve_expect(ident) .resolve_expect(ident)
.utf8() .as_str()
.as_ascii()
.expect("keyword must always be utf-8"), .expect("keyword must always be utf-8"),
tok.span(), tok.span(),
"reserved word cannot be an identifier", "reserved word cannot be an identifier",

2
boa_parser/src/parser/expression/left_hand_side/mod.rs

@ -99,7 +99,7 @@ where
return Err(Error::general( return Err(Error::general(
format!( format!(
"keyword `{}` cannot contain escaped characters", "keyword `{}` cannot contain escaped characters",
kw.as_str().0 kw.as_str()
), ),
next.span().start(), next.span().start(),
)); ));

14
boa_parser/src/parser/expression/left_hand_side/optional/tests.rs

@ -8,7 +8,6 @@ use boa_ast::{
Expression, Statement, Expression, Statement,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn simple() { fn simple() {
@ -21,9 +20,7 @@ fn simple() {
Literal::Int(5).into(), Literal::Int(5).into(),
vec![OptionalOperation::new( vec![OptionalOperation::new(
OptionalOperationKind::SimplePropertyAccess { OptionalOperationKind::SimplePropertyAccess {
field: PropertyAccessField::Const( field: PropertyAccessField::Const(interner.get_or_intern("name")),
interner.get_or_intern_static("name", utf16!("name")),
),
}, },
true, true,
)] )]
@ -44,13 +41,11 @@ fn complex_chain() {
r#"a?.b(true)?.["c"]"#, r#"a?.b(true)?.["c"]"#,
vec![Statement::Expression( vec![Statement::Expression(
Optional::new( Optional::new(
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
vec![ vec![
OptionalOperation::new( OptionalOperation::new(
OptionalOperationKind::SimplePropertyAccess { OptionalOperationKind::SimplePropertyAccess {
field: PropertyAccessField::Const( field: PropertyAccessField::Const(interner.get_or_intern("b")),
interner.get_or_intern_static("b", utf16!("b")),
),
}, },
true, true,
), ),
@ -63,8 +58,7 @@ fn complex_chain() {
OptionalOperation::new( OptionalOperation::new(
OptionalOperationKind::SimplePropertyAccess { OptionalOperationKind::SimplePropertyAccess {
field: PropertyAccessField::Expr(Box::new( field: PropertyAccessField::Expr(Box::new(
Literal::String(interner.get_or_intern_static("c", utf16!("c"))) Literal::String(interner.get_or_intern("c")).into(),
.into(),
)), )),
}, },
true, true,

9
boa_parser/src/parser/expression/left_hand_side/tests.rs

@ -4,7 +4,6 @@ use boa_ast::{
Expression, Statement, Expression, Statement,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
macro_rules! check_call_property_identifier { macro_rules! check_call_property_identifier {
($property:literal) => {{ ($property:literal) => {{
@ -14,11 +13,11 @@ macro_rules! check_call_property_identifier {
vec![Statement::Expression(Expression::PropertyAccess( vec![Statement::Expression(Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Call::new( Call::new(
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Box::default(), Box::default(),
) )
.into(), .into(),
interner.get_or_intern_static($property, utf16!($property)), interner.get_or_intern($property),
) )
.into(), .into(),
)) ))
@ -44,8 +43,8 @@ macro_rules! check_member_property_identifier {
format!("a.{}", $property).as_str(), format!("a.{}", $property).as_str(),
vec![Statement::Expression(Expression::PropertyAccess( vec![Statement::Expression(Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static($property, utf16!($property)), interner.get_or_intern($property),
) )
.into(), .into(),
)) ))

3
boa_parser/src/parser/expression/primary/array_initializer/tests.rs

@ -6,7 +6,6 @@ use boa_ast::{
Expression, Statement, Expression, Statement,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
/// Checks an empty array. /// Checks an empty array.
#[test] #[test]
@ -108,7 +107,7 @@ fn check_combined() {
vec![ vec![
Statement::Expression(Expression::from(ArrayLiteral::from(vec![ Statement::Expression(Expression::from(ArrayLiteral::from(vec![
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
Some(Literal::from(interner.get_or_intern_static("a", utf16!("a"))).into()), Some(Literal::from(interner.get_or_intern("a")).into()),
Some(Literal::from(2).into()), Some(Literal::from(2).into()),
]))) ])))
.into(), .into(),

7
boa_parser/src/parser/expression/primary/async_function_expression/tests.rs

@ -7,13 +7,12 @@ use boa_ast::{
Statement, StatementListItem, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks async expression parsing. /// Checks async expression parsing.
#[test] #[test]
fn check_async_expression() { fn check_async_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let add = interner.get_or_intern_static("add", utf16!("add")); let add = interner.get_or_intern("add");
check_script_parser( check_script_parser(
"const add = async function() { "const add = async function() {
return 1; return 1;
@ -48,8 +47,8 @@ fn check_async_expression() {
#[test] #[test]
fn check_nested_async_expression() { fn check_nested_async_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
let b = interner.get_or_intern_static("b", utf16!("b")); let b = interner.get_or_intern("b");
check_script_parser( check_script_parser(
"const a = async function() { "const a = async function() {
const b = async function() { const b = async function() {

8
boa_parser/src/parser/expression/primary/async_generator_expression/tests.rs

@ -7,14 +7,12 @@ use boa_ast::{
Declaration, Statement, StatementListItem, Declaration, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
///checks async generator expression parsing ///checks async generator expression parsing
#[test] #[test]
fn check_async_generator_expr() { fn check_async_generator_expr() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let add = interner.get_or_intern_static("add", utf16!("add")); let add = interner.get_or_intern("add");
check_script_parser( check_script_parser(
"const add = async function*(){ "const add = async function*(){
return 1; return 1;
@ -49,8 +47,8 @@ fn check_async_generator_expr() {
#[test] #[test]
fn check_nested_async_generator_expr() { fn check_nested_async_generator_expr() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
let b = interner.get_or_intern_static("b", utf16!("b")); let b = interner.get_or_intern("b");
check_script_parser( check_script_parser(
"const a = async function*() { "const a = async function*() {
const b = async function*() { const b = async function*() {

11
boa_parser/src/parser/expression/primary/function_expression/tests.rs

@ -7,13 +7,12 @@ use boa_ast::{
Declaration, Statement, StatementListItem, Declaration, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks async expression parsing. /// Checks async expression parsing.
#[test] #[test]
fn check_function_expression() { fn check_function_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let add = interner.get_or_intern_static("add", utf16!("add")); let add = interner.get_or_intern("add");
check_script_parser( check_script_parser(
"const add = function() { "const add = function() {
return 1; return 1;
@ -47,8 +46,8 @@ fn check_function_expression() {
#[test] #[test]
fn check_nested_function_expression() { fn check_nested_function_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
let b = interner.get_or_intern_static("b", utf16!("b")); let b = interner.get_or_intern("b");
check_script_parser( check_script_parser(
"const a = function() { "const a = function() {
const b = function() { const b = function() {
@ -107,10 +106,10 @@ fn check_function_non_reserved_keyword() {
($keyword:literal, $interner:expr) => { ($keyword:literal, $interner:expr) => {
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
$interner.get_or_intern_static("add", utf16!("add")).into(), $interner.get_or_intern("add").into(),
Some( Some(
Function::new_with_binding_identifier( Function::new_with_binding_identifier(
Some($interner.get_or_intern_static($keyword, utf16!($keyword)).into()), Some($interner.get_or_intern($keyword).into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement( vec![StatementListItem::Statement(

5
boa_parser/src/parser/expression/primary/generator_expression/tests.rs

@ -6,12 +6,11 @@ use boa_ast::{
Declaration, Expression, Statement, StatementListItem, Declaration, Expression, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn check_generator_function_expression() { fn check_generator_function_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let gen = interner.get_or_intern_static("gen", utf16!("gen")); let gen = interner.get_or_intern("gen");
check_script_parser( check_script_parser(
"const gen = function*() { "const gen = function*() {
yield 1; yield 1;
@ -46,7 +45,7 @@ fn check_generator_function_expression() {
#[test] #[test]
fn check_generator_function_delegate_yield_expression() { fn check_generator_function_delegate_yield_expression() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let gen = interner.get_or_intern_static("gen", utf16!("gen")); let gen = interner.get_or_intern("gen");
check_script_parser( check_script_parser(
"const gen = function*() { "const gen = function*() {
yield* 1; yield* 1;

16
boa_parser/src/parser/expression/primary/object_initializer/mod.rs

@ -37,8 +37,7 @@ use boa_ast::{
property::{self, MethodDefinition}, property::{self, MethodDefinition},
Expression, Keyword, Punctuator, Expression, Keyword, Punctuator,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{js_string, Interner, Sym};
use boa_macros::utf16;
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::io::Read; use std::io::Read;
@ -358,9 +357,9 @@ where
)?; )?;
let name = property_name.literal().map(|name| { let name = property_name.literal().map(|name| {
let s = interner.resolve_expect(name).utf16(); let s = interner.resolve_expect(name);
interner interner
.get_or_intern([utf16!("get "), s].concat().as_slice()) .get_or_intern(js_string!("get ", &*s).as_str())
.into() .into()
}); });
@ -451,9 +450,9 @@ where
)?; )?;
let name = property_name.literal().map(|name| { let name = property_name.literal().map(|name| {
let s = interner.resolve_expect(name).utf16(); let s = interner.resolve_expect(name);
interner interner
.get_or_intern([utf16!("set "), s].concat().as_slice()) .get_or_intern(js_string!("set ", &*s).as_str())
.into() .into()
}); });
@ -599,10 +598,7 @@ where
Numeric::Integer(num) => Expression::Literal(Literal::from(*num)).into(), Numeric::Integer(num) => Expression::Literal(Literal::from(*num)).into(),
Numeric::BigInt(num) => Expression::Literal(Literal::from(num.clone())).into(), Numeric::BigInt(num) => Expression::Literal(Literal::from(num.clone())).into(),
}, },
TokenKind::Keyword((word, _)) => { TokenKind::Keyword((word, _)) => interner.get_or_intern(word.as_str()).into(),
let (utf8, utf16) = word.as_str();
interner.get_or_intern_static(utf8, utf16).into()
}
TokenKind::NullLiteral(_) => (Sym::NULL).into(), TokenKind::NullLiteral(_) => (Sym::NULL).into(),
TokenKind::BooleanLiteral((bool, _)) => match bool { TokenKind::BooleanLiteral((bool, _)) => match bool {
true => Sym::TRUE.into(), true => Sym::TRUE.into(),

128
boa_parser/src/parser/expression/primary/object_initializer/tests.rs

@ -13,7 +13,6 @@ use boa_ast::{
Declaration, Declaration,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
/// Checks object literal parsing. /// Checks object literal parsing.
#[test] #[test]
@ -22,11 +21,11 @@ fn check_object_literal() {
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Literal::from(true).into(), Literal::from(true).into(),
), ),
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
Literal::from(false).into(), Literal::from(false).into(),
), ),
]; ];
@ -39,7 +38,7 @@ fn check_object_literal() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -57,13 +56,13 @@ fn check_object_short_function() {
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Literal::from(true).into(), Literal::from(true).into(),
), ),
PropertyDefinition::MethodDefinition( PropertyDefinition::MethodDefinition(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
Some(interner.get_or_intern_static("b", utf16!("b")).into()), Some(interner.get_or_intern("b").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -78,7 +77,7 @@ fn check_object_short_function() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -95,10 +94,7 @@ fn check_object_short_function_arguments() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let parameters = FormalParameterList::from(FormalParameter::new( let parameters = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier( Variable::from_identifier(interner.get_or_intern("test").into(), None),
interner.get_or_intern_static("test", utf16!("test")).into(),
None,
),
false, false,
)); ));
@ -107,13 +103,13 @@ fn check_object_short_function_arguments() {
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Literal::from(true).into(), Literal::from(true).into(),
), ),
PropertyDefinition::MethodDefinition( PropertyDefinition::MethodDefinition(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
Some(interner.get_or_intern_static("b", utf16!("b")).into()), Some(interner.get_or_intern("b").into()),
parameters, parameters,
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -128,7 +124,7 @@ fn check_object_short_function_arguments() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -145,17 +141,13 @@ fn check_object_getter() {
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Literal::from(true).into(), Literal::from(true).into(),
), ),
PropertyDefinition::MethodDefinition( PropertyDefinition::MethodDefinition(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
MethodDefinition::Get(Function::new( MethodDefinition::Get(Function::new(
Some( Some(interner.get_or_intern("get b").into()),
interner
.get_or_intern_static("get b", utf16!("get b"))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -170,7 +162,7 @@ fn check_object_getter() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -186,10 +178,7 @@ fn check_object_setter() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier( Variable::from_identifier(interner.get_or_intern("test").into(), None),
interner.get_or_intern_static("test", utf16!("test")).into(),
None,
),
false, false,
)); ));
@ -198,17 +187,13 @@ fn check_object_setter() {
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Literal::from(true).into(), Literal::from(true).into(),
), ),
PropertyDefinition::MethodDefinition( PropertyDefinition::MethodDefinition(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
MethodDefinition::Set(Function::new( MethodDefinition::Set(Function::new(
Some( Some(interner.get_or_intern("set b").into()),
interner
.get_or_intern_static("set b", utf16!("set b"))
.into(),
),
params, params,
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -223,7 +208,7 @@ fn check_object_setter() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -241,7 +226,7 @@ fn check_object_short_function_get() {
let object_properties = vec![PropertyDefinition::MethodDefinition( let object_properties = vec![PropertyDefinition::MethodDefinition(
Sym::GET.into(), Sym::GET.into(),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
Some(interner.get_or_intern_static("get", utf16!("get")).into()), Some(interner.get_or_intern("get").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -254,7 +239,7 @@ fn check_object_short_function_get() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -272,7 +257,7 @@ fn check_object_short_function_set() {
let object_properties = vec![PropertyDefinition::MethodDefinition( let object_properties = vec![PropertyDefinition::MethodDefinition(
Sym::SET.into(), Sym::SET.into(),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
Some(interner.get_or_intern_static("set", utf16!("set")).into()), Some(interner.get_or_intern("set").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -285,7 +270,7 @@ fn check_object_short_function_set() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -301,7 +286,7 @@ fn check_object_shorthand_property_names() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![PropertyDefinition::IdentifierReference( let object_properties = vec![PropertyDefinition::IdentifierReference(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
)]; )];
check_script_parser( check_script_parser(
@ -311,7 +296,7 @@ fn check_object_shorthand_property_names() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Const( Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(true).into()), Some(Literal::from(true).into()),
)] )]
.try_into() .try_into()
@ -320,7 +305,7 @@ fn check_object_shorthand_property_names() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Const( Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -337,12 +322,8 @@ fn check_object_shorthand_multiple_properties() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::IdentifierReference( PropertyDefinition::IdentifierReference(interner.get_or_intern("a").into()),
interner.get_or_intern_static("a", utf16!("a")).into(), PropertyDefinition::IdentifierReference(interner.get_or_intern("b").into()),
),
PropertyDefinition::IdentifierReference(
interner.get_or_intern_static("b", utf16!("b")).into(),
),
]; ];
check_script_parser( check_script_parser(
@ -353,7 +334,7 @@ fn check_object_shorthand_multiple_properties() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Const( Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(true).into()), Some(Literal::from(true).into()),
)] )]
.try_into() .try_into()
@ -362,7 +343,7 @@ fn check_object_shorthand_multiple_properties() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Const( Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
Some(Literal::from(false).into()), Some(Literal::from(false).into()),
)] )]
.try_into() .try_into()
@ -371,7 +352,7 @@ fn check_object_shorthand_multiple_properties() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Const( Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -388,13 +369,8 @@ fn check_object_spread() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(interner.get_or_intern("a").into(), Literal::from(1).into()),
interner.get_or_intern_static("a", utf16!("a")).into(), PropertyDefinition::SpreadObject(Identifier::new(interner.get_or_intern("b")).into()),
Literal::from(1).into(),
),
PropertyDefinition::SpreadObject(
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(),
),
]; ];
check_script_parser( check_script_parser(
@ -402,7 +378,7 @@ fn check_object_spread() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -418,9 +394,9 @@ fn check_async_method() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![PropertyDefinition::MethodDefinition( let object_properties = vec![PropertyDefinition::MethodDefinition(
interner.get_or_intern_static("dive", utf16!("dive")).into(), interner.get_or_intern("dive").into(),
MethodDefinition::Async(AsyncFunction::new( MethodDefinition::Async(AsyncFunction::new(
Some(interner.get_or_intern_static("dive", utf16!("dive")).into()), Some(interner.get_or_intern("dive").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
false, false,
@ -434,7 +410,7 @@ fn check_async_method() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -450,15 +426,9 @@ fn check_async_generator_method() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![PropertyDefinition::MethodDefinition( let object_properties = vec![PropertyDefinition::MethodDefinition(
interner interner.get_or_intern("vroom").into(),
.get_or_intern_static("vroom", utf16!("vroom"))
.into(),
MethodDefinition::AsyncGenerator(AsyncGenerator::new( MethodDefinition::AsyncGenerator(AsyncGenerator::new(
Some( Some(interner.get_or_intern("vroom").into()),
interner
.get_or_intern_static("vroom", utf16!("vroom"))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
false, false,
@ -472,7 +442,7 @@ fn check_async_generator_method() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -510,13 +480,9 @@ fn check_async_ordinary_method() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![PropertyDefinition::MethodDefinition( let object_properties = vec![PropertyDefinition::MethodDefinition(
PropertyName::Literal(interner.get_or_intern_static("async", utf16!("async"))), PropertyName::Literal(interner.get_or_intern("async")),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
Some( Some(interner.get_or_intern("async").into()),
interner
.get_or_intern_static("async", utf16!("async"))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)), )),
@ -529,7 +495,7 @@ fn check_async_ordinary_method() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -545,7 +511,7 @@ fn check_async_property() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![PropertyDefinition::Property( let object_properties = vec![PropertyDefinition::Property(
PropertyName::Literal(interner.get_or_intern_static("async", utf16!("async"))), PropertyName::Literal(interner.get_or_intern("async")),
Literal::from(true).into(), Literal::from(true).into(),
)]; )];
@ -556,7 +522,7 @@ fn check_async_property() {
", ",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()

3
boa_parser/src/parser/expression/primary/tests.rs

@ -1,7 +1,6 @@
use crate::parser::tests::check_script_parser; use crate::parser::tests::check_script_parser;
use boa_ast::{expression::literal::Literal, Expression, Statement}; use boa_ast::{expression::literal::Literal, Expression, Statement};
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
#[test] #[test]
fn check_string() { fn check_string() {
@ -17,7 +16,7 @@ fn check_string() {
check_script_parser( check_script_parser(
"\"hello\"", "\"hello\"",
vec![Statement::Expression(Expression::from(Literal::from( vec![Statement::Expression(Expression::from(Literal::from(
interner.get_or_intern_static("hello", utf16!("hello")), interner.get_or_intern("hello"),
))) )))
.into()], .into()],
interner, interner,

213
boa_parser/src/parser/expression/tests.rs

@ -13,7 +13,6 @@ use boa_ast::{
Declaration, Expression, Statement, Declaration, Expression, Statement,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
/// Checks numeric operations /// Checks numeric operations
#[test] #[test]
@ -23,8 +22,8 @@ fn check_numeric_operations() {
"a + b", "a + b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -35,7 +34,7 @@ fn check_numeric_operations() {
"a+1", "a+1",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(1).into(), Literal::from(1).into(),
))) )))
.into()], .into()],
@ -47,8 +46,8 @@ fn check_numeric_operations() {
"a - b", "a - b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Sub.into(), ArithmeticOp::Sub.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -59,7 +58,7 @@ fn check_numeric_operations() {
"a-1", "a-1",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Sub.into(), ArithmeticOp::Sub.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(1).into(), Literal::from(1).into(),
))) )))
.into()], .into()],
@ -71,8 +70,8 @@ fn check_numeric_operations() {
"a / b", "a / b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -83,7 +82,7 @@ fn check_numeric_operations() {
"a/2", "a/2",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(2).into(), Literal::from(2).into(),
))) )))
.into()], .into()],
@ -95,16 +94,8 @@ fn check_numeric_operations() {
"let myRegex = /=/;", "let myRegex = /=/;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner interner.get_or_intern("myRegex").into(),
.get_or_intern_static("myRegex", utf16!("myRegex")) Some(RegExpLiteral::new(interner.get_or_intern("="), Sym::EMPTY_STRING).into()),
.into(),
Some(
RegExpLiteral::new(
interner.get_or_intern_static("=", utf16!("=")),
Sym::EMPTY_STRING,
)
.into(),
),
)] )]
.try_into() .try_into()
.unwrap(), .unwrap(),
@ -117,13 +108,8 @@ fn check_numeric_operations() {
check_script_parser( check_script_parser(
"fn(/=/);", "fn(/=/);",
vec![Statement::Expression(Expression::from(Call::new( vec![Statement::Expression(Expression::from(Call::new(
Identifier::new(interner.get_or_intern_static("fn", utf16!("fn"))).into(), Identifier::new(interner.get_or_intern("fn")).into(),
vec![RegExpLiteral::new( vec![RegExpLiteral::new(interner.get_or_intern("="), Sym::EMPTY_STRING).into()].into(),
interner.get_or_intern_static("=", utf16!("=")),
Sym::EMPTY_STRING,
)
.into()]
.into(),
))) )))
.into()], .into()],
interner, interner,
@ -133,11 +119,11 @@ fn check_numeric_operations() {
check_script_parser( check_script_parser(
"fn(a / b);", "fn(a / b);",
vec![Statement::Expression(Expression::from(Call::new( vec![Statement::Expression(Expression::from(Call::new(
Identifier::new(interner.get_or_intern_static("fn", utf16!("fn"))).into(), Identifier::new(interner.get_or_intern("fn")).into(),
vec![Expression::from(Binary::new( vec![Expression::from(Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))] ))]
.into(), .into(),
))) )))
@ -151,12 +137,11 @@ fn check_numeric_operations() {
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Call::new( Call::new(
Identifier::new(interner.get_or_intern_static("fn", utf16!("fn"))).into(), Identifier::new(interner.get_or_intern("fn")).into(),
vec![Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into()] vec![Identifier::new(interner.get_or_intern("a")).into()].into(),
.into(),
) )
.into(), .into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -167,8 +152,8 @@ fn check_numeric_operations() {
"a * b", "a * b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Mul.into(), ArithmeticOp::Mul.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -179,7 +164,7 @@ fn check_numeric_operations() {
"a*2", "a*2",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Mul.into(), ArithmeticOp::Mul.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(2).into(), Literal::from(2).into(),
))) )))
.into()], .into()],
@ -191,8 +176,8 @@ fn check_numeric_operations() {
"a ** b", "a ** b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Exp.into(), ArithmeticOp::Exp.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -203,7 +188,7 @@ fn check_numeric_operations() {
"a**2", "a**2",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Exp.into(), ArithmeticOp::Exp.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(2).into(), Literal::from(2).into(),
))) )))
.into()], .into()],
@ -215,8 +200,8 @@ fn check_numeric_operations() {
"a % b", "a % b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Mod.into(), ArithmeticOp::Mod.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -227,7 +212,7 @@ fn check_numeric_operations() {
"a%2", "a%2",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
ArithmeticOp::Mod.into(), ArithmeticOp::Mod.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(2).into(), Literal::from(2).into(),
))) )))
.into()], .into()],
@ -245,14 +230,14 @@ fn check_complex_numeric_operations() {
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Binary::new( Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Binary::new( Binary::new(
ArithmeticOp::Mul.into(), ArithmeticOp::Mul.into(),
Identifier::new(interner.get_or_intern_static("d", utf16!("d"))).into(), Identifier::new(interner.get_or_intern("d")).into(),
Parenthesized::new( Parenthesized::new(
Binary::new( Binary::new(
ArithmeticOp::Sub.into(), ArithmeticOp::Sub.into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
Literal::from(3).into(), Literal::from(3).into(),
) )
.into(), .into(),
@ -277,8 +262,8 @@ fn check_bitwise_operations() {
"a & b", "a & b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::And.into(), BitwiseOp::And.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -289,8 +274,8 @@ fn check_bitwise_operations() {
"a&b", "a&b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::And.into(), BitwiseOp::And.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -301,8 +286,8 @@ fn check_bitwise_operations() {
"a | b", "a | b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Or.into(), BitwiseOp::Or.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -313,8 +298,8 @@ fn check_bitwise_operations() {
"a|b", "a|b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Or.into(), BitwiseOp::Or.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -325,8 +310,8 @@ fn check_bitwise_operations() {
"a ^ b", "a ^ b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Xor.into(), BitwiseOp::Xor.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -337,8 +322,8 @@ fn check_bitwise_operations() {
"a^b", "a^b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Xor.into(), BitwiseOp::Xor.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -349,8 +334,8 @@ fn check_bitwise_operations() {
"a << b", "a << b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Shl.into(), BitwiseOp::Shl.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -361,8 +346,8 @@ fn check_bitwise_operations() {
"a<<b", "a<<b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Shl.into(), BitwiseOp::Shl.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -373,8 +358,8 @@ fn check_bitwise_operations() {
"a >> b", "a >> b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Shr.into(), BitwiseOp::Shr.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -385,8 +370,8 @@ fn check_bitwise_operations() {
"a>>b", "a>>b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
BitwiseOp::Shr.into(), BitwiseOp::Shr.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -401,8 +386,8 @@ fn check_assign_operations() {
"a += b", "a += b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Add, AssignOp::Add,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -413,8 +398,8 @@ fn check_assign_operations() {
"a -= b", "a -= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Sub, AssignOp::Sub,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -425,8 +410,8 @@ fn check_assign_operations() {
"a *= b", "a *= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Mul, AssignOp::Mul,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -437,8 +422,8 @@ fn check_assign_operations() {
"a **= b", "a **= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Exp, AssignOp::Exp,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -449,8 +434,8 @@ fn check_assign_operations() {
"a /= b", "a /= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Div, AssignOp::Div,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -461,8 +446,8 @@ fn check_assign_operations() {
"a %= b", "a %= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Mod, AssignOp::Mod,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -473,8 +458,8 @@ fn check_assign_operations() {
"a &= b", "a &= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::And, AssignOp::And,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -485,8 +470,8 @@ fn check_assign_operations() {
"a |= b", "a |= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Or, AssignOp::Or,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -497,8 +482,8 @@ fn check_assign_operations() {
"a ^= b", "a ^= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Xor, AssignOp::Xor,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -509,8 +494,8 @@ fn check_assign_operations() {
"a <<= b", "a <<= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Shl, AssignOp::Shl,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -521,8 +506,8 @@ fn check_assign_operations() {
"a >>= b", "a >>= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Shr, AssignOp::Shr,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -533,8 +518,8 @@ fn check_assign_operations() {
"a >>>= b", "a >>>= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Ushr, AssignOp::Ushr,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -545,7 +530,7 @@ fn check_assign_operations() {
"a %= 10 / 2", "a %= 10 / 2",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Mod, AssignOp::Mod,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Binary::new( Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Literal::from(10).into(), Literal::from(10).into(),
@ -562,8 +547,8 @@ fn check_assign_operations() {
"a ??= b", "a ??= b",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Coalesce, AssignOp::Coalesce,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -577,8 +562,8 @@ fn check_relational_operations() {
"a < b", "a < b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
RelationalOp::LessThan.into(), RelationalOp::LessThan.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -589,8 +574,8 @@ fn check_relational_operations() {
"a > b", "a > b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
RelationalOp::GreaterThan.into(), RelationalOp::GreaterThan.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -601,8 +586,8 @@ fn check_relational_operations() {
"a <= b", "a <= b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
RelationalOp::LessThanOrEqual.into(), RelationalOp::LessThanOrEqual.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -613,8 +598,8 @@ fn check_relational_operations() {
"a >= b", "a >= b",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
RelationalOp::GreaterThanOrEqual.into(), RelationalOp::GreaterThanOrEqual.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -625,8 +610,8 @@ fn check_relational_operations() {
"p in o", "p in o",
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
RelationalOp::In.into(), RelationalOp::In.into(),
Identifier::new(interner.get_or_intern_static("p", utf16!("p"))).into(), Identifier::new(interner.get_or_intern("p")).into(),
Identifier::new(interner.get_or_intern_static("o", utf16!("o"))).into(), Identifier::new(interner.get_or_intern("o")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -642,19 +627,19 @@ fn check_logical_expressions() {
LogicalOp::Or.into(), LogicalOp::Or.into(),
Binary::new( Binary::new(
LogicalOp::And.into(), LogicalOp::And.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
Binary::new( Binary::new(
LogicalOp::Or.into(), LogicalOp::Or.into(),
Binary::new( Binary::new(
LogicalOp::And.into(), LogicalOp::And.into(),
Identifier::new(interner.get_or_intern_static("c", utf16!("c"))).into(), Identifier::new(interner.get_or_intern("c")).into(),
Identifier::new(interner.get_or_intern_static("d", utf16!("d"))).into(), Identifier::new(interner.get_or_intern("d")).into(),
) )
.into(), .into(),
Identifier::new(interner.get_or_intern_static("e", utf16!("e"))).into(), Identifier::new(interner.get_or_intern("e")).into(),
) )
.into(), .into(),
))) )))
@ -669,11 +654,11 @@ fn check_logical_expressions() {
LogicalOp::Coalesce.into(), LogicalOp::Coalesce.into(),
Binary::new( Binary::new(
LogicalOp::Coalesce.into(), LogicalOp::Coalesce.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
Identifier::new(interner.get_or_intern_static("c", utf16!("c"))).into(), Identifier::new(interner.get_or_intern("c")).into(),
))) )))
.into()], .into()],
interner, interner,
@ -691,11 +676,7 @@ macro_rules! check_non_reserved_identifier {
check_script_parser( check_script_parser(
format!("({})", $keyword).as_str(), format!("({})", $keyword).as_str(),
vec![Statement::Expression( vec![Statement::Expression(
Parenthesized::new( Parenthesized::new(Identifier::new(interner.get_or_intern($keyword)).into()).into(),
Identifier::new(interner.get_or_intern_static($keyword, utf16!($keyword)))
.into(),
)
.into(),
) )
.into()], .into()],
interner, interner,

173
boa_parser/src/parser/function/tests.rs

@ -13,14 +13,13 @@ use boa_ast::{
Declaration, Expression, Statement, StatementListItem, Declaration, Expression, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks basic function declaration parsing. /// Checks basic function declaration parsing.
#[test] #[test]
fn check_basic() { fn check_basic() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -29,13 +28,11 @@ fn check_basic() {
check_script_parser( check_script_parser(
"function foo(a) { return a; }", "function foo(a) { return a; }",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(Identifier::from(interner.get_or_intern("a")).into())),
Identifier::from(interner.get_or_intern_static("a", utf16!("a"))).into(),
)),
))] ))]
.into(), .into(),
), ),
@ -51,11 +48,11 @@ fn check_duplicates_strict_off() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
]); ]);
@ -67,13 +64,11 @@ fn check_duplicates_strict_off() {
check_script_parser( check_script_parser(
"function foo(a, a) { return a; }", "function foo(a, a) { return a; }",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(Identifier::from(interner.get_or_intern("a")).into())),
Identifier::from(interner.get_or_intern_static("a", utf16!("a"))).into(),
)),
))] ))]
.into(), .into(),
), ),
@ -94,7 +89,7 @@ fn check_duplicates_strict_on() {
fn check_basic_semicolon_insertion() { fn check_basic_semicolon_insertion() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -103,13 +98,11 @@ fn check_basic_semicolon_insertion() {
check_script_parser( check_script_parser(
"function foo(a) { return a }", "function foo(a) { return a }",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(Identifier::from(interner.get_or_intern("a")).into())),
Identifier::from(interner.get_or_intern_static("a", utf16!("a"))).into(),
)),
))] ))]
.into(), .into(),
), ),
@ -124,7 +117,7 @@ fn check_basic_semicolon_insertion() {
fn check_empty_return() { fn check_empty_return() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -132,7 +125,7 @@ fn check_empty_return() {
check_script_parser( check_script_parser(
"function foo(a) { return; }", "function foo(a) { return; }",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
@ -151,7 +144,7 @@ fn check_empty_return() {
fn check_empty_return_semicolon_insertion() { fn check_empty_return_semicolon_insertion() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -159,7 +152,7 @@ fn check_empty_return_semicolon_insertion() {
check_script_parser( check_script_parser(
"function foo(a) { return }", "function foo(a) { return }",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
@ -179,11 +172,11 @@ fn check_rest_operator() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
true, true,
), ),
]); ]);
@ -195,7 +188,7 @@ fn check_rest_operator() {
check_script_parser( check_script_parser(
"function foo(a, ...b) {}", "function foo(a, ...b) {}",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::default(), FunctionBody::default(),
)) ))
@ -209,7 +202,7 @@ fn check_rest_operator() {
fn check_arrow_only_rest() { fn check_arrow_only_rest() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
true, true,
)); ));
assert_eq!( assert_eq!(
@ -235,15 +228,15 @@ fn check_arrow_rest() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("c", utf16!("c")).into(), None), Variable::from_identifier(interner.get_or_intern("c").into(), None),
true, true,
), ),
]); ]);
@ -270,11 +263,11 @@ fn check_arrow() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -290,8 +283,8 @@ fn check_arrow() {
Return::new(Some( Return::new(Some(
Binary::new( Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
)), )),
@ -310,11 +303,11 @@ fn check_arrow_semicolon_insertion() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -328,8 +321,8 @@ fn check_arrow_semicolon_insertion() {
Return::new(Some( Return::new(Some(
Binary::new( Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
)), )),
@ -348,11 +341,11 @@ fn check_arrow_epty_return() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -379,11 +372,11 @@ fn check_arrow_empty_return_semicolon_insertion() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -408,7 +401,7 @@ fn check_arrow_empty_return_semicolon_insertion() {
fn check_arrow_assignment() { fn check_arrow_assignment() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -417,18 +410,15 @@ fn check_arrow_assignment() {
"let foo = (a) => { return a };", "let foo = (a) => { return a };",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -449,7 +439,7 @@ fn check_arrow_assignment() {
fn check_arrow_assignment_nobrackets() { fn check_arrow_assignment_nobrackets() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -458,18 +448,15 @@ fn check_arrow_assignment_nobrackets() {
"let foo = (a) => a;", "let foo = (a) => a;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("foo", utf16!("foo")).into(), interner.get_or_intern("foo").into(),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -490,7 +477,7 @@ fn check_arrow_assignment_nobrackets() {
fn check_arrow_assignment_noparenthesis() { fn check_arrow_assignment_noparenthesis() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -499,18 +486,15 @@ fn check_arrow_assignment_noparenthesis() {
"let foo = a => { return a };", "let foo = a => { return a };",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("foo", utf16!("foo")).into(), interner.get_or_intern("foo").into(),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -531,7 +515,7 @@ fn check_arrow_assignment_noparenthesis() {
fn check_arrow_assignment_noparenthesis_nobrackets() { fn check_arrow_assignment_noparenthesis_nobrackets() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
)); ));
assert_eq!(params.flags(), FormalParameterListFlags::default()); assert_eq!(params.flags(), FormalParameterListFlags::default());
@ -540,18 +524,15 @@ fn check_arrow_assignment_noparenthesis_nobrackets() {
"let foo = a => a;", "let foo = a => a;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -573,11 +554,11 @@ fn check_arrow_assignment_2arg() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -587,18 +568,15 @@ fn check_arrow_assignment_2arg() {
"let foo = (a, b) => { return a };", "let foo = (a, b) => { return a };",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -620,11 +598,11 @@ fn check_arrow_assignment_2arg_nobrackets() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
]); ]);
@ -634,18 +612,15 @@ fn check_arrow_assignment_2arg_nobrackets() {
"let foo = (a, b) => a;", "let foo = (a, b) => a;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -667,15 +642,15 @@ fn check_arrow_assignment_3arg() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("c", utf16!("c")).into(), None), Variable::from_identifier(interner.get_or_intern("c").into(), None),
false, false,
), ),
]); ]);
@ -685,18 +660,15 @@ fn check_arrow_assignment_3arg() {
"let foo = (a, b, c) => { return a };", "let foo = (a, b, c) => { return a };",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),
@ -718,15 +690,15 @@ fn check_arrow_assignment_3arg_nobrackets() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let params = FormalParameterList::from(vec![ let params = FormalParameterList::from(vec![
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("a", utf16!("a")).into(), None), Variable::from_identifier(interner.get_or_intern("a").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("b", utf16!("b")).into(), None), Variable::from_identifier(interner.get_or_intern("b").into(), None),
false, false,
), ),
FormalParameter::new( FormalParameter::new(
Variable::from_identifier(interner.get_or_intern_static("c", utf16!("c")).into(), None), Variable::from_identifier(interner.get_or_intern("c").into(), None),
false, false,
), ),
]); ]);
@ -736,18 +708,15 @@ fn check_arrow_assignment_3arg_nobrackets() {
"let foo = (a, b, c) => a;", "let foo = (a, b, c) => a;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
Identifier::new(interner.get_or_intern_static("foo", utf16!("foo"))), Identifier::new(interner.get_or_intern("foo")),
Some( Some(
ArrowFunction::new( ArrowFunction::new(
Some(interner.get_or_intern_static("foo", utf16!("foo")).into()), Some(interner.get_or_intern("foo").into()),
params, params,
FunctionBody::new( FunctionBody::new(
vec![StatementListItem::Statement(Statement::Return( vec![StatementListItem::Statement(Statement::Return(
Return::new(Some( Return::new(Some(
Identifier::new( Identifier::new(interner.get_or_intern("a")).into(),
interner.get_or_intern_static("a", utf16!("a")),
)
.into(),
)), )),
))] ))]
.into(), .into(),

13
boa_parser/src/parser/statement/block/tests.rs

@ -17,7 +17,6 @@ use boa_ast::{
Declaration, Expression, Statement, StatementListItem, Declaration, Expression, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Helper function to check a block. /// Helper function to check a block.
#[track_caller] #[track_caller]
@ -40,7 +39,7 @@ fn empty() {
#[test] #[test]
fn non_empty() { fn non_empty() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_block( check_block(
r"{ r"{
var a = 10; var a = 10;
@ -66,8 +65,8 @@ fn non_empty() {
); );
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let hello = interner.get_or_intern_static("hello", utf16!("hello")); let hello = interner.get_or_intern("hello");
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_block( check_block(
r"{ r"{
function hello() { function hello() {
@ -111,8 +110,8 @@ fn non_empty() {
#[test] #[test]
fn hoisting() { fn hoisting() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let hello = interner.get_or_intern_static("hello", utf16!("hello")); let hello = interner.get_or_intern("hello");
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_block( check_block(
r"{ r"{
var a = hello(); var a = hello();
@ -151,7 +150,7 @@ fn hoisting() {
); );
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_block( check_block(
r"{ r"{
a = 10; a = 10;

9
boa_parser/src/parser/statement/break_stm/tests.rs

@ -5,7 +5,6 @@ use boa_ast::{
Statement, StatementListItem, Statement, StatementListItem,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
#[test] #[test]
fn inline() { fn inline() {
@ -61,11 +60,11 @@ fn new_line_semicolon_insertion() {
LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new( LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new(
Literal::from(true).into(), Literal::from(true).into(),
Block::from(vec![StatementListItem::Statement(Statement::Break( Block::from(vec![StatementListItem::Statement(Statement::Break(
Break::new(Some(interner.get_or_intern_static("test", utf16!("test")))), Break::new(Some(interner.get_or_intern("test"))),
))]) ))])
.into(), .into(),
))), ))),
interner.get_or_intern_static("test", utf16!("test")), interner.get_or_intern("test"),
)) ))
.into()], .into()],
interner, interner,
@ -99,11 +98,11 @@ fn new_line_block() {
LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new( LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new(
Literal::from(true).into(), Literal::from(true).into(),
Block::from(vec![StatementListItem::Statement(Statement::Break( Block::from(vec![StatementListItem::Statement(Statement::Break(
Break::new(Some(interner.get_or_intern_static("test", utf16!("test")))), Break::new(Some(interner.get_or_intern("test"))),
))]) ))])
.into(), .into(),
))), ))),
interner.get_or_intern_static("test", utf16!("test")), interner.get_or_intern("test"),
)) ))
.into()], .into()],
interner, interner,

9
boa_parser/src/parser/statement/continue_stm/tests.rs

@ -5,7 +5,6 @@ use boa_ast::{
Statement, StatementListItem, Statement, StatementListItem,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
#[test] #[test]
fn inline() { fn inline() {
@ -61,11 +60,11 @@ fn new_line_semicolon_insertion() {
LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new( LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new(
Literal::from(true).into(), Literal::from(true).into(),
Block::from(vec![StatementListItem::Statement(Statement::Continue( Block::from(vec![StatementListItem::Statement(Statement::Continue(
Continue::new(Some(interner.get_or_intern_static("test", utf16!("test")))), Continue::new(Some(interner.get_or_intern("test"))),
))]) ))])
.into(), .into(),
))), ))),
interner.get_or_intern_static("test", utf16!("test")), interner.get_or_intern("test"),
)) ))
.into()], .into()],
interner, interner,
@ -99,11 +98,11 @@ fn new_line_block() {
LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new( LabelledItem::Statement(Statement::WhileLoop(WhileLoop::new(
Literal::from(true).into(), Literal::from(true).into(),
Block::from(vec![StatementListItem::Statement(Statement::Continue( Block::from(vec![StatementListItem::Statement(Statement::Continue(
Continue::new(Some(interner.get_or_intern_static("test", utf16!("test")))), Continue::new(Some(interner.get_or_intern("test"))),
))]) ))])
.into(), .into(),
))), ))),
interner.get_or_intern_static("test", utf16!("test")), interner.get_or_intern("test"),
)) ))
.into()], .into()],
interner, interner,

2
boa_parser/src/parser/statement/declaration/export.rs

@ -307,7 +307,7 @@ where
match tok.kind() { match tok.kind() {
TokenKind::StringLiteral((ident, _)) => { TokenKind::StringLiteral((ident, _)) => {
if interner.resolve_expect(*ident).utf8().is_none() { if !interner.resolve_expect(*ident).as_str().is_ascii() {
return Err(Error::general( return Err(Error::general(
"import specifiers don't allow unpaired surrogates", "import specifiers don't allow unpaired surrogates",
tok.span().end(), tok.span().end(),

7
boa_parser/src/parser/statement/declaration/hoistable/async_function_decl/tests.rs

@ -4,7 +4,6 @@ use boa_ast::{
Declaration, Declaration,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
/// Async function declaration parsing. /// Async function declaration parsing.
#[test] #[test]
@ -13,11 +12,7 @@ fn async_function_declaration() {
check_script_parser( check_script_parser(
"async function hello() {}", "async function hello() {}",
vec![Declaration::AsyncFunction(AsyncFunction::new( vec![Declaration::AsyncFunction(AsyncFunction::new(
Some( Some(interner.get_or_intern("hello").into()),
interner
.get_or_intern_static("hello", utf16!("hello"))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
false, false,

3
boa_parser/src/parser/statement/declaration/hoistable/async_generator_decl/tests.rs

@ -4,7 +4,6 @@ use boa_ast::{
Declaration, Declaration,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn async_generator_function_declaration() { fn async_generator_function_declaration() {
@ -12,7 +11,7 @@ fn async_generator_function_declaration() {
check_script_parser( check_script_parser(
"async function* gen() {}", "async function* gen() {}",
vec![Declaration::AsyncGenerator(AsyncGenerator::new( vec![Declaration::AsyncGenerator(AsyncGenerator::new(
Some(interner.get_or_intern_static("gen", utf16!("gen")).into()), Some(interner.get_or_intern("gen").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
false, false,

10
boa_parser/src/parser/statement/declaration/hoistable/class_decl/mod.rs

@ -28,8 +28,7 @@ use boa_ast::{
property::{ClassElementName, MethodDefinition}, property::{ClassElementName, MethodDefinition},
Expression, Keyword, Punctuator, Expression, Keyword, Punctuator,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{js_string, Interner, Sym};
use boa_macros::utf16;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use std::io::Read; use std::io::Read;
@ -1162,11 +1161,8 @@ where
} }
TokenKind::PrivateIdentifier(name) => { TokenKind::PrivateIdentifier(name) => {
let name = *name; let name = *name;
let name_private = interner.get_or_intern( let name_private = interner
[utf16!("#"), interner.resolve_expect(name).utf16()] .get_or_intern(js_string!("#", &*interner.resolve_expect(name)).as_str());
.concat()
.as_slice(),
);
cursor.advance(interner); cursor.advance(interner);
let token = cursor.peek(0, interner).or_abrupt()?; let token = cursor.peek(0, interner).or_abrupt()?;
match token.kind() { match token.kind() {

31
boa_parser/src/parser/statement/declaration/hoistable/class_decl/tests.rs

@ -11,14 +11,13 @@ use boa_ast::{
Declaration, Expression, Statement, StatementList, StatementListItem, Declaration, Expression, Statement, StatementList, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn check_async_ordinary_method() { fn check_async_ordinary_method() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let elements = vec![ClassElement::MethodDefinition( let elements = vec![ClassElement::MethodDefinition(
PropertyName::Literal(interner.get_or_intern_static("async", utf16!("async"))), PropertyName::Literal(interner.get_or_intern("async")),
MethodDefinition::Ordinary(Function::new( MethodDefinition::Ordinary(Function::new(
None, None,
FormalParameterList::default(), FormalParameterList::default(),
@ -32,7 +31,7 @@ fn check_async_ordinary_method() {
} }
", ",
[Declaration::Class(Class::new( [Declaration::Class(Class::new(
Some(interner.get_or_intern_static("A", utf16!("A")).into()), Some(interner.get_or_intern("A").into()),
None, None,
None, None,
elements.into(), elements.into(),
@ -48,7 +47,7 @@ fn check_async_field_initialization() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let elements = vec![ClassElement::FieldDefinition( let elements = vec![ClassElement::FieldDefinition(
PropertyName::Literal(interner.get_or_intern_static("async", utf16!("async"))), PropertyName::Literal(interner.get_or_intern("async")),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)]; )];
@ -59,7 +58,7 @@ fn check_async_field_initialization() {
} }
", ",
[Declaration::Class(Class::new( [Declaration::Class(Class::new(
Some(interner.get_or_intern_static("A", utf16!("A")).into()), Some(interner.get_or_intern("A").into()),
None, None,
None, None,
elements.into(), elements.into(),
@ -75,7 +74,7 @@ fn check_async_field() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let elements = vec![ClassElement::FieldDefinition( let elements = vec![ClassElement::FieldDefinition(
PropertyName::Literal(interner.get_or_intern_static("async", utf16!("async"))), PropertyName::Literal(interner.get_or_intern("async")),
None, None,
)]; )];
@ -85,7 +84,7 @@ fn check_async_field() {
} }
", ",
[Declaration::Class(Class::new( [Declaration::Class(Class::new(
Some(interner.get_or_intern_static("A", utf16!("A")).into()), Some(interner.get_or_intern("A").into()),
None, None,
None, None,
elements.into(), elements.into(),
@ -101,24 +100,20 @@ fn check_new_target_with_property_access() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let new_target = Expression::PropertyAccess( let new_target = Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(Expression::NewTarget, interner.get_or_intern("name")).into(),
Expression::NewTarget,
interner.get_or_intern_static("name", utf16!("name")),
)
.into(),
); );
let console = Expression::Call(Call::new( let console = Expression::Call(Call::new(
PropertyAccess::Simple(SimplePropertyAccess::new( PropertyAccess::Simple(SimplePropertyAccess::new(
Identifier::from(interner.get_or_intern_static("console", utf16!("console"))).into(), Identifier::from(interner.get_or_intern("console")).into(),
interner.get_or_intern_static("log", utf16!("log")), interner.get_or_intern("log"),
)) ))
.into(), .into(),
[new_target].into(), [new_target].into(),
)); ));
let constructor = Function::new( let constructor = Function::new(
Some(interner.get_or_intern_static("A", utf16!("A")).into()), Some(interner.get_or_intern("A").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::new(StatementList::new( FunctionBody::new(StatementList::new(
[Statement::Expression(console).into()], [Statement::Expression(console).into()],
@ -127,7 +122,7 @@ fn check_new_target_with_property_access() {
); );
let class = Class::new( let class = Class::new(
Some(interner.get("A").unwrap().into()), Some(interner.get_or_intern("A").into()),
None, None,
Some(constructor), Some(constructor),
Box::default(), Box::default(),
@ -136,7 +131,7 @@ fn check_new_target_with_property_access() {
let instantiation = Expression::New( let instantiation = Expression::New(
Call::new( Call::new(
Identifier::from(interner.get("A").unwrap()).into(), Identifier::from(interner.get_or_intern("A")).into(),
Box::default(), Box::default(),
) )
.into(), .into(),
@ -145,7 +140,7 @@ fn check_new_target_with_property_access() {
let const_decl = LexicalDeclaration::Const( let const_decl = LexicalDeclaration::Const(
VariableList::new( VariableList::new(
[Variable::from_identifier( [Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(instantiation), Some(instantiation),
)] )]
.into(), .into(),

13
boa_parser/src/parser/statement/declaration/hoistable/function_decl/tests.rs

@ -4,7 +4,6 @@ use boa_ast::{
Declaration, Declaration,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Function declaration parsing. /// Function declaration parsing.
#[test] #[test]
@ -13,11 +12,7 @@ fn function_declaration() {
check_script_parser( check_script_parser(
"function hello() {}", "function hello() {}",
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some( Some(interner.get_or_intern("hello").into()),
interner
.get_or_intern_static("hello", utf16!("hello"))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)) ))
@ -32,11 +27,7 @@ fn function_declaration_keywords() {
macro_rules! genast { macro_rules! genast {
($keyword:literal, $interner:expr) => { ($keyword:literal, $interner:expr) => {
vec![Declaration::Function(Function::new( vec![Declaration::Function(Function::new(
Some( Some($interner.get_or_intern($keyword).into()),
$interner
.get_or_intern_static($keyword, utf16!($keyword))
.into(),
),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
)) ))

3
boa_parser/src/parser/statement/declaration/hoistable/generator_decl/tests.rs

@ -4,7 +4,6 @@ use boa_ast::{
Declaration, Declaration,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn generator_function_declaration() { fn generator_function_declaration() {
@ -12,7 +11,7 @@ fn generator_function_declaration() {
check_script_parser( check_script_parser(
"function* gen() {}", "function* gen() {}",
vec![Declaration::Generator(Generator::new( vec![Declaration::Generator(Generator::new(
Some(interner.get_or_intern_static("gen", utf16!("gen")).into()), Some(interner.get_or_intern("gen").into()),
FormalParameterList::default(), FormalParameterList::default(),
FunctionBody::default(), FunctionBody::default(),
false, false,

2
boa_parser/src/parser/statement/declaration/import.rs

@ -298,7 +298,7 @@ where
match tok.kind() { match tok.kind() {
TokenKind::StringLiteral((name, _)) => { TokenKind::StringLiteral((name, _)) => {
let name = *name; let name = *name;
if interner.resolve_expect(name).utf8().is_none() { if !interner.resolve_expect(name).as_str().is_ascii() {
return Err(Error::general( return Err(Error::general(
"import specifiers don't allow unpaired surrogates", "import specifiers don't allow unpaired surrogates",
tok.span().end(), tok.span().end(),

39
boa_parser/src/parser/statement/declaration/tests.rs

@ -5,7 +5,6 @@ use boa_ast::{
Declaration, Statement, Declaration, Statement,
}; };
use boa_interner::{Interner, Sym}; use boa_interner::{Interner, Sym};
use boa_macros::utf16;
/// Checks `var` declaration parsing. /// Checks `var` declaration parsing.
#[test] #[test]
@ -15,7 +14,7 @@ fn var_declaration() {
"var a = 5;", "var a = 5;",
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -68,7 +67,7 @@ fn var_declaration_no_spaces() {
"var a=5;", "var a=5;",
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -87,7 +86,7 @@ fn empty_var_declaration() {
"var a;", "var a;",
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
None, None,
)] )]
.try_into() .try_into()
@ -107,15 +106,12 @@ fn multiple_var_declaration() {
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![ vec![
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
), ),
Variable::from_identifier(interner.get_or_intern("b").into(), None),
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("c").into(),
None,
),
Variable::from_identifier(
interner.get_or_intern_static("c", utf16!("c")).into(),
Some(Literal::from(6).into()), Some(Literal::from(6).into()),
), ),
] ]
@ -135,7 +131,7 @@ fn let_declaration() {
"let a = 5;", "let a = 5;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -188,7 +184,7 @@ fn let_declaration_no_spaces() {
"let a=5;", "let a=5;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -207,7 +203,7 @@ fn empty_let_declaration() {
"let a;", "let a;",
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
None, None,
)] )]
.try_into() .try_into()
@ -227,15 +223,12 @@ fn multiple_let_declaration() {
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![ vec![
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
), ),
Variable::from_identifier(interner.get_or_intern("b").into(), None),
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("c").into(),
None,
),
Variable::from_identifier(
interner.get_or_intern_static("c", utf16!("c")).into(),
Some(Literal::from(6).into()), Some(Literal::from(6).into()),
), ),
] ]
@ -255,7 +248,7 @@ fn const_declaration() {
"const a = 5;", "const a = 5;",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -308,7 +301,7 @@ fn const_declaration_no_spaces() {
"const a=5;", "const a=5;",
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
)] )]
.try_into() .try_into()
@ -334,11 +327,11 @@ fn multiple_const_declaration() {
vec![Declaration::Lexical(LexicalDeclaration::Const( vec![Declaration::Lexical(LexicalDeclaration::Const(
vec![ vec![
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::from(5).into()), Some(Literal::from(5).into()),
), ),
Variable::from_identifier( Variable::from_identifier(
interner.get_or_intern_static("c", utf16!("c")).into(), interner.get_or_intern("c").into(),
Some(Literal::from(6).into()), Some(Literal::from(6).into()),
), ),
] ]

61
boa_parser/src/parser/statement/iteration/tests.rs

@ -16,7 +16,6 @@ use boa_ast::{
Expression, Statement, StatementListItem, Expression, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks do-while statement parsing. /// Checks do-while statement parsing.
#[test] #[test]
@ -31,7 +30,7 @@ fn check_do_while() {
vec![StatementListItem::Statement(Statement::Expression( vec![StatementListItem::Statement(Statement::Expression(
Expression::from(Assign::new( Expression::from(Assign::new(
AssignOp::Add, AssignOp::Add,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(1).into(), Literal::from(1).into(),
)), )),
))] ))]
@ -54,7 +53,7 @@ fn check_do_while_semicolon_insertion() {
vec![ vec![
Statement::Var(VarDeclaration( Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("i", utf16!("i")).into(), interner.get_or_intern("i").into(),
Some(Literal::from(0).into()), Some(Literal::from(0).into()),
)] )]
.try_into() .try_into()
@ -67,19 +66,12 @@ fn check_do_while_semicolon_insertion() {
Expression::from(Call::new( Expression::from(Call::new(
Expression::PropertyAccess( Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Identifier::new( Identifier::new(interner.get_or_intern("console")).into(),
interner.get_or_intern_static("console", utf16!("console")), interner.get_or_intern("log"),
)
.into(),
interner.get_or_intern_static("log", utf16!("log")),
) )
.into(), .into(),
), ),
vec![Literal::from( vec![Literal::from(interner.get_or_intern("hello")).into()].into(),
interner.get_or_intern_static("hello", utf16!("hello")),
)
.into()]
.into(),
)), )),
))] ))]
.into(), .into(),
@ -88,9 +80,7 @@ fn check_do_while_semicolon_insertion() {
RelationalOp::LessThan.into(), RelationalOp::LessThan.into(),
Update::new( Update::new(
UpdateOp::IncrementPost, UpdateOp::IncrementPost,
UpdateTarget::Identifier(Identifier::new( UpdateTarget::Identifier(Identifier::new(interner.get_or_intern("i"))),
interner.get_or_intern_static("i", utf16!("i")),
)),
) )
.into(), .into(),
Literal::from(10).into(), Literal::from(10).into(),
@ -101,16 +91,12 @@ fn check_do_while_semicolon_insertion() {
Statement::Expression(Expression::from(Call::new( Statement::Expression(Expression::from(Call::new(
Expression::PropertyAccess( Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Identifier::new( Identifier::new(interner.get_or_intern("console")).into(),
interner.get_or_intern_static("console", utf16!("console")), interner.get_or_intern("log"),
)
.into(),
interner.get_or_intern_static("log", utf16!("log")),
) )
.into(), .into(),
), ),
vec![Literal::from(interner.get_or_intern_static("end", utf16!("end"))).into()] vec![Literal::from(interner.get_or_intern("end")).into()].into(),
.into(),
))) )))
.into(), .into(),
], ],
@ -129,7 +115,7 @@ fn check_do_while_semicolon_insertion_no_space() {
vec![ vec![
Statement::Var(VarDeclaration( Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("i", utf16!("i")).into(), interner.get_or_intern("i").into(),
Some(Literal::from(0).into()), Some(Literal::from(0).into()),
)] )]
.try_into() .try_into()
@ -142,19 +128,12 @@ fn check_do_while_semicolon_insertion_no_space() {
Expression::from(Call::new( Expression::from(Call::new(
Expression::PropertyAccess( Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Identifier::new( Identifier::new(interner.get_or_intern("console")).into(),
interner.get_or_intern_static("console", utf16!("console")), interner.get_or_intern("log"),
)
.into(),
interner.get_or_intern_static("log", utf16!("log")),
) )
.into(), .into(),
), ),
vec![Literal::from( vec![Literal::from(interner.get_or_intern("hello")).into()].into(),
interner.get_or_intern_static("hello", utf16!("hello")),
)
.into()]
.into(),
)), )),
))] ))]
.into(), .into(),
@ -163,9 +142,7 @@ fn check_do_while_semicolon_insertion_no_space() {
RelationalOp::LessThan.into(), RelationalOp::LessThan.into(),
Update::new( Update::new(
UpdateOp::IncrementPost, UpdateOp::IncrementPost,
UpdateTarget::Identifier(Identifier::new( UpdateTarget::Identifier(Identifier::new(interner.get_or_intern("i"))),
interner.get_or_intern_static("i", utf16!("i")),
)),
) )
.into(), .into(),
Literal::from(10).into(), Literal::from(10).into(),
@ -176,16 +153,12 @@ fn check_do_while_semicolon_insertion_no_space() {
Statement::Expression(Expression::from(Call::new( Statement::Expression(Expression::from(Call::new(
Expression::PropertyAccess( Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
Identifier::new( Identifier::new(interner.get_or_intern("console")).into(),
interner.get_or_intern_static("console", utf16!("console")), interner.get_or_intern("log"),
)
.into(),
interner.get_or_intern_static("log", utf16!("log")),
) )
.into(), .into(),
), ),
vec![Literal::from(interner.get_or_intern_static("end", utf16!("end"))).into()] vec![Literal::from(interner.get_or_intern("end")).into()].into(),
.into(),
))) )))
.into(), .into(),
], ],

10
boa_parser/src/parser/statement/mod.rs

@ -56,7 +56,6 @@ use boa_ast::{
Keyword, Punctuator, Keyword, Punctuator,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
use boa_profiler::Profiler; use boa_profiler::Profiler;
use std::io::Read; use std::io::Read;
@ -317,12 +316,9 @@ where
ast::StatementListItem::Statement(ast::Statement::Expression( ast::StatementListItem::Statement(ast::Statement::Expression(
ast::Expression::Literal(ast::expression::literal::Literal::String(string)), ast::Expression::Literal(ast::expression::literal::Literal::String(string)),
)) if !strict => { )) if !strict => {
if interner.resolve_expect(*string).join( if &*interner.resolve_expect(*string) == "use strict"
|s| s == "use strict", && directives_stack.last().expect("token should exist").1
|g| g == utf16!("use strict"), == EscapeSequence::empty()
true,
) && directives_stack.last().expect("token should exist").1
== EscapeSequence::empty()
{ {
cursor.set_strict(true); cursor.set_strict(true);
strict = true; strict = true;

13
boa_parser/src/parser/statement/switch/tests.rs

@ -6,7 +6,6 @@ use boa_ast::{
Declaration, Expression, Statement, Declaration, Expression, Statement,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks parsing malformed switch with no closeblock. /// Checks parsing malformed switch with no closeblock.
#[test] #[test]
@ -148,9 +147,9 @@ fn check_separated_switch() {
"#; "#;
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let log = interner.get_or_intern_static("log", utf16!("log")); let log = interner.get_or_intern("log");
let console = interner.get_or_intern_static("console", utf16!("console")); let console = interner.get_or_intern("console");
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
s, s,
@ -203,11 +202,7 @@ fn check_separated_switch() {
SimplePropertyAccess::new(Identifier::new(console).into(), log) SimplePropertyAccess::new(Identifier::new(console).into(), log)
.into(), .into(),
), ),
vec![Literal::from( vec![Literal::from(interner.get_or_intern("Default")).into()].into(),
interner.get_or_intern_static("Default", utf16!("Default")),
)
.into()]
.into(),
))) )))
.into()] .into()]
.into(), .into(),

3
boa_parser/src/parser/statement/throw/tests.rs

@ -1,7 +1,6 @@
use crate::parser::tests::check_script_parser; use crate::parser::tests::check_script_parser;
use boa_ast::{expression::literal::Literal, statement::Throw, Statement}; use boa_ast::{expression::literal::Literal, statement::Throw, Statement};
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn check_throw_parsing() { fn check_throw_parsing() {
@ -9,7 +8,7 @@ fn check_throw_parsing() {
check_script_parser( check_script_parser(
"throw 'error';", "throw 'error';",
vec![Statement::Throw(Throw::new( vec![Statement::Throw(Throw::new(
Literal::from(interner.get_or_intern_static("error", utf16!("error"))).into(), Literal::from(interner.get_or_intern("error")).into(),
)) ))
.into()], .into()],
interner, interner,

39
boa_parser/src/parser/statement/try_stm/tests.rs

@ -8,7 +8,6 @@ use boa_ast::{
Statement, StatementListItem, Statement, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
#[test] #[test]
fn check_inline_with_empty_try_catch() { fn check_inline_with_empty_try_catch() {
@ -18,7 +17,7 @@ fn check_inline_with_empty_try_catch() {
vec![Statement::Try(Try::new( vec![Statement::Try(Try::new(
Block::default(), Block::default(),
ErrorHandler::Catch(Catch::new( ErrorHandler::Catch(Catch::new(
Some(Identifier::from(interner.get_or_intern_static("e", utf16!("e"))).into()), Some(Identifier::from(interner.get_or_intern("e")).into()),
Block::default(), Block::default(),
)), )),
)) ))
@ -35,7 +34,7 @@ fn check_inline_with_var_decl_inside_try() {
vec![Statement::Try(Try::new( vec![Statement::Try(Try::new(
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)] )]
.try_into() .try_into()
@ -44,7 +43,7 @@ fn check_inline_with_var_decl_inside_try() {
.into()] .into()]
.into(), .into(),
ErrorHandler::Catch(Catch::new( ErrorHandler::Catch(Catch::new(
Some(Identifier::from(interner.get_or_intern_static("e", utf16!("e"))).into()), Some(Identifier::from(interner.get_or_intern("e")).into()),
Block::default(), Block::default(),
)), )),
)) ))
@ -61,7 +60,7 @@ fn check_inline_with_var_decl_inside_catch() {
vec![Statement::Try(Try::new( vec![Statement::Try(Try::new(
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)] )]
.try_into() .try_into()
@ -70,10 +69,10 @@ fn check_inline_with_var_decl_inside_catch() {
.into()] .into()]
.into(), .into(),
ErrorHandler::Catch(Catch::new( ErrorHandler::Catch(Catch::new(
Some(Identifier::from(interner.get_or_intern_static("e", utf16!("e"))).into()), Some(Identifier::from(interner.get_or_intern("e")).into()),
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)] )]
.try_into() .try_into()
@ -97,7 +96,7 @@ fn check_inline_with_empty_try_catch_finally() {
Block::default(), Block::default(),
ErrorHandler::Full( ErrorHandler::Full(
Catch::new( Catch::new(
Some(Identifier::from(interner.get_or_intern_static("e", utf16!("e"))).into()), Some(Identifier::from(interner.get_or_intern("e")).into()),
Block::default(), Block::default(),
), ),
Finally::from(Block::default()), Finally::from(Block::default()),
@ -131,7 +130,7 @@ fn check_inline_with_empty_try_var_decl_in_finally() {
ErrorHandler::Finally(Finally::from(Block::from(vec![ ErrorHandler::Finally(Finally::from(Block::from(vec![
StatementListItem::Statement(Statement::Var(VarDeclaration( StatementListItem::Statement(Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)] )]
.try_into() .try_into()
@ -155,7 +154,7 @@ fn check_inline_empty_try_paramless_catch() {
None, None,
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(Literal::from(1).into()), Some(Literal::from(1).into()),
)] )]
.try_into() .try_into()
@ -173,7 +172,7 @@ fn check_inline_empty_try_paramless_catch() {
#[test] #[test]
fn check_inline_with_binding_pattern_object() { fn check_inline_with_binding_pattern_object() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
"try {} catch ({ a, b: c }) {}", "try {} catch ({ a, b: c }) {}",
vec![Statement::Try(Try::new( vec![Statement::Try(Try::new(
@ -187,10 +186,8 @@ fn check_inline_with_binding_pattern_object() {
default_init: None, default_init: None,
}, },
ObjectPatternElement::SingleName { ObjectPatternElement::SingleName {
ident: interner.get_or_intern_static("c", utf16!("c")).into(), ident: interner.get_or_intern("c").into(),
name: PropertyName::Literal( name: PropertyName::Literal(interner.get_or_intern("b")),
interner.get_or_intern_static("b", utf16!("b")),
),
default_init: None, default_init: None,
}, },
]) ])
@ -215,11 +212,11 @@ fn check_inline_with_binding_pattern_array() {
Some( Some(
Pattern::from(vec![ Pattern::from(vec![
ArrayPatternElement::SingleName { ArrayPatternElement::SingleName {
ident: interner.get_or_intern_static("a", utf16!("a")).into(), ident: interner.get_or_intern("a").into(),
default_init: None, default_init: None,
}, },
ArrayPatternElement::SingleName { ArrayPatternElement::SingleName {
ident: interner.get_or_intern_static("b", utf16!("b")).into(), ident: interner.get_or_intern("b").into(),
default_init: None, default_init: None,
}, },
]) ])
@ -241,13 +238,11 @@ fn check_catch_with_var_redeclaration() {
vec![Statement::Try(Try::new( vec![Statement::Try(Try::new(
Block::from(vec![]), Block::from(vec![]),
ErrorHandler::Catch(Catch::new( ErrorHandler::Catch(Catch::new(
Some(Identifier::new(interner.get_or_intern_static("e", utf16!("e"))).into()), Some(Identifier::new(interner.get_or_intern("e")).into()),
vec![Statement::Var(VarDeclaration( vec![Statement::Var(VarDeclaration(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("e", utf16!("e")).into(), interner.get_or_intern("e").into(),
Some( Some(Literal::from(interner.get_or_intern("oh")).into()),
Literal::from(interner.get_or_intern_static("oh", utf16!("oh"))).into(),
),
)] )]
.try_into() .try_into()
.unwrap(), .unwrap(),

72
boa_parser/src/parser/tests/mod.rs

@ -27,7 +27,6 @@ use boa_ast::{
Expression, Script, Statement, StatementList, StatementListItem, Expression, Script, Statement, StatementList, StatementListItem,
}; };
use boa_interner::Interner; use boa_interner::Interner;
use boa_macros::utf16;
/// Checks that the given JavaScript string gives the expected expression. /// Checks that the given JavaScript string gives the expected expression.
#[track_caller] #[track_caller]
@ -61,12 +60,11 @@ fn check_construct_call_precedence() {
Expression::PropertyAccess( Expression::PropertyAccess(
SimplePropertyAccess::new( SimplePropertyAccess::new(
New::from(Call::new( New::from(Call::new(
Identifier::new(interner.get_or_intern_static("Date", utf16!("Date"))) Identifier::new(interner.get_or_intern("Date")).into(),
.into(),
Box::default(), Box::default(),
)) ))
.into(), .into(),
interner.get_or_intern_static("getTime", utf16!("getTime")), interner.get_or_intern("getTime"),
) )
.into(), .into(),
), ),
@ -84,10 +82,10 @@ fn assign_operator_precedence() {
"a = a + 1", "a = a + 1",
vec![Statement::Expression(Expression::from(Assign::new( vec![Statement::Expression(Expression::from(Assign::new(
AssignOp::Assign, AssignOp::Assign,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Binary::new( Binary::new(
ArithmeticOp::Add.into(), ArithmeticOp::Add.into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(1).into(), Literal::from(1).into(),
) )
.into(), .into(),
@ -100,8 +98,8 @@ fn assign_operator_precedence() {
#[test] #[test]
fn hoisting() { fn hoisting() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let hello = interner.get_or_intern_static("hello", utf16!("hello")); let hello = interner.get_or_intern("hello");
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
r" r"
var a = hello(); var a = hello();
@ -137,7 +135,7 @@ fn hoisting() {
); );
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
r" r"
a = 10; a = 10;
@ -179,13 +177,13 @@ fn ambigous_regex_divide_expression() {
Binary::new( Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Literal::Int(1).into(), Literal::Int(1).into(),
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
) )
.into(), .into(),
Binary::new( Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Literal::Int(1).into(), Literal::Int(1).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
))) )))
@ -199,7 +197,7 @@ fn two_divisions_in_expression() {
let s = "a !== 0 || 1 / a === 1 / b;"; let s = "a !== 0 || 1 / a === 1 / b;";
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
s, s,
vec![Statement::Expression(Expression::from(Binary::new( vec![Statement::Expression(Expression::from(Binary::new(
@ -221,7 +219,7 @@ fn two_divisions_in_expression() {
Binary::new( Binary::new(
ArithmeticOp::Div.into(), ArithmeticOp::Div.into(),
Literal::Int(1).into(), Literal::Int(1).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(), Identifier::new(interner.get_or_intern("b")).into(),
) )
.into(), .into(),
) )
@ -245,7 +243,7 @@ fn comment_semi_colon_insertion() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::Int(10).into()), Some(Literal::Int(10).into()),
)] )]
.try_into() .try_into()
@ -254,7 +252,7 @@ fn comment_semi_colon_insertion() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
Some(Literal::Int(20).into()), Some(Literal::Int(20).into()),
)] )]
.try_into() .try_into()
@ -281,7 +279,7 @@ fn multiline_comment_semi_colon_insertion() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::Int(10).into()), Some(Literal::Int(10).into()),
)] )]
.try_into() .try_into()
@ -290,7 +288,7 @@ fn multiline_comment_semi_colon_insertion() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
Some(Literal::Int(20).into()), Some(Literal::Int(20).into()),
)] )]
.try_into() .try_into()
@ -314,7 +312,7 @@ fn multiline_comment_no_lineterminator() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::Int(10).into()), Some(Literal::Int(10).into()),
)] )]
.try_into() .try_into()
@ -323,7 +321,7 @@ fn multiline_comment_no_lineterminator() {
.into(), .into(),
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("b", utf16!("b")).into(), interner.get_or_intern("b").into(),
Some(Literal::Int(20).into()), Some(Literal::Int(20).into()),
)] )]
.try_into() .try_into()
@ -350,7 +348,7 @@ fn assignment_line_terminator() {
vec![ vec![
Declaration::Lexical(LexicalDeclaration::Let( Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("a", utf16!("a")).into(), interner.get_or_intern("a").into(),
Some(Literal::Int(3).into()), Some(Literal::Int(3).into()),
)] )]
.try_into() .try_into()
@ -359,7 +357,7 @@ fn assignment_line_terminator() {
.into(), .into(),
Statement::Expression(Expression::from(Assign::new( Statement::Expression(Expression::from(Assign::new(
AssignOp::Assign, AssignOp::Assign,
Identifier::new(interner.get_or_intern_static("a", utf16!("a"))).into(), Identifier::new(interner.get_or_intern("a")).into(),
Literal::from(5).into(), Literal::from(5).into(),
))) )))
.into(), .into(),
@ -381,7 +379,7 @@ fn assignment_multiline_terminator() {
"#; "#;
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
s, s,
vec![ vec![
@ -413,10 +411,7 @@ fn bracketed_expr() {
check_script_parser( check_script_parser(
s, s,
vec![Statement::Expression( vec![Statement::Expression(
Parenthesized::new( Parenthesized::new(Identifier::new(interner.get_or_intern("b")).into()).into(),
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(),
)
.into(),
) )
.into()], .into()],
interner, interner,
@ -428,7 +423,7 @@ fn increment_in_comma_op() {
let s = r#"(b++, b)"#; let s = r#"(b++, b)"#;
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let b = interner.get_or_intern_static("b", utf16!("b")); let b = interner.get_or_intern("b");
check_script_parser( check_script_parser(
s, s,
vec![Statement::Expression( vec![Statement::Expression(
@ -463,20 +458,15 @@ fn spread_in_object() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let object_properties = vec![ let object_properties = vec![
PropertyDefinition::Property( PropertyDefinition::Property(interner.get_or_intern("a").into(), Literal::from(1).into()),
interner.get_or_intern_static("a", utf16!("a")).into(), PropertyDefinition::SpreadObject(Identifier::new(interner.get_or_intern("b")).into()),
Literal::from(1).into(),
),
PropertyDefinition::SpreadObject(
Identifier::new(interner.get_or_intern_static("b", utf16!("b"))).into(),
),
]; ];
check_script_parser( check_script_parser(
s, s,
vec![Declaration::Lexical(LexicalDeclaration::Let( vec![Declaration::Lexical(LexicalDeclaration::Let(
vec![Variable::from_identifier( vec![Variable::from_identifier(
interner.get_or_intern_static("x", utf16!("x")).into(), interner.get_or_intern("x").into(),
Some(ObjectLiteral::from(object_properties).into()), Some(ObjectLiteral::from(object_properties).into()),
)] )]
.try_into() .try_into()
@ -496,7 +486,7 @@ fn spread_in_arrow_function() {
"#; "#;
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let b = interner.get_or_intern_static("b", utf16!("b")); let b = interner.get_or_intern("b");
let params = FormalParameterList::from(FormalParameter::new( let params = FormalParameterList::from(FormalParameter::new(
Variable::from_identifier(b.into(), None), Variable::from_identifier(b.into(), None),
true, true,
@ -520,7 +510,7 @@ fn spread_in_arrow_function() {
#[test] #[test]
fn empty_statement() { fn empty_statement() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
check_script_parser( check_script_parser(
r" r"
;;var a = 10; ;;var a = 10;
@ -547,11 +537,9 @@ fn empty_statement() {
#[test] #[test]
fn empty_statement_ends_directive_prologues() { fn empty_statement_ends_directive_prologues() {
let interner = &mut Interner::default(); let interner = &mut Interner::default();
let a = interner.get_or_intern_static("a", utf16!("a")); let a = interner.get_or_intern("a");
let use_strict = interner.get_or_intern_static("use strict", utf16!("use strict")); let use_strict = interner.get_or_intern("use strict");
let public = interner let public = interner.get_or_intern("public").into();
.get_or_intern_static("public", utf16!("public"))
.into();
check_script_parser( check_script_parser(
r#" r#"
"a"; "a";

103
boa_types/src/string/common.rs

@ -60,7 +60,8 @@ impl StaticJsStrings {
/// Gets the `JsString` corresponding to `string`, or `None` if the string /// Gets the `JsString` corresponding to `string`, or `None` if the string
/// doesn't exist inside the static array. /// doesn't exist inside the static array.
pub(crate) fn get_string(string: &str) -> Option<JsString> { #[must_use]
pub fn get_string(string: &str) -> Option<JsString> {
if string.len() > MAX_STATIC_LENGTH { if string.len() > MAX_STATIC_LENGTH {
return None; return None;
} }
@ -74,7 +75,8 @@ impl StaticJsStrings {
/// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index /// Gets the `&[u16]` slice corresponding to the provided index, or `None` if the index
/// provided exceeds the size of the static array. /// provided exceeds the size of the static array.
pub(crate) fn get(index: usize) -> Option<&'static str> { #[must_use]
pub fn get(index: usize) -> Option<&'static str> {
RAW_STATICS.index(index).copied() RAW_STATICS.index(index).copied()
} }
@ -206,8 +208,82 @@ const MAX_STATIC_LENGTH: usize = {
}; };
/// Array of raw static strings that aren't reference counted. /// Array of raw static strings that aren't reference counted.
const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!( pub const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
// Reserved identifiers
// See: <https://tc39.es/ecma262/#prod-ReservedWord>
// Note, they must all be together.
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"import",
"in",
"instanceof",
"new",
"null",
"return",
"super",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"var",
"void",
"while",
"with",
// End reserved identifier
// strict reserved identifiers.
// See: <https://tc39.es/ecma262/#prod-Identifier>
// Note, they must all be together.
"implements",
"interface",
"let",
"package",
"private",
"protected",
"public",
"static",
"yield",
// End strict reserved identifiers
"", "",
"prototype",
"constructor",
"arguments",
"eval",
"RegExp",
"get",
"set",
"<main>",
"raw",
"anonymous",
"async",
"of",
"target",
"as",
"from",
"__proto__",
"name",
"await",
"*default*",
"meta",
// Well known symbols // Well known symbols
"Symbol.asyncIterator", "Symbol.asyncIterator",
"[Symbol.asyncIterator]", "[Symbol.asyncIterator]",
@ -259,7 +335,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"URIError", "URIError",
"escape", "escape",
"unescape", "unescape",
"eval",
"Function", "Function",
"Generator", "Generator",
"GeneratorFunction", "GeneratorFunction",
@ -282,7 +357,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"Promise", "Promise",
"Proxy", "Proxy",
"Reflect", "Reflect",
"RegExp",
"Set", "Set",
"String", "String",
"Symbol", "Symbol",
@ -321,28 +395,18 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
",", ",",
":", ":",
// Generic use // Generic use
"name",
"length", "length",
"arguments",
"prototype",
"constructor",
"return",
"throw",
"global", "global",
"globalThis", "globalThis",
// typeof // typeof
"null",
"undefined", "undefined",
"number", "number",
"string", "string",
"symbol", "symbol",
"bigint", "bigint",
"object", "object",
"function",
// Property descriptor // Property descriptor
"value", "value",
"get",
"set",
"writable", "writable",
"enumerable", "enumerable",
"configurable", "configurable",
@ -381,7 +445,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"__defineSetter__", "__defineSetter__",
"__lookupGetter__", "__lookupGetter__",
"__lookupSetter__", "__lookupSetter__",
"__proto__",
"get __proto__", "get __proto__",
"set __proto__", "set __proto__",
// Function object // Function object
@ -393,9 +456,7 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"callee", "callee",
// Array object // Array object
"at", "at",
"from",
"isArray", "isArray",
"of",
"copyWithin", "copyWithin",
"every", "every",
"fill", "fill",
@ -427,7 +488,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"toReversed", "toReversed",
"toSorted", "toSorted",
"toSpliced", "toSpliced",
"with",
// String object // String object
"charAt", "charAt",
"charCodeAt", "charCodeAt",
@ -442,7 +502,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"normalize", "normalize",
"padEnd", "padEnd",
"padStart", "padStart",
"raw",
"repeat", "repeat",
"replace", "replace",
"replaceAll", "replaceAll",
@ -519,7 +578,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"get flags", "get flags",
"get source", "get source",
// Symbol object // Symbol object
"for",
"keyFor", "keyFor",
"description", "description",
"asyncIterator", "asyncIterator",
@ -533,7 +591,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"get description", "get description",
// Map object // Map object
"clear", "clear",
"delete",
"has", "has",
"size", "size",
// Set object // Set object
@ -601,8 +658,6 @@ const RAW_STATICS: phf::OrderedSet<&'static str> = phf::phf_ordered_set!(
"any", "any",
"race", "race",
"then", "then",
"catch",
"finally",
"withResolvers", "withResolvers",
// Iterator object // Iterator object
"Array Iterator", "Array Iterator",

6
boa_types/src/string/mod.rs

@ -867,6 +867,12 @@ impl JsString {
pub fn is_static(&self) -> bool { pub fn is_static(&self) -> bool {
self.ptr.is_tagged() self.ptr.is_tagged()
} }
pub fn as_static(&self) -> Option<usize> {
if let UnwrappedTagged::Tag(index) = self.ptr.unwrap() {
return Some(index);
}
None
}
pub fn get<'a, I>(&'a self, index: I) -> Option<I::Value> pub fn get<'a, I>(&'a self, index: I) -> Option<I::Value>
where where

Loading…
Cancel
Save