diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 00e9de15158..cc193fa1b6a 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -95,9 +95,9 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Utf16 if (given_name.is_empty()) given_name = Utf16FlyString {}; - auto has_own_name = !name().is_empty(); + auto own_name = name(); + auto has_own_name = !own_name.is_empty(); - auto own_name = Utf16FlyString::from_utf8(name()); auto const& used_name = has_own_name ? own_name : given_name; auto environment = GC::Ref { *vm.running_execution_context().lexical_environment }; @@ -120,10 +120,10 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Utf16 return closure; } -Optional CallExpression::expression_string() const +Optional CallExpression::expression_string() const { if (is(*m_callee)) - return static_cast(*m_callee).string().to_string(); + return static_cast(*m_callee).string().to_utf16_string(); if (is(*m_callee)) return static_cast(*m_callee).to_string_approximation(); @@ -137,7 +137,7 @@ static ThrowCompletionOr class_key_to_property_name(VM& vm, Ex auto& private_identifier = static_cast(key); auto private_environment = vm.running_execution_context().private_environment; VERIFY(private_environment); - return ClassElementName { private_environment->resolve_private_identifier(Utf16FlyString::from_utf8(private_identifier.string())) }; + return ClassElementName { private_environment->resolve_private_identifier(private_identifier.string()) }; } VERIFY(!prop_key.is_special_empty_value()); @@ -156,7 +156,7 @@ ThrowCompletionOr ClassMethod::class_element_evaluatio auto& method_function = *ECMAScriptFunctionObject::create_from_function_node( *m_function, - Utf16String::from_utf8(m_function->name()), + m_function->name(), *vm.current_realm(), vm.lexical_environment(), vm.running_execution_context().private_environment); @@ -271,19 +271,19 @@ ThrowCompletionOr ClassField::class_element_evaluation }; } -static Optional nullopt_or_private_identifier_description(Expression const& expression) +static Optional nullopt_or_private_identifier_description(Expression const& expression) { if (is(expression)) return static_cast(expression).string(); return {}; } -Optional ClassField::private_bound_identifier() const +Optional ClassField::private_bound_identifier() const { return nullopt_or_private_identifier_description(*m_key); } -Optional ClassMethod::private_bound_identifier() const +Optional ClassMethod::private_bound_identifier() const { return nullopt_or_private_identifier_description(*m_key); } @@ -355,7 +355,7 @@ ThrowCompletionOr ClassExpression::create_class_const auto const& constructor = *m_constructor; auto class_constructor = ECMAScriptFunctionObject::create_from_function_node( constructor, - Utf16FlyString::from_utf8(constructor.name()), + constructor.name(), realm, vm.lexical_environment(), vm.running_execution_context().private_environment); @@ -1244,16 +1244,17 @@ void MemberExpression::dump(int indent) const m_property->dump(indent + 1); } -String MemberExpression::to_string_approximation() const +Utf16String MemberExpression::to_string_approximation() const { - String object_string = ""_string; + Utf16View object_string = ""sv; if (is(*m_object)) - object_string = static_cast(*m_object).string().to_string(); + object_string = static_cast(*m_object).string().view(); + if (is_computed()) - return MUST(String::formatted("{}[]", object_string)); + return Utf16String::formatted("{}[]", object_string); if (is(*m_property)) - return MUST(String::formatted("{}.{}", object_string, as(*m_property).string())); - return MUST(String::formatted("{}.{}", object_string, as(*m_property).string())); + return Utf16String::formatted("{}.{}", object_string, as(*m_property).string()); + return Utf16String::formatted("{}.{}", object_string, as(*m_property).string()); } bool MemberExpression::ends_in_private_name() const @@ -1531,7 +1532,7 @@ void ScopeNode::add_hoisted_function(NonnullRefPtr de m_functions_hoistable_with_annexB_extension.append(move(declaration)); } -FlyString ExportStatement::local_name_for_default = "*default*"_fly_string; +Utf16FlyString ExportStatement::local_name_for_default = "*default*"_utf16_fly_string; static void dump_assert_clauses(ModuleRequest const& request) { @@ -1549,7 +1550,7 @@ void ExportStatement::dump(int indent) const print_indent(indent + 1); outln("(ExportEntries)"); - auto string_or_null = [](Optional const& string) -> ByteString { + auto string_or_null = [](Optional const& string) -> ByteString { if (!string.has_value()) { return "null"; } @@ -1597,7 +1598,7 @@ void ImportStatement::dump(int indent) const } } -bool ExportStatement::has_export(FlyString const& export_name) const +bool ExportStatement::has_export(Utf16FlyString const& export_name) const { return any_of(m_entries.begin(), m_entries.end(), [&](auto& entry) { // Make sure that empty exported names does not overlap with anything @@ -1607,7 +1608,7 @@ bool ExportStatement::has_export(FlyString const& export_name) const }); } -bool ImportStatement::has_bound_name(FlyString const& name) const +bool ImportStatement::has_bound_name(Utf16FlyString const& name) const { return any_of(m_entries.begin(), m_entries.end(), [&](auto& entry) { return entry.local_name == name; @@ -1641,7 +1642,7 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment return; } - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // i. If IsConstantDeclaration of d is true, then if (is_constant_declaration) { @@ -1664,7 +1665,7 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment // ii. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv. auto function = ECMAScriptFunctionObject::create_from_function_node( function_declaration, - Utf16FlyString::from_utf8(function_declaration.name()), + function_declaration.name(), realm, environment, private_environment); @@ -1697,7 +1698,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // 2. Let varNames be the VarDeclaredNames of script. // 3. For each element name of lexNames, do TRY(for_each_lexically_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // a. If HasLexicalDeclaration(env, name) is true, throw a SyntaxError exception. if (global_environment.has_lexical_declaration(name)) @@ -1719,7 +1720,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // 4. For each element name of varNames, do TRY(for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { // a. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. - if (global_environment.has_lexical_declaration(Utf16FlyString::from_utf8(identifier.string()))) + if (global_environment.has_lexical_declaration(identifier.string())) return vm.throw_completion(ErrorType::TopLevelVariableAlreadyDeclared, identifier.string()); return {}; @@ -1735,7 +1736,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // 8. For each element d of varDeclarations, in reverse List order, do TRY(for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) -> ThrowCompletionOr { - auto function_name = Utf16FlyString::from_utf8(function.name()); + auto function_name = function.name(); // a. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then // i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration. @@ -1754,7 +1755,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // 2. If fnDefinable is false, throw a TypeError exception. if (!function_definable) - return vm.throw_completion(ErrorType::CannotDeclareGlobalFunction, function.name()); + return vm.throw_completion(ErrorType::CannotDeclareGlobalFunction, function_name); // 3. Append fn to declaredFunctionNames. // Note: Already done in step iv. above. @@ -1776,7 +1777,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // i. For each String vn of the BoundNames of d, do return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // 1. If vn is not an element of declaredFunctionNames, then if (declared_function_names.contains(name)) @@ -1806,7 +1807,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within script, do TRY(for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr { // i. Let F be StringValue of the BindingIdentifier of f. - auto function_name = Utf16FlyString::from_utf8(function_declaration.name()); + auto function_name = function_declaration.name(); // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for script, then // Note: This step is already performed during parsing and for_each_function_hoistable_with_annexB_extension so this always passes here. @@ -1858,7 +1859,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // a. NOTE: Lexically declared names are only instantiated here but not initialized. // b. For each element dn of the BoundNames of d, do return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // i. If IsConstantDeclaration of d is true, then if (declaration.is_constant_declaration()) { @@ -1884,7 +1885,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global // b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv. auto function = ECMAScriptFunctionObject::create_from_function_node( declaration, - Utf16FlyString::from_utf8(declaration.name()), + declaration.name(), realm, &global_environment, private_environment); @@ -1903,7 +1904,7 @@ ThrowCompletionOr Program::global_declaration_instantiation(VM& vm, Global return {}; } -ModuleRequest::ModuleRequest(FlyString module_specifier_, Vector attributes) +ModuleRequest::ModuleRequest(Utf16FlyString module_specifier_, Vector attributes) : module_specifier(move(module_specifier_)) , attributes(move(attributes)) { diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 303a90f07fe..8d87033230f 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -343,7 +345,7 @@ public: ThrowCompletionOr for_each_function_hoistable_with_annexB_extension(ThrowCompletionOrVoidCallback&& callback) const; auto const& local_variables_names() const { return m_local_variables_names; } - size_t add_local_variable(FlyString name, LocalVariable::DeclarationKind declaration_kind) + size_t add_local_variable(Utf16FlyString name, LocalVariable::DeclarationKind declaration_kind) { auto index = m_local_variables_names.size(); m_local_variables_names.append({ move(name), declaration_kind }); @@ -370,10 +372,10 @@ private: // ImportEntry Record, https://tc39.es/ecma262/#table-importentry-record-fields struct ImportEntry { - Optional import_name; // [[ImportName]]: stored string if Optional is not empty, NAMESPACE-OBJECT otherwise - FlyString local_name; // [[LocalName]] + Optional import_name; // [[ImportName]]: stored string if Optional is not empty, NAMESPACE-OBJECT otherwise + Utf16FlyString local_name; // [[LocalName]] - ImportEntry(Optional import_name_, FlyString local_name_) + ImportEntry(Optional import_name_, Utf16FlyString local_name_) : import_name(move(import_name_)) , local_name(move(local_name_)) { @@ -407,7 +409,7 @@ public: virtual Bytecode::CodeGenerationErrorOr> generate_bytecode(Bytecode::Generator&, Optional preferred_dst = {}) const override; - bool has_bound_name(FlyString const& name) const; + bool has_bound_name(Utf16FlyString const& name) const; Vector const& entries() const { return m_entries; } ModuleRequest const& module_request() const { return m_module_request; } @@ -429,10 +431,10 @@ struct ExportEntry { EmptyNamedExport, } kind; - Optional export_name; // [[ExportName]] - Optional local_or_import_name; // Either [[ImportName]] or [[LocalName]] + Optional export_name; // [[ExportName]] + Optional local_or_import_name; // Either [[ImportName]] or [[LocalName]] - ExportEntry(Kind export_kind, Optional export_name_, Optional local_or_import_name_) + ExportEntry(Kind export_kind, Optional export_name_, Optional local_or_import_name_) : kind(export_kind) , export_name(move(export_name_)) , local_or_import_name(move(local_or_import_name_)) @@ -444,7 +446,7 @@ struct ExportEntry { return m_module_request != nullptr; } - static ExportEntry indirect_export_entry(ModuleRequest const& module_request, Optional export_name, Optional import_name) + static ExportEntry indirect_export_entry(ModuleRequest const& module_request, Optional export_name, Optional import_name) { ExportEntry entry { Kind::NamedExport, move(export_name), move(import_name) }; entry.m_module_request = &module_request; @@ -462,7 +464,7 @@ private: friend class ExportStatement; public: - static ExportEntry named_export(FlyString export_name, FlyString local_name) + static ExportEntry named_export(Utf16FlyString export_name, Utf16FlyString local_name) { return ExportEntry { Kind::NamedExport, move(export_name), move(local_name) }; } @@ -472,7 +474,7 @@ public: return ExportEntry { Kind::ModuleRequestAllButDefault, {}, {} }; } - static ExportEntry all_module_request(FlyString export_name) + static ExportEntry all_module_request(Utf16FlyString export_name) { return ExportEntry { Kind::ModuleRequestAll, move(export_name), {} }; } @@ -485,7 +487,7 @@ public: class ExportStatement final : public Statement { public: - static FlyString local_name_for_default; + static Utf16FlyString local_name_for_default; ExportStatement(SourceRange source_range, RefPtr statement, Vector entries, bool is_default_export, Optional module_request) : Statement(move(source_range)) @@ -504,7 +506,7 @@ public: virtual Bytecode::CodeGenerationErrorOr> generate_bytecode(Bytecode::Generator&, Optional preferred_dst = {}) const override; - bool has_export(FlyString const& export_name) const; + bool has_export(Utf16FlyString const& export_name) const; bool has_statement() const { return m_statement; } Vector const& entries() const { return m_entries; } @@ -676,13 +678,13 @@ struct BindingPattern : RefCounted { class Identifier final : public Expression { public: - explicit Identifier(SourceRange source_range, FlyString string) + explicit Identifier(SourceRange source_range, Utf16FlyString string) : Expression(move(source_range)) , m_string(move(string)) { } - FlyString const& string() const { return m_string; } + Utf16FlyString const& string() const { return m_string; } struct Local { enum Type { @@ -720,7 +722,7 @@ public: private: virtual bool is_identifier() const override { return true; } - FlyString m_string; + Utf16FlyString m_string; Optional m_local_index; bool m_is_global { false }; @@ -748,7 +750,7 @@ public: size_t size() const { return m_parameters.size(); } Vector const& parameters() const { return m_parameters; } - Optional get_index_of_parameter_name(FlyString const& name) const + Optional get_index_of_parameter_name(Utf16FlyString const& name) const { // Iterate backwards to return the last parameter with the same name for (int i = m_parameters.size() - 1; i >= 0; i--) { @@ -780,7 +782,7 @@ struct FunctionParsingInsights { class FunctionNode { public: - FlyString name() const { return m_name ? m_name->string() : ""_fly_string; } + Utf16FlyString name() const { return m_name ? m_name->string() : Utf16FlyString {}; } RefPtr name_identifier() const { return m_name; } ByteString const& source_text() const { return m_source_text; } Statement const& body() const { return *m_body; } @@ -1303,7 +1305,7 @@ private: class StringLiteral final : public Expression { public: - explicit StringLiteral(SourceRange source_range, String value) + explicit StringLiteral(SourceRange source_range, Utf16String value) : Expression(move(source_range)) , m_value(move(value)) { @@ -1312,12 +1314,12 @@ public: virtual void dump(int indent) const override; virtual Bytecode::CodeGenerationErrorOr> generate_bytecode(Bytecode::Generator&, Optional preferred_dst = {}) const override; - String const& value() const { return m_value; } + Utf16String const& value() const { return m_value; } private: virtual bool is_string_literal() const override { return true; } - String m_value; + Utf16String m_value; }; class NullLiteral final : public PrimitiveLiteral { @@ -1367,20 +1369,20 @@ private: class PrivateIdentifier final : public Expression { public: - explicit PrivateIdentifier(SourceRange source_range, FlyString string) + explicit PrivateIdentifier(SourceRange source_range, Utf16FlyString string) : Expression(move(source_range)) , m_string(move(string)) { } - FlyString const& string() const { return m_string; } + Utf16FlyString const& string() const { return m_string; } virtual void dump(int indent) const override; virtual bool is_private_identifier() const override { return true; } private: - FlyString m_string; + Utf16FlyString m_string; }; class ClassElement : public ASTNode { @@ -1404,7 +1406,7 @@ public: using ClassValue = Variant; virtual ThrowCompletionOr class_element_evaluation(VM&, Object& home_object, Value) const = 0; - virtual Optional private_bound_identifier() const { return {}; } + virtual Optional private_bound_identifier() const { return {}; } private: bool m_is_static { false }; @@ -1432,7 +1434,7 @@ public: virtual void dump(int indent) const override; virtual ThrowCompletionOr class_element_evaluation(VM&, Object& home_object, Value property_key) const override; - virtual Optional private_bound_identifier() const override; + virtual Optional private_bound_identifier() const override; private: virtual bool is_class_method() const override { return true; } @@ -1458,7 +1460,7 @@ public: virtual void dump(int indent) const override; virtual ThrowCompletionOr class_element_evaluation(VM&, Object& home_object, Value property_key) const override; - virtual Optional private_bound_identifier() const override; + virtual Optional private_bound_identifier() const override; private: NonnullRefPtr m_key; @@ -1507,7 +1509,7 @@ public: { } - FlyString name() const { return m_name ? m_name->string() : ""_fly_string; } + Utf16FlyString name() const { return m_name ? m_name->string() : Utf16FlyString {}; } ByteString const& source_text() const { return m_source_text; } RefPtr constructor() const { return m_constructor; } @@ -1547,7 +1549,7 @@ public: virtual bool is_lexical_declaration() const override { return true; } - FlyString name() const { return m_class_expression->name(); } + Utf16FlyString name() const { return m_class_expression->name(); } private: virtual bool is_class_declaration() const override { return true; } @@ -1651,7 +1653,7 @@ protected: virtual bool is_call_expression() const override { return true; } - Optional expression_string() const; + Optional expression_string() const; NonnullRefPtr m_callee; }; @@ -1994,7 +1996,7 @@ public: Expression const& object() const { return *m_object; } Expression const& property() const { return *m_property; } - [[nodiscard]] String to_string_approximation() const; + Utf16String to_string_approximation() const; bool ends_in_private_name() const; diff --git a/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Libraries/LibJS/Bytecode/ASTCodegen.cpp index cb376d2e5a5..2366ed923ac 100644 --- a/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1171,7 +1171,7 @@ Bytecode::CodeGenerationErrorOr> ObjectExpression::gener if (is(property->key())) { auto& string_literal = static_cast(property->key()); - Bytecode::IdentifierTableIndex key_name = generator.intern_identifier(MUST(FlyString::from_utf8(string_literal.value().bytes()))); + Bytecode::IdentifierTableIndex key_name = generator.intern_identifier(string_literal.value()); Optional value; if (property_kind == Bytecode::Op::PropertyKind::ProtoSetter) { @@ -1179,9 +1179,10 @@ Bytecode::CodeGenerationErrorOr> ObjectExpression::gener } else { auto identifier = string_literal.value(); if (property_kind == Bytecode::Op::PropertyKind::Getter) - identifier = MUST(String::formatted("get {}", identifier)); + identifier = Utf16String::formatted("get {}", identifier); else if (property_kind == Bytecode::Op::PropertyKind::Setter) - identifier = MUST(String::formatted("set {}", identifier)); + identifier = Utf16String::formatted("set {}", identifier); + auto name = generator.intern_identifier(identifier); value = TRY(generator.emit_named_evaluation_if_anonymous_function(property->value(), name)); } @@ -1769,7 +1770,7 @@ Bytecode::CodeGenerationErrorOr> CallExpression::generat Optional expression_string_index; if (auto expression_string = this->expression_string(); expression_string.has_value()) - expression_string_index = generator.intern_string(expression_string.release_value()); + expression_string_index = generator.intern_string(expression_string->to_utf8_but_should_be_ported_to_utf16()); bool has_spread = any_of(arguments(), [](auto& argument) { return argument.is_spread; }); auto dst = choose_dst(generator, preferred_dst); diff --git a/Libraries/LibJS/Bytecode/Generator.cpp b/Libraries/LibJS/Bytecode/Generator.cpp index 5fb900aa101..8e16218f68c 100644 --- a/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Libraries/LibJS/Bytecode/Generator.cpp @@ -915,7 +915,7 @@ static Optional expression_identifier(Expression const& expression) { if (expression.is_identifier()) { auto const& identifier = static_cast(expression); - return identifier.string().to_string(); + return identifier.string().view().to_utf8_but_should_be_ported_to_utf16(); } if (expression.is_numeric_literal()) { diff --git a/Libraries/LibJS/Bytecode/Interpreter.cpp b/Libraries/LibJS/Bytecode/Interpreter.cpp index a4e7bd8a493..c784cecac74 100644 --- a/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1361,7 +1361,7 @@ inline Value new_function(VM& vm, FunctionNode const& function_node, Optional new_class(VM& vm, Value supe if (!class_expression.has_name() && lhs_name.has_value()) { class_name = interpreter.current_executable().get_identifier(lhs_name.value()); } else { - auto name = Utf16FlyString::from_utf8(class_expression.name()); - binding_name = name; - class_name = name; + class_name = class_expression.name(); + binding_name = class_name; } return TRY(class_expression.create_class_constructor(vm, class_environment, vm.lexical_environment(), super_class, element_keys, binding_name, class_name)); diff --git a/Libraries/LibJS/LocalVariable.h b/Libraries/LibJS/LocalVariable.h index 7d947ab44bd..ec1362e5c62 100644 --- a/Libraries/LibJS/LocalVariable.h +++ b/Libraries/LibJS/LocalVariable.h @@ -6,12 +6,11 @@ #pragma once -#include +#include namespace JS { struct LocalVariable { - FlyString name; enum class DeclarationKind { Var, LetOrConst, @@ -19,6 +18,8 @@ struct LocalVariable { ArgumentsObject, CatchClauseParameter }; + + Utf16FlyString name; DeclarationKind declaration_kind; }; diff --git a/Libraries/LibJS/Module.cpp b/Libraries/LibJS/Module.cpp index 0dacda66d16..6589256e368 100644 --- a/Libraries/LibJS/Module.cpp +++ b/Libraries/LibJS/Module.cpp @@ -120,7 +120,7 @@ void finish_loading_imported_module(ImportedModuleReferrer referrer, ModuleReque // i. Append the Record { [[Specifier]]: specifier, [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]]. loaded_modules.append(ModuleWithSpecifier { - .specifier = module_request.module_specifier.to_string(), + .specifier = module_request.module_specifier.to_utf16_string(), .module = GC::Ref(*module) }); } } diff --git a/Libraries/LibJS/Parser.cpp b/Libraries/LibJS/Parser.cpp index bf8de1b4605..5699d14153b 100644 --- a/Libraries/LibJS/Parser.cpp +++ b/Libraries/LibJS/Parser.cpp @@ -237,7 +237,7 @@ public: ScopePusher* parent_scope() { return m_parent_scope; } ScopePusher const* parent_scope() const { return m_parent_scope; } - [[nodiscard]] bool has_declaration(FlyString const& name) const + [[nodiscard]] bool has_declaration(Utf16FlyString const& name) const { return m_lexical_names.contains(name) || m_var_names.contains(name) || !m_functions_to_hoist.find_if([&name](auto& function) { return function->name() == name; }).is_end(); } @@ -496,7 +496,7 @@ public: } private: - void throw_identifier_declared(FlyString const& name, NonnullRefPtr const& declaration) + void throw_identifier_declared(Utf16FlyString const& name, NonnullRefPtr const& declaration) { m_parser.syntax_error(MUST(String::formatted("Identifier '{}' already declared", name)), declaration->source_range().start); } @@ -509,17 +509,17 @@ private: ScopePusher* m_parent_scope { nullptr }; ScopePusher* m_top_level_scope { nullptr }; - HashTable m_lexical_names; - HashTable m_var_names; - HashTable m_function_names; - HashTable m_catch_parameter_names; + HashTable m_lexical_names; + HashTable m_var_names; + HashTable m_function_names; + HashTable m_catch_parameter_names; - HashTable m_forbidden_lexical_names; - HashTable m_forbidden_var_names; + HashTable m_forbidden_lexical_names; + HashTable m_forbidden_var_names; Vector> m_functions_to_hoist; - HashTable m_bound_names; - HashTable m_function_parameters_candidates_for_local_variables; + HashTable m_bound_names; + HashTable m_function_parameters_candidates_for_local_variables; struct IdentifierGroup { bool captured_by_nested_function { false }; @@ -529,7 +529,7 @@ private: Vector> identifiers; Optional declaration_kind; }; - HashMap m_identifier_groups; + HashMap m_identifier_groups; RefPtr m_function_parameters; @@ -983,20 +983,11 @@ bool Parser::match_invalid_escaped_keyword() const return token_value != "let"sv; } -static constexpr AK::Array strict_reserved_words = { "implements"sv, "interface"sv, "let"sv, "package"sv, "private"sv, "protected"sv, "public"sv, "static"sv, "yield"sv }; +static auto strict_reserved_words = AK::Array { "implements"_utf16_fly_string, "interface"_utf16_fly_string, "let"_utf16_fly_string, "package"_utf16_fly_string, "private"_utf16_fly_string, "protected"_utf16_fly_string, "public"_utf16_fly_string, "static"_utf16_fly_string, "yield"_utf16_fly_string }; -static bool is_strict_reserved_word(StringView str) +static bool is_strict_reserved_word(Utf16FlyString const& str) { - return any_of(strict_reserved_words, [&str](StringView word) { - return word == str; - }); -} - -static bool is_strict_reserved_word(Utf16View const& str) -{ - return any_of(strict_reserved_words, [&str](StringView word) { - return word == str; - }); + return strict_reserved_words.contains_slow(str); } static bool is_simple_parameter_list(FunctionParameters const& parameters) @@ -1090,7 +1081,8 @@ RefPtr Parser::try_parse_arrow_function_expression(boo syntax_error("BindingIdentifier may not be 'arguments' or 'eval' in strict mode"_string); if (is_async && token.value() == "await"sv) syntax_error("'await' is a reserved identifier in async functions"_string); - auto identifier = create_ast_node({ m_source_code, rule_start.position(), position() }, token.value().to_utf8_but_should_be_ported_to_utf16()); + + auto identifier = create_ast_node({ m_source_code, rule_start.position(), position() }, token.fly_string_value()); parameters = FunctionParameters::create(Vector { FunctionParameter { identifier, {} } }); } @@ -1475,7 +1467,7 @@ NonnullRefPtr Parser::parse_class_expression(bool expect_ switch (m_state.current_token.type()) { case TokenType::Identifier: name = consume().fly_string_value(); - property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name.view().to_utf8_but_should_be_ported_to_utf16()); + property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name.to_utf16_string()); break; case TokenType::PrivateIdentifier: name = consume().fly_string_value(); @@ -1512,11 +1504,11 @@ NonnullRefPtr Parser::parse_class_expression(bool expect_ syntax_error(MUST(String::formatted("Duplicate private field or method named '{}'", name))); } - property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name.view().to_utf8_but_should_be_ported_to_utf16()); + property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name); break; case TokenType::StringLiteral: { auto string_literal = parse_string_literal(consume()); - name = Utf16FlyString::from_utf8(string_literal->value()); + name = string_literal->value(); property_key = move(string_literal); break; } @@ -1552,7 +1544,7 @@ NonnullRefPtr Parser::parse_class_expression(bool expect_ break; } - property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name.view().to_utf8_but_should_be_ported_to_utf16()); + property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, name.to_utf16_string()); } else if (match(TokenType::CurlyOpen) && is_static) { auto static_start = push_start(); consume(TokenType::CurlyOpen); @@ -1657,11 +1649,11 @@ NonnullRefPtr Parser::parse_class_expression(bool expect_ // this function does not. // So we use a custom version of SuperCall which doesn't use the @@iterator // method on %Array.prototype% visibly. - auto argument_name = create_ast_node({ m_source_code, rule_start.position(), position() }, "args"_fly_string); + auto argument_name = create_ast_node({ m_source_code, rule_start.position(), position() }, "args"_utf16_fly_string); auto super_call = create_ast_node( { m_source_code, rule_start.position(), position() }, SuperCall::IsPartOfSyntheticConstructor::Yes, - CallExpression::Argument { create_ast_node({ m_source_code, rule_start.position(), position() }, "args"_fly_string), true }); + CallExpression::Argument { create_ast_node({ m_source_code, rule_start.position(), position() }, "args"_utf16_fly_string), true }); // NOTE: While the JS approximation above doesn't do `return super(...args)`, the // abstract closure is expected to capture and return the result, so we do need a // return statement here to create the correct completion. @@ -1767,7 +1759,7 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression() if (auto arrow_function_result = try_arrow_function_parse_or_fail(position(), false)) return { arrow_function_result.release_nonnull(), false }; - auto string = m_state.current_token.value(); + auto string = m_state.current_token.fly_string_value(); // This could be 'eval' or 'arguments' and thus needs a custom check (`eval[1] = true`) if (m_state.strict_mode && (string == "let"sv || is_strict_reserved_word(string))) syntax_error(MUST(String::formatted("Identifier must not be a reserved word in strict mode ('{}')", string))); @@ -1852,7 +1844,7 @@ Parser::PrimaryExpressionParseResult Parser::parse_primary_expression() syntax_error(MUST(String::formatted("Reference to undeclared private field or method '{}'", m_state.current_token.value()))); if (next_token().type() != TokenType::In) syntax_error("Cannot have a private identifier in expression if not followed by 'in'"_string); - return { create_ast_node({ m_source_code, rule_start.position(), position() }, consume().value().to_utf8_but_should_be_ported_to_utf16()) }; + return { create_ast_node({ m_source_code, rule_start.position(), position() }, consume().fly_string_value()) }; default: if (match_identifier_name()) goto read_as_identifier; @@ -2015,7 +2007,7 @@ NonnullRefPtr Parser::parse_property_key() } else { if (!match_identifier_name()) expected("IdentifierName"); - return create_ast_node({ m_source_code, rule_start.position(), position() }, consume().value().to_utf8_but_should_be_ported_to_utf16()); + return create_ast_node({ m_source_code, rule_start.position(), position() }, consume().fly_string_value().to_utf16_string()); } } @@ -2083,7 +2075,7 @@ NonnullRefPtr Parser::parse_object_expression() property_type = ObjectProperty::Type::Setter; property_key = parse_property_key(); } else { - property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, identifier.value().to_utf8_but_should_be_ported_to_utf16()); + property_key = create_ast_node({ m_source_code, rule_start.position(), position() }, identifier.fly_string_value().to_utf16_string()); property_value = create_identifier_and_register_in_current_scope({ m_source_code, rule_start.position(), position() }, identifier.fly_string_value()); } } else { @@ -2092,7 +2084,7 @@ NonnullRefPtr Parser::parse_object_expression() // 4. Else if propKey is the String value "__proto__" and if IsComputedPropertyKey of PropertyName is false, then // a. Let isProtoSetter be true. - bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is(*property_key) && static_cast(*property_key).value() == "__proto__"; + bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is(*property_key) && static_cast(*property_key).value() == "__proto__"sv; if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) { if (!match(TokenType::ParenOpen)) { @@ -2240,7 +2232,7 @@ NonnullRefPtr Parser::parse_string_literal(Token const& tok } } - return create_ast_node({ m_source_code, rule_start.position(), position() }, string.to_utf8_but_should_be_ported_to_utf16()); + return create_ast_node({ m_source_code, rule_start.position(), position() }, move(string)); } NonnullRefPtr Parser::parse_template_literal(bool is_tagged) @@ -2252,7 +2244,7 @@ NonnullRefPtr Parser::parse_template_literal(bool is_tagg Vector> raw_strings; auto append_empty_string = [this, &rule_start, &expressions, &raw_strings, is_tagged]() { - auto string_literal = create_ast_node({ m_source_code, rule_start.position(), position() }, ""_string); + auto string_literal = create_ast_node({ m_source_code, rule_start.position(), position() }, Utf16String {}); expressions.append(string_literal); if (is_tagged) raw_strings.append(string_literal); @@ -2274,7 +2266,7 @@ NonnullRefPtr Parser::parse_template_literal(bool is_tagg else expressions.append(move(parsed_string_value)); if (is_tagged) - raw_strings.append(create_ast_node({ m_source_code, rule_start.position(), position() }, token.raw_template_value().to_utf8_but_should_be_ported_to_utf16())); + raw_strings.append(create_ast_node({ m_source_code, rule_start.position(), position() }, token.raw_template_value())); } else if (match(TokenType::TemplateLiteralExprStart)) { consume(TokenType::TemplateLiteralExprStart); if (match(TokenType::TemplateLiteralExprEnd)) { @@ -2492,12 +2484,12 @@ Parser::ExpressionResult Parser::parse_secondary_expression(NonnullRefPtr(*lhs)) syntax_error(MUST(String::formatted("Cannot access private field or method '{}' on super", m_state.current_token.value()))); - return create_ast_node({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node({ m_source_code, rule_start.position(), position() }, consume().value().to_utf8_but_should_be_ported_to_utf16())); + return create_ast_node({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node({ m_source_code, rule_start.position(), position() }, consume().fly_string_value())); } else if (!match_identifier_name()) { expected("IdentifierName"); } - return create_ast_node({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node({ m_source_code, rule_start.position(), position() }, consume_and_allow_division().value().to_utf8_but_should_be_ported_to_utf16())); + return create_ast_node({ m_source_code, rule_start.position(), position() }, move(lhs), create_ast_node({ m_source_code, rule_start.position(), position() }, consume_and_allow_division().fly_string_value())); case TokenType::BracketOpen: { consume(TokenType::BracketOpen); auto expression = create_ast_node({ m_source_code, rule_start.position(), position() }, move(lhs), parse_expression(0), true); @@ -2861,7 +2853,7 @@ NonnullRefPtr Parser::parse_function_body(NonnullRefPtrin_strict_mode() || function_kind != FunctionKind::Normal) { - Vector parameter_names; + Vector parameter_names; for (auto& parameter : parameters->parameters()) { parameter.binding.visit( [&](Identifier const& identifier) { @@ -3091,7 +3083,7 @@ NonnullRefPtr Parser::parse_formal_parameters(int& fun syntax_error(message, Position { token.line_number(), token.line_column() }); break; } - return create_ast_node({ m_source_code, rule_start.position(), position() }, token.value().to_utf8_but_should_be_ported_to_utf16()); + return create_ast_node({ m_source_code, rule_start.position(), position() }, token.fly_string_value()); }; while (match(TokenType::CurlyOpen) || match(TokenType::BracketOpen) || match_identifier() || match(TokenType::TripleDot)) { @@ -3139,7 +3131,7 @@ NonnullRefPtr Parser::parse_formal_parameters(int& fun return FunctionParameters::create(move(parameters)); } -static AK::Array s_reserved_words = { "break"_fly_string, "case"_fly_string, "catch"_fly_string, "class"_fly_string, "const"_fly_string, "continue"_fly_string, "debugger"_fly_string, "default"_fly_string, "delete"_fly_string, "do"_fly_string, "else"_fly_string, "enum"_fly_string, "export"_fly_string, "extends"_fly_string, "false"_fly_string, "finally"_fly_string, "for"_fly_string, "function"_fly_string, "if"_fly_string, "import"_fly_string, "in"_fly_string, "instanceof"_fly_string, "new"_fly_string, "null"_fly_string, "return"_fly_string, "super"_fly_string, "switch"_fly_string, "this"_fly_string, "throw"_fly_string, "true"_fly_string, "try"_fly_string, "typeof"_fly_string, "var"_fly_string, "void"_fly_string, "while"_fly_string, "with"_fly_string }; +static auto s_reserved_words = AK::Array { "break"_utf16_fly_string, "case"_utf16_fly_string, "catch"_utf16_fly_string, "class"_utf16_fly_string, "const"_utf16_fly_string, "continue"_utf16_fly_string, "debugger"_utf16_fly_string, "default"_utf16_fly_string, "delete"_utf16_fly_string, "do"_utf16_fly_string, "else"_utf16_fly_string, "enum"_utf16_fly_string, "export"_utf16_fly_string, "extends"_utf16_fly_string, "false"_utf16_fly_string, "finally"_utf16_fly_string, "for"_utf16_fly_string, "function"_utf16_fly_string, "if"_utf16_fly_string, "import"_utf16_fly_string, "in"_utf16_fly_string, "instanceof"_utf16_fly_string, "new"_utf16_fly_string, "null"_utf16_fly_string, "return"_utf16_fly_string, "super"_utf16_fly_string, "switch"_utf16_fly_string, "this"_utf16_fly_string, "throw"_utf16_fly_string, "true"_utf16_fly_string, "try"_utf16_fly_string, "typeof"_utf16_fly_string, "var"_utf16_fly_string, "void"_utf16_fly_string, "while"_utf16_fly_string, "with"_utf16_fly_string }; RefPtr Parser::parse_binding_pattern(Parser::AllowDuplicates allow_duplicates, Parser::AllowMemberExpressions allow_member_expressions) { @@ -3328,7 +3320,7 @@ RefPtr Parser::parse_binding_pattern(Parser::AllowDuplicat pattern->entries = move(entries); pattern->kind = kind; - Vector bound_names; + Vector bound_names; // NOTE: Nothing in the callback throws an exception. MUST(pattern->for_each_bound_identifier([&](auto& identifier) { auto const& name = identifier.string(); @@ -3603,7 +3595,7 @@ NonnullRefPtr Parser::parse_optional_chain(NonnullRefPtr({ m_source_code, start, position() }, private_identifier.value().to_utf8_but_should_be_ported_to_utf16()), + create_ast_node({ m_source_code, start, position() }, private_identifier.fly_string_value()), OptionalChain::Mode::Optional }); break; } @@ -3620,7 +3612,7 @@ NonnullRefPtr Parser::parse_optional_chain(NonnullRefPtr({ m_source_code, start, position() }, identifier.value().to_utf8_but_should_be_ported_to_utf16()), + create_ast_node({ m_source_code, start, position() }, identifier.fly_string_value()), OptionalChain::Mode::Optional, }); } else { @@ -3639,14 +3631,14 @@ NonnullRefPtr Parser::parse_optional_chain(NonnullRefPtr({ m_source_code, start, position() }, private_identifier.value().to_utf8_but_should_be_ported_to_utf16()), + create_ast_node({ m_source_code, start, position() }, private_identifier.fly_string_value()), OptionalChain::Mode::NotOptional, }); } else if (match_identifier_name()) { auto start = position(); auto identifier = consume_and_allow_division(); chain.append(OptionalChain::MemberReference { - create_ast_node({ m_source_code, start, position() }, identifier.value().to_utf8_but_should_be_ported_to_utf16()), + create_ast_node({ m_source_code, start, position() }, identifier.fly_string_value()), OptionalChain::Mode::NotOptional, }); } else { @@ -3835,7 +3827,7 @@ NonnullRefPtr Parser::parse_catch_clause() if (should_expect_parameter && !parameter && !pattern_parameter) expected("an identifier or a binding pattern"); - HashTable bound_names; + HashTable bound_names; if (pattern_parameter) { // NOTE: Nothing in the callback throws an exception. @@ -4511,7 +4503,7 @@ Token Parser::consume(TokenType expected_type) } auto token = expected_type == TokenType::Identifier ? consume_and_allow_division() : consume(); if (expected_type == TokenType::Identifier) { - if (m_state.strict_mode && is_strict_reserved_word(token.value())) + if (m_state.strict_mode && is_strict_reserved_word(token.fly_string_value())) syntax_error(MUST(String::formatted("Identifier must not be a reserved word in strict mode ('{}')", token.value()))); } return token; @@ -4585,19 +4577,6 @@ void Parser::discard_saved_state() m_saved_state.take_last(); } -void Parser::check_identifier_name_for_assignment_validity(FlyString const& name, bool force_strict) -{ - // FIXME: this is now called from multiple places maybe the error message should be dynamic? - if (any_of(s_reserved_words, [&](auto& value) { return name == value; })) { - syntax_error("Binding pattern target may not be a reserved word"_string); - } else if (m_state.strict_mode || force_strict) { - if (name.is_one_of("arguments"sv, "eval"sv)) - syntax_error("Binding pattern target may not be called 'arguments' or 'eval' in strict mode"_string); - else if (is_strict_reserved_word(name)) - syntax_error(MUST(String::formatted("Binding pattern target may not be called '{}' in strict mode", name))); - } -} - void Parser::check_identifier_name_for_assignment_validity(Utf16FlyString const& name, bool force_strict) { // FIXME: this is now called from multiple places maybe the error message should be dynamic? @@ -4611,24 +4590,20 @@ void Parser::check_identifier_name_for_assignment_validity(Utf16FlyString const& } } -FlyString Parser::consume_string_value() +Utf16FlyString Parser::consume_string_value() { VERIFY(match(TokenType::StringLiteral)); auto string_token = consume(); - FlyString value = parse_string_literal(string_token)->value(); + auto value = parse_string_literal(string_token)->value(); // This also checks IsStringWellFormedUnicode which makes sure there is no unpaired surrogate - // Surrogates are at least 3 bytes - if (value.bytes().size() < 3) + if (value.is_empty()) return value; - Utf8View view { value.bytes_as_string_view().substring_view(value.bytes().size() - 3) }; - VERIFY(view.length() <= 3); - auto codepoint = *view.begin(); - if (AK::UnicodeUtils::is_utf16_high_surrogate(codepoint)) { + auto last_code_unit = value.code_unit_at(value.length_in_code_units() - 1); + + if (AK::UnicodeUtils::is_utf16_high_surrogate(last_code_unit)) syntax_error("StringValue ending with unpaired high surrogate"_string); - VERIFY(view.length() == 1); - } return value; } @@ -4640,7 +4615,7 @@ ModuleRequest Parser::parse_module_request() if (!match(TokenType::StringLiteral)) { expected("ModuleSpecifier (string)"); - return ModuleRequest { "!!invalid!!"_fly_string }; + return ModuleRequest { "!!invalid!!"_utf16_fly_string }; } ModuleRequest request { consume_string_value() }; @@ -4652,12 +4627,12 @@ ModuleRequest Parser::parse_module_request() consume(TokenType::CurlyOpen); while (!done() && !match(TokenType::CurlyClose)) { - String key; + Utf16String key; if (match(TokenType::StringLiteral)) { key = parse_string_literal(m_state.current_token)->value(); consume(); } else if (match_identifier_name()) { - key = consume().value().to_utf8_but_should_be_ported_to_utf16(); + key = consume().fly_string_value().to_utf16_string(); } else { expected("IdentifierName or StringValue as WithKey"); consume(); @@ -4685,7 +4660,7 @@ ModuleRequest Parser::parse_module_request() return request; } -static FlyString default_string_value = "default"_fly_string; +static auto default_string_value = "default"_utf16_fly_string; // https://tc39.es/ecma262/#prod-ImportDeclaration NonnullRefPtr Parser::parse_import_statement(Program& program) @@ -4734,8 +4709,8 @@ NonnullRefPtr Parser::parse_import_statement(Program& pro if (match_imported_binding()) { // ImportedDefaultBinding : ImportedBinding auto id_position = position(); - auto bound_name = consume().value().to_utf8_but_should_be_ported_to_utf16(); - entries_with_location.append({ { default_string_value, bound_name }, id_position }); + auto bound_name = consume().fly_string_value(); + entries_with_location.append({ { default_string_value, move(bound_name) }, id_position }); if (match(TokenType::Comma)) { consume(TokenType::Comma); @@ -4757,8 +4732,8 @@ NonnullRefPtr Parser::parse_import_statement(Program& pro if (match_imported_binding()) { auto namespace_position = position(); - auto namespace_name = consume().value().to_utf8_but_should_be_ported_to_utf16(); - entries_with_location.append({ ImportEntry({}, namespace_name), namespace_position }); + auto namespace_name = consume().fly_string_value(); + entries_with_location.append({ ImportEntry({}, move(namespace_name)), namespace_position }); } else { syntax_error(MUST(String::formatted("Unexpected token: {}", m_state.current_token.name()))); } @@ -4773,16 +4748,16 @@ NonnullRefPtr Parser::parse_import_statement(Program& pro // ImportSpecifier : ImportedBinding auto require_as = !match_imported_binding(); auto name_position = position(); - auto name = consume().value().to_utf8_but_should_be_ported_to_utf16(); + auto name = consume().fly_string_value(); if (match_as()) { consume(TokenType::Identifier); auto alias_position = position(); - auto alias = consume_identifier().value().to_utf8_but_should_be_ported_to_utf16(); + auto alias = consume_identifier().fly_string_value(); check_identifier_name_for_assignment_validity(alias); - entries_with_location.append({ { name, alias }, alias_position }); + entries_with_location.append({ { move(name), move(alias) }, alias_position }); } else if (require_as) { syntax_error(MUST(String::formatted("Unexpected reserved word '{}'", name))); } else { @@ -4800,10 +4775,10 @@ NonnullRefPtr Parser::parse_import_statement(Program& pro consume(TokenType::Identifier); auto alias_position = position(); - auto alias = consume_identifier().value().to_utf8_but_should_be_ported_to_utf16(); + auto alias = consume_identifier().fly_string_value(); check_identifier_name_for_assignment_validity(alias); - entries_with_location.append({ { move(name), alias }, alias_position }); + entries_with_location.append({ { move(name), move(alias) }, alias_position }); } else { expected("identifier"); break; @@ -4892,7 +4867,7 @@ NonnullRefPtr Parser::parse_export_statement(Program& pro auto default_position = position(); consume(TokenType::Default); - Optional local_name; + Optional local_name; auto lookahead_token = next_token(); @@ -4992,7 +4967,7 @@ NonnullRefPtr Parser::parse_export_statement(Program& pro } } else { expected("Declaration or assignment expression"); - local_name = "!!invalid!!"_fly_string; + local_name = "!!invalid!!"_utf16_fly_string; } if (!local_name.has_value()) @@ -5006,13 +4981,13 @@ NonnullRefPtr Parser::parse_export_statement(Program& pro Required } check_for_from { FromSpecifier::NotAllowed }; - auto parse_module_export_name = [&](bool lhs) -> FlyString { + auto parse_module_export_name = [&](bool lhs) -> Utf16FlyString { // https://tc39.es/ecma262/#prod-ModuleExportName // ModuleExportName : // IdentifierName // StringLiteral if (match_identifier_name()) { - return consume().value().to_utf8_but_should_be_ported_to_utf16(); + return consume().fly_string_value(); } if (match(TokenType::StringLiteral)) { // It is a Syntax Error if ReferencedBindings of NamedExports contains any StringLiterals. @@ -5139,7 +5114,7 @@ NonnullRefPtr Parser::parse_export_statement(Program& pro for (auto& entry : entries_with_location) { for (auto& export_statement : program.exports()) { - if (export_statement->has_export(entry.entry.export_name.value_or(""_fly_string))) + if (export_statement->has_export(entry.entry.export_name.value_or({}))) syntax_error(MUST(String::formatted("Duplicate export with name: '{}'", entry.entry.export_name)), entry.position); } @@ -5231,7 +5206,7 @@ Parser::ForbiddenTokens Parser::ForbiddenTokens::forbid(std::initializer_list Parser::parse_function_node(u16, Optional const&); template NonnullRefPtr Parser::parse_function_node(u16, Optional const&); -NonnullRefPtr Parser::create_identifier_and_register_in_current_scope(SourceRange range, FlyString string, Optional declaration_kind) +NonnullRefPtr Parser::create_identifier_and_register_in_current_scope(SourceRange range, Utf16FlyString string, Optional declaration_kind) { auto id = create_ast_node(move(range), move(string)); if (m_state.current_scope_pusher) @@ -5239,11 +5214,6 @@ NonnullRefPtr Parser::create_identifier_and_register_in_curren return id; } -NonnullRefPtr Parser::create_identifier_and_register_in_current_scope(SourceRange range, Utf16FlyString const& string, Optional declaration_kind) -{ - return create_identifier_and_register_in_current_scope(move(range), string.view().to_utf8_but_should_be_ported_to_utf16(), declaration_kind); -} - Parser Parser::parse_function_body_from_string(ByteString const& body_string, u16 parse_options, NonnullRefPtr parameters, FunctionKind kind, FunctionParsingInsights& parsing_insights) { RefPtr function_body; diff --git a/Libraries/LibJS/Parser.h b/Libraries/LibJS/Parser.h index 8de9813eb6f..1a2bc9bb16b 100644 --- a/Libraries/LibJS/Parser.h +++ b/Libraries/LibJS/Parser.h @@ -245,7 +245,6 @@ private: Token next_token() const; - void check_identifier_name_for_assignment_validity(FlyString const&, bool force_strict = false); void check_identifier_name_for_assignment_validity(Utf16FlyString const&, bool force_strict = false); bool try_parse_arrow_function_expression_failed_at_position(Position const&) const; @@ -256,7 +255,7 @@ private: bool parse_directive(ScopeNode& body); void parse_statement_list(ScopeNode& output_node, AllowLabelledFunction allow_labelled_functions = AllowLabelledFunction::No); - FlyString consume_string_value(); + Utf16FlyString consume_string_value(); ModuleRequest parse_module_request(); struct RulePosition { @@ -319,8 +318,7 @@ private: ParserState(Lexer, Program::Type); }; - [[nodiscard]] NonnullRefPtr create_identifier_and_register_in_current_scope(SourceRange range, FlyString string, Optional = {}); - [[nodiscard]] NonnullRefPtr create_identifier_and_register_in_current_scope(SourceRange range, Utf16FlyString const& string, Optional = {}); + [[nodiscard]] NonnullRefPtr create_identifier_and_register_in_current_scope(SourceRange range, Utf16FlyString string, Optional = {}); NonnullRefPtr m_source_code; Vector m_rule_starts; diff --git a/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Libraries/LibJS/Runtime/AbstractOperations.cpp index e018127ba04..52bf822bce5 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -771,7 +771,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr if (global_var_environment) { // i. For each element name of varNames, do TRY(program.for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // 1. If varEnv.HasLexicalDeclaration(name) is true, throw a SyntaxError exception. if (global_var_environment->has_lexical_declaration(name)) @@ -793,7 +793,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // 1. NOTE: The environment of with statements cannot contain any lexical declaration so it doesn't need to be checked for var/let hoisting conflicts. // 2. For each element name of varNames, do TRY(program.for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // a. If ! thisEnv.HasBinding(name) is true, then if (MUST(this_environment->has_binding(name))) { @@ -831,7 +831,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // 10. For each element d of varDeclarations, in reverse List order, do TRY(program.for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) -> ThrowCompletionOr { - auto function_name = Utf16FlyString::from_utf8(function.name()); + auto function_name = function.name(); // a. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then // i. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration. @@ -874,7 +874,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // b. For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause Contained within body, do TRY(program.for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) -> ThrowCompletionOr { // i. Let F be StringValue of the BindingIdentifier of f. - auto function_name = Utf16FlyString::from_utf8(function_declaration.name()); + auto function_name = function_declaration.name(); // ii. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for body, then // Note: This is checked during parsing and for_each_function_hoistable_with_annexB_extension so it always passes here. @@ -969,7 +969,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // i. For each String vn of the BoundNames of d, do return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // 1. If vn is not an element of declaredFunctionNames, then if (!declared_function_names.contains(name)) { @@ -1000,7 +1000,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // b. For each element dn of the BoundNames of d, do return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // i. If IsConstantDeclaration of d is true, then if (declaration.is_constant_declaration()) { @@ -1021,7 +1021,7 @@ ThrowCompletionOr eval_declaration_instantiation(VM& vm, Program const& pr // instead of prepending. We append because prepending is much slower // and we only use the created vector here. for (auto const& declaration : functions_to_initialize.in_reverse()) { - auto declaration_name = Utf16FlyString::from_utf8(declaration.name()); + auto declaration_name = declaration.name(); // a. Let fn be the sole element of the BoundNames of f. // b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv. @@ -1178,7 +1178,7 @@ Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Nonnull VERIFY(formals->size() <= NumericLimits::max()); for (i32 index = static_cast(formals->size()) - 1; index >= 0; --index) { // a. Let name be parameterNames[index]. - auto name = Utf16FlyString::from_utf8(formals->parameters()[index].binding.get>()->string()); + auto const& name = formals->parameters()[index].binding.get>()->string(); // b. If name is not an element of mappedNames, then if (seen_names.contains(name)) @@ -1792,7 +1792,7 @@ ThrowCompletionOr perform_import_call(VM& vm, Value specifier, Value opti // 8. Let specifierString be Completion(ToString(specifier)). // 9. IfAbruptRejectPromise(specifierString, promiseCapability). - FlyString specifier_string = TRY_OR_REJECT(vm, promise_capability, specifier.to_string(vm)); + auto specifier_string = TRY_OR_REJECT(vm, promise_capability, specifier.to_utf16_string(vm)); // 10. Let attributes be a new empty List. Vector attributes; @@ -1850,7 +1850,7 @@ ThrowCompletionOr perform_import_call(VM& vm, Value specifier, Value opti } // b. Append the ImportAttribute Record { [[Key]]: key, [[Value]]: value } to attributes. - attributes.empend(key.as_string().utf8_string(), value.as_string().utf8_string()); + attributes.empend(key.as_string().utf16_string(), value.as_string().utf16_string()); } } } diff --git a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index e4273995828..bbf80d89ab4 100644 --- a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -210,7 +210,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( parameter.binding.visit( [&](Identifier const& identifier) { - if (m_parameter_names.set(Utf16FlyString::from_utf8(identifier.string()), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry) + if (m_parameter_names.set(identifier.string(), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry) m_has_duplicates = true; else if (!identifier.is_local()) ++parameters_in_environment; @@ -221,7 +221,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( // NOTE: Nothing in the callback throws an exception. MUST(pattern->for_each_bound_identifier([&](auto& identifier) { - if (m_parameter_names.set(Utf16FlyString::from_utf8(identifier.string()), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry) + if (m_parameter_names.set(identifier.string(), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry) m_has_duplicates = true; else if (!identifier.is_local()) ++parameters_in_environment; @@ -253,9 +253,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( if (scope_body) { // NOTE: Nothing in the callback throws an exception. MUST(scope_body->for_each_var_function_declaration_in_reverse_order([&](FunctionDeclaration const& function) { - auto name = Utf16FlyString::from_utf8(function.name()); - - if (function_names.set(name) == AK::HashSetResult::InsertedNewEntry) + if (function_names.set(function.name()) == AK::HashSetResult::InsertedNewEntry) m_functions_to_initialize.append(function); })); @@ -325,7 +323,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( // c. For each element n of varNames, do MUST(scope_body->for_each_var_declared_identifier([&](Identifier const& id) { // i. If instantiatedVarNames does not contain n, then - if (instantiated_var_names.set(Utf16FlyString::from_utf8(id.string()), id.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) == AK::HashSetResult::InsertedNewEntry) { + if (instantiated_var_names.set(id.string(), id.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) == AK::HashSetResult::InsertedNewEntry) { // 1. Append n to instantiatedVarNames. // Following steps will be executed in function_declaration_instantiation: // 2. Perform ! env.CreateMutableBinding(n, false). @@ -356,7 +354,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( // e. For each element n of varNames, do if (scope_body) { MUST(scope_body->for_each_var_declared_identifier([&](Identifier const& id) { - auto name = Utf16FlyString::from_utf8(id.string()); + auto const& name = id.string(); // 1. Append n to instantiatedVarNames. // Following steps will be executed in function_declaration_instantiation: @@ -380,7 +378,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData( // B.3.2.1 Changes to FunctionDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation if (!m_strict && scope_body) { MUST(scope_body->for_each_function_hoistable_with_annexB_extension([&](FunctionDeclaration& function_declaration) { - auto function_name = Utf16FlyString::from_utf8(function_declaration.name()); + auto function_name = function_declaration.name(); if (parameter_bindings.contains(function_name)) return; diff --git a/Libraries/LibJS/Runtime/ModuleRequest.h b/Libraries/LibJS/Runtime/ModuleRequest.h index 44f2d52a053..7629941d73a 100644 --- a/Libraries/LibJS/Runtime/ModuleRequest.h +++ b/Libraries/LibJS/Runtime/ModuleRequest.h @@ -7,21 +7,21 @@ #pragma once -#include +#include #include #include namespace JS { struct ModuleWithSpecifier { - String specifier; // [[Specifier]] + Utf16String specifier; // [[Specifier]] GC::Ref module; // [[Module]] }; // https://tc39.es/ecma262/#importattribute-record struct ImportAttribute { - String key; - String value; + Utf16String key; + Utf16String value; bool operator==(ImportAttribute const&) const = default; }; @@ -30,19 +30,19 @@ struct ImportAttribute { struct ModuleRequest { ModuleRequest() = default; - explicit ModuleRequest(FlyString specifier) + explicit ModuleRequest(Utf16FlyString specifier) : module_specifier(move(specifier)) { } - ModuleRequest(FlyString specifier, Vector attributes); + ModuleRequest(Utf16FlyString specifier, Vector attributes); - void add_attribute(String key, String value) + void add_attribute(Utf16String key, Utf16String value) { attributes.empend(move(key), move(value)); } - FlyString module_specifier; // [[Specifier]] + Utf16FlyString module_specifier; // [[Specifier]] Vector attributes; // [[Attributes]] bool operator==(ModuleRequest const&) const = default; diff --git a/Libraries/LibJS/Runtime/ShadowRealm.cpp b/Libraries/LibJS/Runtime/ShadowRealm.cpp index d6727ad87e2..92513822146 100644 --- a/Libraries/LibJS/Runtime/ShadowRealm.cpp +++ b/Libraries/LibJS/Runtime/ShadowRealm.cpp @@ -211,7 +211,7 @@ ThrowCompletionOr perform_shadow_realm_eval(VM& vm, Value source, Realm& } // 3.1.4 ShadowRealmImportValue ( specifierString: a String, exportNameString: a String, callerRealm: a Realm Record, evalRealm: a Realm Record, evalContext: an execution context, ), https://tc39.es/proposal-shadowrealm/#sec-shadowrealmimportvalue -ThrowCompletionOr shadow_realm_import_value(VM& vm, String specifier_string, String export_name_string, Realm& caller_realm, Realm& eval_realm) +ThrowCompletionOr shadow_realm_import_value(VM& vm, Utf16FlyString specifier_string, Utf16FlyString export_name_string, Realm& caller_realm, Realm& eval_realm) { auto& realm = *vm.current_realm(); @@ -232,7 +232,7 @@ ThrowCompletionOr shadow_realm_import_value(VM& vm, String specifier_stri auto referrer = GC::Ref { *eval_context->realm }; // 7. Perform HostLoadImportedModule(referrer, specifierString, empty, innerCapability). - vm.host_load_imported_module(referrer, ModuleRequest { specifier_string }, nullptr, inner_capability); + vm.host_load_imported_module(referrer, ModuleRequest { move(specifier_string) }, nullptr, inner_capability); // 7. Suspend evalContext and remove it from the execution context stack. // NOTE: We don't support this concept yet. @@ -242,7 +242,7 @@ ThrowCompletionOr shadow_realm_import_value(VM& vm, String specifier_stri // NOTE: We don't support this concept yet. // 9. Let steps be the steps of an ExportGetter function as described below. - auto steps = [string = Utf16String::from_utf8(export_name_string)](auto& vm) -> ThrowCompletionOr { + auto steps = [string = move(export_name_string)](auto& vm) -> ThrowCompletionOr { // 1. Assert: exports is a module namespace exotic object. VERIFY(vm.argument(0).is_object()); auto& exports = vm.argument(0).as_object(); diff --git a/Libraries/LibJS/Runtime/ShadowRealm.h b/Libraries/LibJS/Runtime/ShadowRealm.h index d14a7a60d5b..d815a11e721 100644 --- a/Libraries/LibJS/Runtime/ShadowRealm.h +++ b/Libraries/LibJS/Runtime/ShadowRealm.h @@ -35,7 +35,7 @@ private: ThrowCompletionOr copy_name_and_length(VM&, FunctionObject& function, FunctionObject& target, Optional prefix = {}, Optional arg_count = {}); ThrowCompletionOr perform_shadow_realm_eval(VM&, Value source, Realm& caller_realm, Realm& eval_realm); -ThrowCompletionOr shadow_realm_import_value(VM&, String specifier_string, String export_name_string, Realm& caller_realm, Realm& eval_realm); +ThrowCompletionOr shadow_realm_import_value(VM&, Utf16FlyString specifier_string, Utf16FlyString export_name_string, Realm& caller_realm, Realm& eval_realm); ThrowCompletionOr get_wrapped_value(VM&, Realm& caller_realm, Value); NonnullOwnPtr get_shadow_realm_context(Realm& shadow_realm, bool strict_eval, u32 registers_and_constants_and_locals_count); diff --git a/Libraries/LibJS/Runtime/ShadowRealmPrototype.cpp b/Libraries/LibJS/Runtime/ShadowRealmPrototype.cpp index 6a3fdf92eca..86f12057b08 100644 --- a/Libraries/LibJS/Runtime/ShadowRealmPrototype.cpp +++ b/Libraries/LibJS/Runtime/ShadowRealmPrototype.cpp @@ -64,7 +64,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::import_value) auto object = TRY(typed_this_object(vm)); // 3. Let specifierString be ? ToString(specifier). - auto specifier_string = TRY(specifier.to_string(vm)); + auto specifier_string = TRY(specifier.to_utf16_string(vm)); // 4. If Type(exportName) is not String, throw a TypeError exception. if (!export_name.is_string()) @@ -77,7 +77,7 @@ JS_DEFINE_NATIVE_FUNCTION(ShadowRealmPrototype::import_value) auto& eval_realm = object->shadow_realm(); // 7. Return ShadowRealmImportValue(specifierString, exportName, callerRealm, evalRealm). - return shadow_realm_import_value(vm, move(specifier_string), export_name.as_string().utf8_string(), *caller_realm, eval_realm); + return shadow_realm_import_value(vm, specifier_string, export_name.as_string().utf16_string(), *caller_realm, eval_realm); } } diff --git a/Libraries/LibJS/Runtime/VM.cpp b/Libraries/LibJS/Runtime/VM.cpp index f6d8e600722..9154b42e56b 100644 --- a/Libraries/LibJS/Runtime/VM.cpp +++ b/Libraries/LibJS/Runtime/VM.cpp @@ -121,7 +121,7 @@ VM::VM(ErrorMessages error_messages) }; host_get_supported_import_attributes = [&] { - return Vector { "type"_string }; + return Vector { "type"_utf16 }; }; // 1 HostGetCodeForEval ( argument ), https://tc39.es/proposal-dynamic-code-brand-checks/#sec-hostgetcodeforeval @@ -523,7 +523,7 @@ ScriptOrModule VM::get_active_script_or_module() const return m_execution_context_stack[0]->script_or_module; } -VM::StoredModule* VM::get_stored_module(ImportedModuleReferrer const&, ByteString const& filename, String const&) +VM::StoredModule* VM::get_stored_module(ImportedModuleReferrer const&, ByteString const& filename, Utf16String const&) { // Note the spec says: // If this operation is called multiple times with the same (referrer, specifier) pair and it performs @@ -582,7 +582,7 @@ ThrowCompletionOr VM::link_and_eval_module(CyclicModule& module) return {}; } -static ByteString resolve_module_filename(StringView filename, StringView module_type) +static ByteString resolve_module_filename(StringView filename, Utf16View const& module_type) { auto extensions = Vector { "js"sv, "mjs"sv }; if (module_type == "json"sv) @@ -635,7 +635,7 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con return; } - String module_type; + Utf16String module_type; for (auto& attribute : module_request.attributes) { if (attribute.key == "type"sv) { module_type = attribute.value; @@ -662,7 +662,7 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con }); LexicalPath base_path { base_filename }; - auto filename = LexicalPath::absolute_path(base_path.dirname(), module_request.module_specifier); + auto filename = LexicalPath::absolute_path(base_path.dirname(), MUST(module_request.module_specifier.view().to_byte_string())); dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] base path: '{}'", base_path); dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] initial filename: '{}'", filename); diff --git a/Libraries/LibJS/Runtime/VM.h b/Libraries/LibJS/Runtime/VM.h index 7c710e8f7b8..a0d19ad3d0f 100644 --- a/Libraries/LibJS/Runtime/VM.h +++ b/Libraries/LibJS/Runtime/VM.h @@ -283,7 +283,7 @@ public: Function(SourceTextModule&)> host_get_import_meta_properties; Function host_finalize_import_meta; - Function()> host_get_supported_import_attributes; + Function()> host_get_supported_import_attributes; void set_dynamic_imports_allowed(bool value) { m_dynamic_imports_allowed = value; } @@ -351,7 +351,7 @@ private: bool has_once_started_linking { false }; }; - StoredModule* get_stored_module(ImportedModuleReferrer const& script_or_module, ByteString const& filename, String const& type); + StoredModule* get_stored_module(ImportedModuleReferrer const& script_or_module, ByteString const& filename, Utf16String const& type); Vector m_loaded_modules; diff --git a/Libraries/LibJS/SourceTextModule.cpp b/Libraries/LibJS/SourceTextModule.cpp index f931994de46..53aa99bf263 100644 --- a/Libraries/LibJS/SourceTextModule.cpp +++ b/Libraries/LibJS/SourceTextModule.cpp @@ -296,7 +296,7 @@ Vector SourceTextModule::get_exported_names(VM& vm, HashTable SourceTextModule::get_exported_names(VM& vm, HashTable SourceTextModule::initialize_environment(VM& vm) VERIFY(entry.export_name.has_value()); // a. Let resolution be module.ResolveExport(e.[[ExportName]]). - auto resolution = resolve_export(vm, Utf16FlyString::from_utf8(entry.export_name.value())); + auto resolution = resolve_export(vm, entry.export_name.value()); // b. If resolution is either null or AMBIGUOUS, throw a SyntaxError exception. if (!resolution.is_valid()) @@ -371,8 +371,6 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) // 7. For each ImportEntry Record in of module.[[ImportEntries]], do for (auto const& import_entry : m_import_entries) { - auto local_name = Utf16FlyString::from_utf8(import_entry.local_name); - // a. Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]). auto imported_module = get_imported_module(import_entry.module_request()); @@ -382,14 +380,14 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) auto namespace_ = imported_module->get_module_namespace(vm); // ii. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true). - MUST(environment->create_immutable_binding(vm, local_name, true)); + MUST(environment->create_immutable_binding(vm, import_entry.local_name, true)); // iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal). - MUST(environment->initialize_binding(vm, local_name, namespace_, Environment::InitializeBindingHint::Normal)); + MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_, Environment::InitializeBindingHint::Normal)); } // c. Else, else { - auto import_name = Utf16FlyString::from_utf8(import_entry.import_name.value()); + auto const& import_name = import_entry.import_name.value(); // i. Let resolution be importedModule.ResolveExport(in.[[ImportName]]). auto resolution = imported_module->resolve_export(vm, import_name); @@ -404,15 +402,15 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) auto namespace_ = resolution.module->get_module_namespace(vm); // 2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true). - MUST(environment->create_immutable_binding(vm, local_name, true)); + MUST(environment->create_immutable_binding(vm, import_entry.local_name, true)); // 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal). - MUST(environment->initialize_binding(vm, local_name, namespace_, Environment::InitializeBindingHint::Normal)); + MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_, Environment::InitializeBindingHint::Normal)); } // iv. Else, else { // 1. Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]). - MUST(environment->create_import_binding(local_name, resolution.module, resolution.export_name)); + MUST(environment->create_import_binding(import_entry.local_name, resolution.module, resolution.export_name)); } } } @@ -458,7 +456,7 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) // NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below, // an exception should not result from `for_each_var_declared_identifier`. MUST(m_ecmascript_code->for_each_var_declared_identifier([&](Identifier const& identifier) { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // i. If dn is not an element of declaredVarNames, then if (!declared_var_names.contains_slow(name)) { @@ -484,7 +482,7 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) MUST(m_ecmascript_code->for_each_lexically_scoped_declaration([&](Declaration const& declaration) { // a. For each element dn of the BoundNames of d, do MUST(declaration.for_each_bound_identifier([&](Identifier const& identifier) { - auto name = Utf16FlyString::from_utf8(identifier.string()); + auto const& name = identifier.string(); // i. If IsConstantDeclaration of d is true, then if (declaration.is_constant_declaration()) { @@ -505,12 +503,12 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) // 1. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv. // NOTE: Special case if the function is a default export of an anonymous function // it has name "*default*" but internally should have name "default". - FlyString function_name = function_declaration.name(); + auto function_name = function_declaration.name(); if (function_name == ExportStatement::local_name_for_default) - function_name = "default"_fly_string; + function_name = "default"_utf16_fly_string; auto function = ECMAScriptFunctionObject::create_from_function_node( function_declaration, - Utf16FlyString::from_utf8(function_name), + move(function_name), realm, environment, private_environment); @@ -528,7 +526,7 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) VERIFY(m_default_export->has_statement()); if (auto const& statement = m_default_export->statement(); !is(statement)) { - auto name = Utf16FlyString::from_utf8(m_default_export->entries()[0].local_or_import_name.value()); + auto const& name = m_default_export->entries()[0].local_or_import_name.value(); dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] Adding default export to lexical declarations: local name: {}, Expression: {}", name, statement.class_name()); // 1. Perform ! env.CreateMutableBinding(dn, false). @@ -581,7 +579,7 @@ ResolvedBinding SourceTextModule::resolve_export(VM& vm, Utf16FlyString const& e return ResolvedBinding { ResolvedBinding::Type::BindingName, this, - Utf16FlyString::from_utf8(entry.local_or_import_name.value()), + entry.local_or_import_name.value(), }; } @@ -613,7 +611,7 @@ ResolvedBinding SourceTextModule::resolve_export(VM& vm, Utf16FlyString const& e // FIXME: What does this mean? / How do we check this // 2. Return importedModule.ResolveExport(e.[[ImportName]], resolveSet). - return imported_module->resolve_export(vm, Utf16FlyString::from_utf8(entry.local_or_import_name.value()), resolve_set); + return imported_module->resolve_export(vm, entry.local_or_import_name.value(), resolve_set); } } diff --git a/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 13b05f61ac4..547f916633f 100644 --- a/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -418,9 +418,9 @@ void initialize_main_thread_vm(AgentType type) }; // 8.1.6.7.2 HostGetSupportedImportAttributes(), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetsupportedimportassertions - s_main_thread_vm->host_get_supported_import_attributes = []() -> Vector { + s_main_thread_vm->host_get_supported_import_attributes = []() -> Vector { // 1. Return « "type" ». - return { "type"_string }; + return { "type"_utf16 }; }; // 8.1.6.7.3 HostLoadImportedModule(referrer, moduleRequest, loadState, payload), https://html.spec.whatwg.org/multipage/webappapis.html#hostloadimportedmodule @@ -494,7 +494,7 @@ void initialize_main_thread_vm(AgentType type) // 2. Resolve a module specifier given referencingScript and moduleRequest.[[Specifier]], catching any // exceptions. If they throw an exception, let resolutionError be the thrown exception. - auto maybe_exception = HTML::resolve_module_specifier(referencing_script, module_request.module_specifier.to_string()); + auto maybe_exception = HTML::resolve_module_specifier(referencing_script, module_request.module_specifier.view().to_utf8_but_should_be_ported_to_utf16()); // 3. If the previous step threw an exception, then: if (maybe_exception.is_exception()) { @@ -544,7 +544,7 @@ void initialize_main_thread_vm(AgentType type) // 8. Let url be the result of resolving a module specifier given referencingScript and moduleRequest.[[Specifier]], // catching any exceptions. If they throw an exception, let resolutionError be the thrown exception. - auto url = HTML::resolve_module_specifier(referencing_script, module_request.module_specifier.to_string()); + auto url = HTML::resolve_module_specifier(referencing_script, module_request.module_specifier.view().to_utf8_but_should_be_ported_to_utf16()); // 9. If the previous step threw an exception, then: if (url.is_exception()) { diff --git a/Libraries/LibWeb/HTML/Scripting/Fetching.cpp b/Libraries/LibWeb/HTML/Scripting/Fetching.cpp index 38a6f277a50..47f4fbda691 100644 --- a/Libraries/LibWeb/HTML/Scripting/Fetching.cpp +++ b/Libraries/LibWeb/HTML/Scripting/Fetching.cpp @@ -76,7 +76,7 @@ String module_type_from_module_request(JS::ModuleRequest const& module_request) module_type = ""_string; // FIXME: This should be null! // 2. Otherwise, set moduleType to entry.[[Value]]. else - module_type = entry.value; + module_type = entry.value.to_utf8_but_should_be_ported_to_utf16(); } // 3. Return moduleType.