LibJS+LibWeb+WebContent: Port JS::PropertyKey to UTF-16

This has quite a lot of fall out. But the majority of it is just type or
UDL substitution, where the changes just fall through to other function
calls.

By changing property key storage to UTF-16, the main affected areas are:
* NativeFunction names must now be UTF-16
* Bytecode identifiers must now be UTF-16
* Module/binding names must now be UTF-16
This commit is contained in:
Timothy Flynn 2025-08-02 19:27:29 -04:00 committed by Tim Flynn
parent cd276235d7
commit 0efa98a57a
131 changed files with 766 additions and 726 deletions

View File

@ -64,7 +64,7 @@ static void print_indent(int indent)
out("{}", ByteString::repeated(' ', indent * 2));
}
static void update_function_name(Value value, FlyString const& name)
static void update_function_name(Value value, Utf16FlyString const& name)
{
if (!value.is_function())
return;
@ -88,20 +88,23 @@ void LabelledStatement::dump(int indent) const
}
// 15.2.5 Runtime Semantics: InstantiateOrdinaryFunctionExpression, https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, FlyString given_name) const
Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, Utf16FlyString given_name) const
{
auto& realm = *vm.current_realm();
if (given_name.is_empty())
given_name = ""_fly_string;
given_name = Utf16FlyString {};
auto has_own_name = !name().is_empty();
auto const used_name = has_own_name ? name() : given_name;
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 };
if (has_own_name) {
VERIFY(environment);
environment = new_declarative_environment(*environment);
MUST(environment->create_immutable_binding(vm, name(), false));
MUST(environment->create_immutable_binding(vm, own_name, false));
}
auto private_environment = vm.running_execution_context().private_environment;
@ -112,7 +115,7 @@ Value FunctionExpression::instantiate_ordinary_function_expression(VM& vm, FlySt
// FIXME: 7. Perform MakeConstructor(closure).
if (has_own_name)
MUST(environment->initialize_binding(vm, name(), closure, Environment::InitializeBindingHint::Normal));
MUST(environment->initialize_binding(vm, own_name, closure, Environment::InitializeBindingHint::Normal));
return closure;
}
@ -134,7 +137,7 @@ static ThrowCompletionOr<ClassElementName> class_key_to_property_name(VM& vm, Ex
auto& private_identifier = static_cast<PrivateIdentifier const&>(key);
auto private_environment = vm.running_execution_context().private_environment;
VERIFY(private_environment);
return ClassElementName { private_environment->resolve_private_identifier(private_identifier.string()) };
return ClassElementName { private_environment->resolve_private_identifier(Utf16FlyString::from_utf8(private_identifier.string())) };
}
VERIFY(!prop_key.is_special_empty_value());
@ -153,7 +156,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
auto& method_function = *ECMAScriptFunctionObject::create_from_function_node(
*m_function,
m_function->name(),
Utf16String::from_utf8(m_function->name()),
*vm.current_realm(),
vm.lexical_environment(),
vm.running_execution_context().private_environment);
@ -161,22 +164,22 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
auto method_value = Value(&method_function);
method_function.make_method(target);
auto set_function_name = [&](ByteString prefix = "") {
auto set_function_name = [&](StringView prefix = {}) {
auto name = property_key_or_private_name.visit(
[&](PropertyKey const& property_key) -> String {
[&](PropertyKey const& property_key) {
if (property_key.is_symbol()) {
auto description = property_key.as_symbol()->description();
if (!description.has_value() || description->is_empty())
return ""_string;
return MUST(String::formatted("[{}]", *description));
return Utf16String {};
return Utf16String::formatted("[{}]", *description);
}
return property_key.to_string();
},
[&](PrivateName const& private_name) -> String {
return private_name.description.to_string();
[&](PrivateName const& private_name) {
return private_name.description.to_utf16_string();
});
update_function_name(method_value, MUST(String::formatted("{}{}{}", prefix, prefix.is_empty() ? "" : " ", name)));
update_function_name(method_value, Utf16String::formatted("{}{}{}", prefix, prefix.is_empty() ? "" : " ", name));
};
if (property_key_or_private_name.has<PropertyKey>()) {
@ -187,11 +190,11 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
break;
case ClassMethod::Kind::Getter:
set_function_name("get");
set_function_name("get"sv);
TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true }));
break;
case ClassMethod::Kind::Setter:
set_function_name("set");
set_function_name("set"sv);
TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true }));
break;
default:
@ -206,10 +209,10 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
set_function_name();
return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Method, method_value } };
case Kind::Getter:
set_function_name("get");
set_function_name("get"sv);
return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Accessor, Value(Accessor::create(vm, &method_function, nullptr)) } };
case Kind::Setter:
set_function_name("set");
set_function_name("set"sv);
return ClassValue { PrivateElement { private_name, PrivateElement::Kind::Accessor, Value(Accessor::create(vm, nullptr, &method_function)) } };
default:
VERIFY_NOT_REACHED();
@ -242,19 +245,19 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
} else {
auto copy_initializer = m_initializer;
auto name = property_key_or_private_name.visit(
[&](PropertyKey const& property_key) -> String {
[&](PropertyKey const& property_key) {
return property_key.to_string();
},
[&](PrivateName const& private_name) -> String {
return private_name.description.to_string();
[&](PrivateName const& private_name) {
return private_name.description.to_utf16_string();
});
// FIXME: A potential optimization is not creating the functions here since these are never directly accessible.
auto function_code = create_ast_node<ClassFieldInitializerStatement>(m_initializer->source_range(), copy_initializer.release_nonnull(), name);
auto function_code = create_ast_node<ClassFieldInitializerStatement>(m_initializer->source_range(), copy_initializer.release_nonnull(), name.to_utf8_but_should_be_ported_to_utf16());
FunctionParsingInsights parsing_insights;
parsing_insights.uses_this_from_environment = true;
parsing_insights.uses_this = true;
auto function = ECMAScriptFunctionObject::create(realm, "field"_string, ByteString::empty(), *function_code, FunctionParameters::empty(), 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, parsing_insights, false, property_key_or_private_name);
auto function = ECMAScriptFunctionObject::create(realm, "field"_utf16_fly_string, ByteString::empty(), *function_code, FunctionParameters::empty(), 0, {}, vm.lexical_environment(), vm.running_execution_context().private_environment, FunctionKind::Normal, true, parsing_insights, false, property_key_or_private_name);
function->make_method(target);
initializer = function;
}
@ -303,7 +306,7 @@ ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_eva
FunctionParsingInsights parsing_insights;
parsing_insights.uses_this_from_environment = true;
parsing_insights.uses_this = true;
auto body_function = ECMAScriptFunctionObject::create(realm, ""_string, ByteString::empty(), *m_function_body, FunctionParameters::empty(), 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false);
auto body_function = ECMAScriptFunctionObject::create(realm, {}, ByteString::empty(), *m_function_body, FunctionParameters::empty(), 0, m_function_body->local_variables_names(), lexical_environment, private_environment, FunctionKind::Normal, true, parsing_insights, false);
// 6. Perform MakeMethod(bodyFunction, homeObject).
body_function->make_method(home_object);
@ -312,7 +315,7 @@ ThrowCompletionOr<ClassElement::ClassValue> StaticInitializer::class_element_eva
return ClassValue { normal_completion(body_function) };
}
ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_constructor(VM& vm, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<FlyString> const& binding_name, FlyString const& class_name) const
ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_constructor(VM& vm, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<Utf16FlyString> const& binding_name, Utf16FlyString const& class_name) const
{
auto& realm = *vm.current_realm();
@ -352,7 +355,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> ClassExpression::create_class_const
auto const& constructor = *m_constructor;
auto class_constructor = ECMAScriptFunctionObject::create_from_function_node(
constructor,
constructor.name(),
Utf16FlyString::from_utf8(constructor.name()),
realm,
vm.lexical_environment(),
vm.running_execution_context().private_environment);
@ -1632,13 +1635,14 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment
// NOTE: Due to the use of MUST with `create_immutable_binding` and `create_mutable_binding` below,
// an exception should not result from `for_each_bound_name`.
// a. For each element dn of the BoundNames of d, do
MUST(declaration.for_each_bound_identifier([&](auto const& identifier) {
MUST(declaration.for_each_bound_identifier([&](Identifier const& identifier) {
if (identifier.is_local()) {
// NOTE: No need to create bindings for local variables as their values are not stored in an environment.
return;
}
auto const& name = identifier.string();
auto name = Utf16FlyString::from_utf8(identifier.string());
// i. If IsConstantDeclaration of d is true, then
if (is_constant_declaration) {
// 1. Perform ! env.CreateImmutableBinding(dn, true).
@ -1660,7 +1664,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,
function_declaration.name(),
Utf16FlyString::from_utf8(function_declaration.name()),
realm,
environment,
private_environment);
@ -1678,7 +1682,7 @@ void ScopeNode::block_declaration_instantiation(VM& vm, Environment* environment
}
} else {
VERIFY(is<DeclarativeEnvironment>(*environment));
static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function_declaration.name(), function);
static_cast<DeclarativeEnvironment&>(*environment).initialize_or_set_mutable_binding({}, vm, function->name(), function);
}
}
}));
@ -1693,7 +1697,7 @@ ThrowCompletionOr<void> 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<void> {
auto const& name = identifier.string();
auto name = Utf16FlyString::from_utf8(identifier.string());
// a. If HasLexicalDeclaration(env, name) is true, throw a SyntaxError exception.
if (global_environment.has_lexical_declaration(name))
@ -1713,9 +1717,9 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
}));
// 4. For each element name of varNames, do
TRY(for_each_var_declared_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> {
TRY(for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
// a. If env.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
if (global_environment.has_lexical_declaration(identifier.string()))
if (global_environment.has_lexical_declaration(Utf16FlyString::from_utf8(identifier.string())))
return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, identifier.string());
return {};
@ -1726,11 +1730,13 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
Vector<FunctionDeclaration const&> functions_to_initialize;
// 7. Let declaredFunctionNames be a new empty List.
HashTable<FlyString> declared_function_names;
HashTable<Utf16FlyString> declared_function_names;
// 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<void> {
auto function_name = Utf16FlyString::from_utf8(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.
// Note: This is checked in for_each_var_function_declaration_in_reverse_order.
@ -1740,11 +1746,11 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
// iii. Let fn be the sole element of the BoundNames of d.
// iv. If fn is not an element of declaredFunctionNames, then
if (declared_function_names.set(function.name()) != AK::HashSetResult::InsertedNewEntry)
if (declared_function_names.set(function_name) != AK::HashSetResult::InsertedNewEntry)
return {};
// 1. Let fnDefinable be ? env.CanDeclareGlobalFunction(fn).
auto function_definable = TRY(global_environment.can_declare_global_function(function.name()));
auto function_definable = TRY(global_environment.can_declare_global_function(function_name));
// 2. If fnDefinable is false, throw a TypeError exception.
if (!function_definable)
@ -1761,7 +1767,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
}));
// 9. Let declaredVarNames be a new empty List.
HashTable<FlyString> declared_var_names;
HashTable<Utf16FlyString> declared_var_names;
// 10. For each element d of varDeclarations, do
TRY(for_each_var_scoped_variable_declaration([&](Declaration const& declaration) {
@ -1769,8 +1775,9 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
// Note: This is done in for_each_var_scoped_variable_declaration.
// i. For each String vn of the BoundNames of d, do
return declaration.for_each_bound_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> {
auto const& name = identifier.string();
return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// 1. If vn is not an element of declaredFunctionNames, then
if (declared_function_names.contains(name))
return {};
@ -1799,7 +1806,7 @@ ThrowCompletionOr<void> 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<void> {
// i. Let F be StringValue of the BindingIdentifier of f.
auto function_name = function_declaration.name();
auto function_name = Utf16FlyString::from_utf8(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.
@ -1850,8 +1857,9 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(VM& vm, Global
TRY(for_each_lexically_scoped_declaration([&](Declaration const& declaration) {
// 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([&](auto const& identifier) -> ThrowCompletionOr<void> {
auto const& name = identifier.string();
return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) {
// 1. Perform ? env.CreateImmutableBinding(dn, true).
@ -1876,13 +1884,13 @@ ThrowCompletionOr<void> 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,
declaration.name(),
Utf16FlyString::from_utf8(declaration.name()),
realm,
&global_environment,
private_environment);
// c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false).
TRY(global_environment.create_global_function_binding(declaration.name(), function, false));
TRY(global_environment.create_global_function_binding(function->name(), function, false));
}
// 17. For each String vn of declaredVarNames, do

View File

@ -797,7 +797,7 @@ public:
bool uses_this_from_environment() const { return m_parsing_insights.uses_this_from_environment; }
virtual bool has_name() const = 0;
virtual Value instantiate_ordinary_function_expression(VM&, FlyString given_name) const = 0;
virtual Value instantiate_ordinary_function_expression(VM&, Utf16FlyString given_name) const = 0;
RefPtr<SharedFunctionInstanceData> shared_data() const;
void set_shared_data(RefPtr<SharedFunctionInstanceData>) const;
@ -847,7 +847,7 @@ public:
void set_should_do_additional_annexB_steps() { m_is_hoisted = true; }
bool has_name() const override { return true; }
Value instantiate_ordinary_function_expression(VM&, FlyString) const override { VERIFY_NOT_REACHED(); }
Value instantiate_ordinary_function_expression(VM&, Utf16FlyString) const override { VERIFY_NOT_REACHED(); }
virtual ~FunctionDeclaration() { }
@ -874,7 +874,7 @@ public:
bool has_name() const override { return !name().is_empty(); }
Value instantiate_ordinary_function_expression(VM&, FlyString given_name) const override;
Value instantiate_ordinary_function_expression(VM&, Utf16FlyString given_name) const override;
virtual ~FunctionExpression() { }
@ -1518,7 +1518,7 @@ public:
bool has_name() const { return m_name; }
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<FlyString> const& binding_name = {}, FlyString const& class_name = {}) const;
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, ReadonlySpan<Value> element_keys, Optional<Utf16FlyString> const& binding_name = {}, Utf16FlyString const& class_name = {}) const;
private:
virtual bool is_class_expression() const override { return true; }

View File

@ -6,10 +6,10 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/OwnPtr.h>
#include <AK/Utf16FlyString.h>
#include <AK/WeakPtr.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Bytecode/IdentifierTable.h>
@ -67,7 +67,7 @@ public:
virtual ~Executable() override;
FlyString name;
Utf16FlyString name;
Vector<u8> bytecode;
Vector<PropertyLookupCache> property_lookup_caches;
Vector<GlobalVariableCache> global_variable_caches;
@ -99,9 +99,9 @@ public:
Optional<IdentifierTableIndex> length_identifier;
String const& get_string(StringTableIndex index) const { return string_table->get(index); }
FlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
Utf16FlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
Optional<FlyString const&> get_identifier(Optional<IdentifierTableIndex> const& index) const
Optional<Utf16FlyString const&> get_identifier(Optional<IdentifierTableIndex> const& index) const
{
if (!index.has_value())
return {};

View File

@ -212,7 +212,12 @@ public:
return m_regex_table->insert(move(regex));
}
IdentifierTableIndex intern_identifier(FlyString string)
IdentifierTableIndex intern_identifier(FlyString const& string)
{
return intern_identifier(Utf16FlyString::from_utf8(string));
}
IdentifierTableIndex intern_identifier(Utf16FlyString string)
{
return m_identifier_table->insert(move(string));
}

View File

@ -8,14 +8,14 @@
namespace JS::Bytecode {
IdentifierTableIndex IdentifierTable::insert(FlyString string)
IdentifierTableIndex IdentifierTable::insert(Utf16FlyString string)
{
m_identifiers.append(move(string));
VERIFY(m_identifiers.size() <= NumericLimits<u32>::max());
return { static_cast<u32>(m_identifiers.size() - 1) };
}
FlyString const& IdentifierTable::get(IdentifierTableIndex index) const
Utf16FlyString const& IdentifierTable::get(IdentifierTableIndex index) const
{
return m_identifiers[index.value];
}

View File

@ -7,7 +7,7 @@
#pragma once
#include <AK/DistinctNumeric.h>
#include <AK/FlyString.h>
#include <AK/Utf16FlyString.h>
#include <AK/Vector.h>
namespace JS::Bytecode {
@ -25,13 +25,13 @@ class IdentifierTable {
public:
IdentifierTable() = default;
IdentifierTableIndex insert(FlyString);
FlyString const& get(IdentifierTableIndex) const;
IdentifierTableIndex insert(Utf16FlyString);
Utf16FlyString const& get(IdentifierTableIndex) const;
void dump() const;
bool is_empty() const { return m_identifiers.is_empty(); }
private:
Vector<FlyString> m_identifiers;
Vector<Utf16FlyString> m_identifiers;
};
}

View File

@ -821,7 +821,7 @@ void Interpreter::enter_object_environment(Object& object)
running_execution_context().lexical_environment = new_object_environment(object, true, old_environment);
}
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, FlyString const& name)
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM& vm, ASTNode const& node, FunctionKind kind, Utf16FlyString const& name)
{
auto executable_result = Bytecode::Generator::generate_from_ast_node(vm, node, kind);
if (executable_result.is_error())
@ -1201,7 +1201,7 @@ inline ThrowCompletionOr<Value> get_global(Interpreter& interpreter, IdentifierT
return vm.throw_completion<ReferenceError>(ErrorType::UnknownIdentifier, identifier);
}
inline ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value, Value value, Optional<FlyString const&> const& base_identifier, PropertyKey name, Op::PropertyKind kind, PropertyLookupCache* caches = nullptr)
inline ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value, Value value, Optional<Utf16FlyString const&> const& base_identifier, PropertyKey name, Op::PropertyKind kind, PropertyLookupCache* caches = nullptr)
{
// Better error message than to_object would give
if (vm.in_strict_mode() && base.is_nullish())
@ -1221,14 +1221,14 @@ inline ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value thi
case Op::PropertyKind::Getter: {
auto& function = value.as_function();
if (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject const&>(function).name().is_empty())
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("get {}", name)));
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(Utf16String::formatted("get {}", name));
object->define_direct_accessor(name, &function, nullptr, Attribute::Configurable | Attribute::Enumerable);
break;
}
case Op::PropertyKind::Setter: {
auto& function = value.as_function();
if (is<ECMAScriptFunctionObject>(function) && static_cast<ECMAScriptFunctionObject const&>(function).name().is_empty())
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(MUST(String::formatted("set {}", name)));
static_cast<ECMAScriptFunctionObject*>(&function)->set_name(Utf16String::formatted("set {}", name));
object->define_direct_accessor(name, nullptr, &function, Attribute::Configurable | Attribute::Enumerable);
break;
}
@ -1354,14 +1354,14 @@ inline Value new_function(VM& vm, FunctionNode const& function_node, Optional<Id
Value value;
if (!function_node.has_name()) {
FlyString name;
Utf16FlyString name;
if (lhs_name.has_value())
name = vm.bytecode_interpreter().current_executable().get_identifier(lhs_name.value());
value = function_node.instantiate_ordinary_function_expression(vm, name);
} else {
value = ECMAScriptFunctionObject::create_from_function_node(
function_node,
function_node.name(),
Utf16FlyString::from_utf8(function_node.name()),
*vm.current_realm(),
vm.lexical_environment(),
vm.running_execution_context().private_environment);
@ -1375,7 +1375,7 @@ inline Value new_function(VM& vm, FunctionNode const& function_node, Optional<Id
return value;
}
inline ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Optional<FlyString const&> const& base_identifier, Value property_key_value, Value value, Op::PropertyKind kind)
inline ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Optional<Utf16FlyString const&> const& base_identifier, Value property_key_value, Value value, Op::PropertyKind kind)
{
// OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects.
if ((kind == Op::PropertyKind::KeyValue || kind == Op::PropertyKind::DirectKeyValue)
@ -1496,7 +1496,7 @@ struct CalleeAndThis {
Value this_value;
};
inline ThrowCompletionOr<CalleeAndThis> get_callee_and_this_from_environment(Bytecode::Interpreter& interpreter, FlyString const& name, EnvironmentCoordinate& cache)
inline ThrowCompletionOr<CalleeAndThis> get_callee_and_this_from_environment(Bytecode::Interpreter& interpreter, Utf16FlyString const& name, EnvironmentCoordinate& cache)
{
auto& vm = interpreter.vm();
@ -1583,7 +1583,7 @@ inline Span<Value> argument_list_evaluation(Interpreter& interpreter, Value argu
return argument_values;
}
inline ThrowCompletionOr<void> create_variable(VM& vm, FlyString const& name, Op::EnvironmentMode mode, bool is_global, bool is_immutable, bool is_strict)
inline ThrowCompletionOr<void> create_variable(VM& vm, Utf16FlyString const& name, Op::EnvironmentMode mode, bool is_global, bool is_immutable, bool is_strict)
{
if (mode == Op::EnvironmentMode::Lexical) {
VERIFY(!is_global);
@ -1612,17 +1612,17 @@ inline ThrowCompletionOr<void> create_variable(VM& vm, FlyString const& name, Op
inline ThrowCompletionOr<ECMAScriptFunctionObject*> new_class(VM& vm, Value super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> const& lhs_name, ReadonlySpan<Value> element_keys)
{
auto& interpreter = vm.bytecode_interpreter();
auto name = class_expression.name();
// NOTE: NewClass expects classEnv to be active lexical environment
auto* class_environment = vm.lexical_environment();
vm.running_execution_context().lexical_environment = vm.running_execution_context().saved_lexical_environments.take_last();
Optional<FlyString> binding_name;
FlyString class_name;
Optional<Utf16FlyString> binding_name;
Utf16FlyString class_name;
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;
}

View File

@ -107,7 +107,7 @@ private:
JS_API extern bool g_dump_bytecode;
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ASTNode const&, JS::FunctionKind kind, FlyString const& name);
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ASTNode const&, JS::FunctionKind kind, Utf16FlyString const& name);
ThrowCompletionOr<GC::Ref<Bytecode::Executable>> compile(VM&, ECMAScriptFunctionObject const&);
}

View File

@ -172,7 +172,7 @@ static ThrowCompletionOr<GC::Ref<Object>> create_table_row(Realm& realm, Value r
// 2. Set `row["(index)"]` to `rowIndex`
{
auto key = PropertyKey { "(index)"_fly_string, PropertyKey::StringMayBeNumber::No };
auto key = PropertyKey { "(index)"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
TRY(row->set(key, row_index, Object::ShouldThrowExceptions::No));
add_column(key);

View File

@ -36,15 +36,15 @@ void $262Object::initialize(Realm& realm)
m_is_htmldda = realm.create<IsHTMLDDA>(realm);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, "clearKeptObjects"_fly_string, clear_kept_objects, 0, attr);
define_native_function(realm, "createRealm"_fly_string, create_realm, 0, attr);
define_native_function(realm, "detachArrayBuffer"_fly_string, detach_array_buffer, 1, attr);
define_native_function(realm, "evalScript"_fly_string, eval_script, 1, attr);
define_native_function(realm, "clearKeptObjects"_utf16_fly_string, clear_kept_objects, 0, attr);
define_native_function(realm, "createRealm"_utf16_fly_string, create_realm, 0, attr);
define_native_function(realm, "detachArrayBuffer"_utf16_fly_string, detach_array_buffer, 1, attr);
define_native_function(realm, "evalScript"_utf16_fly_string, eval_script, 1, attr);
define_direct_property("agent"_fly_string, m_agent, attr);
define_direct_property("gc"_fly_string, realm.global_object().get_without_side_effects("gc"_fly_string), attr);
define_direct_property("global"_fly_string, &realm.global_object(), attr);
define_direct_property("IsHTMLDDA"_fly_string, m_is_htmldda, attr);
define_direct_property("agent"_utf16_fly_string, m_agent, attr);
define_direct_property("gc"_utf16_fly_string, realm.global_object().get_without_side_effects("gc"_utf16_fly_string), attr);
define_direct_property("global"_utf16_fly_string, &realm.global_object(), attr);
define_direct_property("IsHTMLDDA"_utf16_fly_string, m_is_htmldda, attr);
}
void $262Object::visit_edges(Cell::Visitor& visitor)

View File

@ -24,8 +24,8 @@ void AgentObject::initialize(JS::Realm& realm)
Base::initialize(realm);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, "monotonicNow"_fly_string, monotonic_now, 0, attr);
define_native_function(realm, "sleep"_fly_string, sleep, 1, attr);
define_native_function(realm, "monotonicNow"_utf16_fly_string, monotonic_now, 0, attr);
define_native_function(realm, "sleep"_utf16_fly_string, sleep, 1, attr);
// TODO: broadcast
// TODO: getReport
// TODO: start

View File

@ -24,8 +24,8 @@ void GlobalObject::initialize(Realm& realm)
// https://github.com/tc39/test262/blob/master/INTERPRETING.md#host-defined-functions
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, "print"_fly_string, print, 1, attr);
define_direct_property("$262"_fly_string, m_$262, attr);
define_native_function(realm, "print"_utf16_fly_string, print, 1, attr);
define_direct_property("$262"_utf16_fly_string, m_$262, attr);
}
void GlobalObject::visit_edges(Cell::Visitor& visitor)

View File

@ -13,7 +13,7 @@ GC_DEFINE_ALLOCATOR(IsHTMLDDA);
IsHTMLDDA::IsHTMLDDA(Realm& realm)
// NativeFunction without prototype is currently not possible (only due to the lack of a ctor that supports it)
: NativeFunction("IsHTMLDDA"_fly_string, realm.intrinsics().function_prototype())
: NativeFunction("IsHTMLDDA"_utf16_fly_string, realm.intrinsics().function_prototype())
{
}

View File

@ -124,7 +124,7 @@ ErrorOr<void> MarkupGenerator::object_to_html(Object const& object, StringBuilde
size_t index = 0;
for (auto& it : object.shape().property_table()) {
TRY(html_output.try_append(TRY(wrap_string_in_style(TRY(String::formatted("\"{}\"", escape_html_entities(it.key.to_string()))), StyleType::String))));
TRY(html_output.try_append(TRY(wrap_string_in_style(TRY(String::formatted("\"{}\"", it.key.to_string().escape_html_entities())), StyleType::String))));
TRY(html_output.try_append(TRY(wrap_string_in_style(": "sv, StyleType::Punctuation))));
TRY(value_to_html(object.get_direct(it.value.offset), html_output, seen_objects));
if (index != object.shape().property_count() - 1)

View File

@ -155,7 +155,7 @@ GC::Ref<Object> Module::get_module_namespace(VM& vm)
auto exported_names = get_exported_names(vm);
// b. Let unambiguousNames be a new empty List.
Vector<FlyString> unambiguous_names;
Vector<Utf16FlyString> unambiguous_names;
// c. For each element name of exportedNames, do
for (auto& name : exported_names) {
@ -175,14 +175,14 @@ GC::Ref<Object> Module::get_module_namespace(VM& vm)
return *namespace_;
}
Vector<FlyString> Module::get_exported_names(VM& vm)
Vector<Utf16FlyString> Module::get_exported_names(VM& vm)
{
HashTable<Module const*> export_star_set;
return get_exported_names(vm, export_star_set);
}
// 10.4.6.12 ModuleNamespaceCreate ( module, exports ), https://tc39.es/ecma262/#sec-modulenamespacecreate
GC::Ref<Object> Module::module_namespace_create(Vector<FlyString> unambiguous_names)
GC::Ref<Object> Module::module_namespace_create(Vector<Utf16FlyString> unambiguous_names)
{
auto& realm = this->realm();

View File

@ -7,7 +7,7 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/Utf16FlyString.h>
#include <LibGC/Ptr.h>
#include <LibJS/Export.h>
#include <LibJS/ModuleLoading.h>
@ -39,7 +39,7 @@ struct ResolvedBinding {
Type type { Null };
GC::Ptr<Module> module;
FlyString export_name;
Utf16FlyString export_name;
bool is_valid() const
{
@ -110,10 +110,10 @@ public:
virtual ThrowCompletionOr<void> link(VM& vm) = 0;
virtual ThrowCompletionOr<GC::Ref<Promise>> evaluate(VM& vm) = 0;
Vector<FlyString> get_exported_names(VM& vm);
virtual Vector<FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) = 0;
Vector<Utf16FlyString> get_exported_names(VM& vm);
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) = 0;
virtual ResolvedBinding resolve_export(VM& vm, FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) = 0;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) = 0;
virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index);
virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index);
@ -131,7 +131,7 @@ protected:
}
private:
GC::Ref<Object> module_namespace_create(Vector<FlyString> unambiguous_names);
GC::Ref<Object> module_namespace_create(Vector<Utf16FlyString> unambiguous_names);
ThrowCompletionOr<void> evaluate_module_sync(VM&);
// These handles are only safe as long as the VM they live in is valid.

View File

@ -225,7 +225,7 @@ ThrowCompletionOr<Realm*> get_function_realm(VM& vm, FunctionObject const& funct
}
// 8.5.2.1 InitializeBoundName ( name, value, environment ), https://tc39.es/ecma262/#sec-initializeboundname
ThrowCompletionOr<void> initialize_bound_name(VM& vm, FlyString const& name, Value value, Environment* environment)
ThrowCompletionOr<void> initialize_bound_name(VM& vm, Utf16FlyString const& name, Value value, Environment* environment)
{
// 1. If environment is not undefined, then
if (environment) {
@ -252,7 +252,7 @@ ThrowCompletionOr<void> initialize_bound_name(VM& vm, FlyString const& name, Val
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
{
// 1. Return ValidateAndApplyPropertyDescriptor(undefined, "", Extensible, Desc, Current).
return validate_and_apply_property_descriptor(nullptr, FlyString {}, extensible, descriptor, current);
return validate_and_apply_property_descriptor(nullptr, Utf16FlyString {}, extensible, descriptor, current);
}
// 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ), https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
@ -701,7 +701,7 @@ ThrowCompletionOr<Value> perform_eval(VM& vm, Value x, CallerMode strict_caller,
if (executable_result.is_error())
return vm.throw_completion<InternalError>(ErrorType::NotImplemented, TRY_OR_THROW_OOM(vm, executable_result.error().to_string()));
auto executable = executable_result.release_value();
executable->name = "eval"_fly_string;
executable->name = "eval"_utf16_fly_string;
if (Bytecode::g_dump_bytecode)
executable->dump();
@ -770,9 +770,11 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// a. If varEnv is a global Environment Record, then
if (global_var_environment) {
// i. For each element name of varNames, do
TRY(program.for_each_var_declared_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> {
TRY(program.for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// 1. If varEnv.HasLexicalDeclaration(name) is true, throw a SyntaxError exception.
if (global_var_environment->has_lexical_declaration(identifier.string()))
if (global_var_environment->has_lexical_declaration(name))
return vm.throw_completion<SyntaxError>(ErrorType::TopLevelVariableAlreadyDeclared, identifier.string());
// 2. NOTE: eval will not create a global var declaration that would be shadowed by a global lexical declaration.
@ -790,8 +792,9 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
if (!is<ObjectEnvironment>(*this_environment)) {
// 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([&](auto const& identifier) -> ThrowCompletionOr<void> {
auto const& name = identifier.string();
TRY(program.for_each_var_declared_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// a. If ! thisEnv.HasBinding(name) is true, then
if (MUST(this_environment->has_binding(name))) {
// i. Throw a SyntaxError exception.
@ -824,10 +827,12 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
Vector<FunctionDeclaration const&> functions_to_initialize;
// 9. Let declaredFunctionNames be a new empty List.
HashTable<FlyString> declared_function_names;
HashTable<Utf16FlyString> declared_function_names;
// 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<void> {
auto function_name = Utf16FlyString::from_utf8(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.
// Note: This is done by for_each_var_function_declaration_in_reverse_order.
@ -835,18 +840,17 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// ii. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
// iii. Let fn be the sole element of the BoundNames of d.
// iv. If fn is not an element of declaredFunctionNames, then
if (declared_function_names.set(function.name()) != AK::HashSetResult::InsertedNewEntry)
if (declared_function_names.set(function_name) != AK::HashSetResult::InsertedNewEntry)
return {};
// 1. If varEnv is a global Environment Record, then
if (global_var_environment) {
// a. Let fnDefinable be ? varEnv.CanDeclareGlobalFunction(fn).
auto function_definable = TRY(global_var_environment->can_declare_global_function(function.name()));
auto function_definable = TRY(global_var_environment->can_declare_global_function(function_name));
// b. If fnDefinable is false, throw a TypeError exception.
if (!function_definable)
return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalFunction, function.name());
return vm.throw_completion<TypeError>(ErrorType::CannotDeclareGlobalFunction, function_name);
}
// 2. Append fn to declaredFunctionNames.
@ -865,12 +869,12 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
if (!strict) {
// a. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames.
// The spec here uses 'declaredVarNames' but that has not been declared yet.
HashTable<FlyString> hoisted_functions;
HashTable<Utf16FlyString> hoisted_functions;
// 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<void> {
// i. Let F be StringValue of the BindingIdentifier of f.
auto function_name = function_declaration.name();
auto function_name = Utf16FlyString::from_utf8(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.
@ -956,7 +960,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
}
// 12. Let declaredVarNames be a new empty List.
HashTable<FlyString> declared_var_names;
HashTable<Utf16FlyString> declared_var_names;
// 13. For each element d of varDeclarations, do
TRY(program.for_each_var_scoped_variable_declaration([&](VariableDeclaration const& declaration) {
@ -964,8 +968,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// Note: This is handled by for_each_var_scoped_variable_declaration.
// i. For each String vn of the BoundNames of d, do
return declaration.for_each_bound_identifier([&](auto const& identifier) -> ThrowCompletionOr<void> {
auto const& name = identifier.string();
return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// 1. If vn is not an element of declaredFunctionNames, then
if (!declared_function_names.contains(name)) {
@ -995,8 +999,8 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// 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([&](auto const& identifier) -> ThrowCompletionOr<void> {
auto const& name = identifier.string();
return declaration.for_each_bound_identifier([&](Identifier const& identifier) -> ThrowCompletionOr<void> {
auto name = Utf16FlyString::from_utf8(identifier.string());
// i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) {
@ -1016,12 +1020,14 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// NOTE: We iterate in reverse order since we appended the functions
// instead of prepending. We append because prepending is much slower
// and we only use the created vector here.
for (auto& declaration : functions_to_initialize.in_reverse()) {
for (auto const& declaration : functions_to_initialize.in_reverse()) {
auto declaration_name = Utf16FlyString::from_utf8(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.
auto function = ECMAScriptFunctionObject::create_from_function_node(
declaration,
declaration.name(),
declaration_name,
realm,
lexical_environment,
private_environment);
@ -1029,32 +1035,31 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& pr
// c. If varEnv is a global Environment Record, then
if (global_var_environment) {
// i. Perform ? varEnv.CreateGlobalFunctionBinding(fn, fo, true).
TRY(global_var_environment->create_global_function_binding(declaration.name(), function, true));
TRY(global_var_environment->create_global_function_binding(declaration_name, function, true));
}
// d. Else,
else {
// i. Let bindingExists be ! varEnv.HasBinding(fn).
auto binding_exists = MUST(variable_environment->has_binding(declaration.name()));
auto binding_exists = MUST(variable_environment->has_binding(declaration_name));
// ii. If bindingExists is false, then
if (!binding_exists) {
// 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
// 2. Perform ! varEnv.CreateMutableBinding(fn, true).
MUST(variable_environment->create_mutable_binding(vm, declaration.name(), true));
MUST(variable_environment->create_mutable_binding(vm, declaration_name, true));
// 3. Perform ! varEnv.InitializeBinding(fn, fo, normal).
MUST(variable_environment->initialize_binding(vm, declaration.name(), function, Environment::InitializeBindingHint::Normal));
MUST(variable_environment->initialize_binding(vm, declaration_name, function, Environment::InitializeBindingHint::Normal));
}
// iii. Else,
else {
// 1. Perform ! varEnv.SetMutableBinding(fn, fo, false).
MUST(variable_environment->set_mutable_binding(vm, declaration.name(), function, false));
MUST(variable_environment->set_mutable_binding(vm, declaration_name, function, false));
}
}
}
// 18. For each String vn of declaredVarNames, do
for (auto& var_name : declared_var_names) {
// a. If varEnv is a global Environment Record, then
if (global_var_environment) {
@ -1165,15 +1170,15 @@ Object* create_mapped_arguments_object(VM& vm, FunctionObject& function, Nonnull
// and getter/setter behavior itself without extra GC allocations.
// 17. Let mappedNames be a new empty List.
HashTable<FlyString> seen_names;
Vector<FlyString> mapped_names;
HashTable<Utf16FlyString> seen_names;
Vector<Utf16FlyString> mapped_names;
// 18. Set index to numberOfParameters - 1.
// 19. Repeat, while index ≥ 0,
VERIFY(formals->size() <= NumericLimits<i32>::max());
for (i32 index = static_cast<i32>(formals->size()) - 1; index >= 0; --index) {
// a. Let name be parameterNames[index].
auto const& name = formals->parameters()[index].binding.get<NonnullRefPtr<Identifier const>>()->string();
auto name = Utf16FlyString::from_utf8(formals->parameters()[index].binding.get<NonnullRefPtr<Identifier const>>()->string());
// b. If name is not an element of mappedNames, then
if (seen_names.contains(name))
@ -1229,22 +1234,23 @@ CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, C
// already covered it with the is_number() == true path.
if (argument.is_empty())
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
u32 current_index = 0;
auto const* characters = argument.bytes_as_string_view().characters_without_null_termination();
auto const length = argument.bytes_as_string_view().length();
if (characters[current_index] == '-') {
if (argument.code_unit_at(current_index) == '-') {
current_index++;
if (current_index == length)
if (current_index == argument.length_in_code_units())
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
}
if (characters[current_index] == '0') {
if (argument.code_unit_at(current_index) == '0') {
current_index++;
if (current_index == length)
if (current_index == argument.length_in_code_units())
return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
if (characters[current_index] != '.')
if (argument.code_unit_at(current_index) != '.')
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
current_index++;
if (current_index == length)
if (current_index == argument.length_in_code_units())
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
}
@ -1253,11 +1259,11 @@ CanonicalIndex canonical_numeric_index_string(PropertyKey const& property_key, C
return CanonicalIndex(CanonicalIndex::Type::Numeric, 0);
// Short circuit any string that doesn't start with digits
if (char first_non_zero = characters[current_index]; first_non_zero < '0' || first_non_zero > '9')
if (auto first_non_zero = argument.code_unit_at(current_index); first_non_zero < '0' || first_non_zero > '9')
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
// 2. Let n be ! ToNumber(argument).
auto maybe_double = argument.bytes_as_string_view().to_number<double>(AK::TrimWhitespace::No);
auto maybe_double = argument.to_number<double>(AK::TrimWhitespace::No);
if (!maybe_double.has_value())
return CanonicalIndex(CanonicalIndex::Type::Undefined, 0);
@ -1417,7 +1423,7 @@ ThrowCompletionOr<String> get_substitution(VM& vm, Utf16View const& matched, Utf
// 2. Let groupName be the substring of templateRemainder from 2 to gtPos.
auto group_name_view = template_remainder.substring_view(2, *greater_than_position - 2);
auto group_name = MUST(group_name_view.to_utf8());
auto group_name = Utf16String::from_utf16(group_name_view);
// 3. Assert: namedCaptures is an Object.
VERIFY(named_captures.is_object());

View File

@ -39,7 +39,7 @@ JS_API ThrowCompletionOr<size_t> length_of_array_like(VM&, Object const&);
ThrowCompletionOr<GC::RootVector<Value>> create_list_from_array_like(VM&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
ThrowCompletionOr<FunctionObject*> species_constructor(VM&, Object const&, FunctionObject& default_constructor);
JS_API ThrowCompletionOr<Realm*> get_function_realm(VM&, FunctionObject const&);
ThrowCompletionOr<void> initialize_bound_name(VM&, FlyString const&, Value, Environment*);
ThrowCompletionOr<void> initialize_bound_name(VM&, Utf16FlyString const&, Value, Environment*);
bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
bool validate_and_apply_property_descriptor(Object*, PropertyKey const&, bool extensible, PropertyDescriptor const&, Optional<PropertyDescriptor> const& current);
JS_API ThrowCompletionOr<Object*> get_prototype_from_constructor(VM&, FunctionObject const& constructor, GC::Ref<Object> (Intrinsics::*intrinsic_default_prototype)());

View File

@ -181,7 +181,7 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
void ArgumentsObject::delete_from_parameter_map(PropertyKey const& property_key)
{
m_mapped_names[property_key.as_number()] = FlyString {};
m_mapped_names[property_key.as_number()] = Utf16FlyString {};
}
Value ArgumentsObject::get_from_parameter_map(PropertyKey const& property_key) const

View File

@ -26,7 +26,7 @@ public:
virtual ThrowCompletionOr<bool> internal_set(PropertyKey const&, Value value, Value receiver, CacheablePropertyMetadata*, PropertyLookupPhase) override;
virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const&) override;
void set_mapped_names(Vector<FlyString> mapped_names) { m_mapped_names = move(mapped_names); }
void set_mapped_names(Vector<Utf16FlyString> mapped_names) { m_mapped_names = move(mapped_names); }
private:
ArgumentsObject(Realm&, Environment&);
@ -39,7 +39,7 @@ private:
virtual void visit_edges(Cell::Visitor&) override;
GC::Ref<Environment> m_environment;
Vector<FlyString> m_mapped_names;
Vector<Utf16FlyString> m_mapped_names;
};
}

View File

@ -607,35 +607,35 @@ namespace JS {
P(zonedDateTimeISO)
struct CommonPropertyNames {
PropertyKey and_ { "and"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey catch_ { "catch"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey delete_ { "delete"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey for_ { "for"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey or_ { "or"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey register_ { "register"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey return_ { "return"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey throw_ { "throw"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey try_ { "try"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey union_ { "union"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey xor_ { "xor"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey inputAlias { "$_"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey lastMatchAlias { "$&"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey lastParenAlias { "$+"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey leftContextAlias { "$`"_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey rightContextAlias { "$'"_fly_string, PropertyKey::StringMayBeNumber::No };
#define __ENUMERATE(x) PropertyKey x { #x##_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey and_ { "and"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey catch_ { "catch"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey delete_ { "delete"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey for_ { "for"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey or_ { "or"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey register_ { "register"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey return_ { "return"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey throw_ { "throw"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey try_ { "try"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey union_ { "union"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey xor_ { "xor"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey inputAlias { "$_"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey lastMatchAlias { "$&"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey lastParenAlias { "$+"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey leftContextAlias { "$`"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
PropertyKey rightContextAlias { "$'"_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
#define __ENUMERATE(x) PropertyKey x { #x##_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
ENUMERATE_STANDARD_PROPERTY_NAMES(__ENUMERATE)
#undef __ENUMERATE
#define __JS_ENUMERATE(x, a, b, c, t) PropertyKey x { #x##_fly_string, PropertyKey::StringMayBeNumber::No };
#define __JS_ENUMERATE(x, a, b, c, t) PropertyKey x { #x##_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(x, a, b, c) PropertyKey x { #x##_fly_string, PropertyKey::StringMayBeNumber::No };
#define __JS_ENUMERATE(x, a, b, c) PropertyKey x { #x##_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
JS_ENUMERATE_INTL_OBJECTS
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(x, a, b, c) PropertyKey x { #x##_fly_string, PropertyKey::StringMayBeNumber::No };
#define __JS_ENUMERATE(x, a, b, c) PropertyKey x { #x##_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
JS_ENUMERATE_TEMPORAL_OBJECTS
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(x, a) PropertyKey x { #x##_fly_string, PropertyKey::StringMayBeNumber::No };
#define __JS_ENUMERATE(x, a) PropertyKey x { #x##_utf16_fly_string, PropertyKey::StringMayBeNumber::No };
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
#undef __JS_ENUMERATE
};

View File

@ -52,7 +52,7 @@ void DeclarativeEnvironment::visit_edges(Visitor& visitor)
}
// 9.1.1.1.1 HasBinding ( N ), https://tc39.es/ecma262/#sec-declarative-environment-records-hasbinding-n
ThrowCompletionOr<bool> DeclarativeEnvironment::has_binding(FlyString const& name, Optional<size_t>* out_index) const
ThrowCompletionOr<bool> DeclarativeEnvironment::has_binding(Utf16FlyString const& name, Optional<size_t>* out_index) const
{
auto binding_and_index = find_binding_and_index(name);
if (!binding_and_index.has_value())
@ -63,7 +63,7 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::has_binding(FlyString const& nam
}
// 9.1.1.1.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-declarative-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted)
ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(VM&, Utf16FlyString const& name, bool can_be_deleted)
{
// 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
@ -86,7 +86,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(VM&, FlyS
}
// 9.1.1.1.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, FlyString const& name, bool strict)
ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, Utf16FlyString const& name, bool strict)
{
// 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
@ -110,7 +110,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(VM&, Fl
// 9.1.1.1.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v
// 4.1.1.1.1 InitializeBinding ( N, V, hint ), https://tc39.es/proposal-explicit-resource-management/#sec-declarative-environment-records
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value, Environment::InitializeBindingHint hint)
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(VM& vm, Utf16FlyString const& name, Value value, Environment::InitializeBindingHint hint)
{
return initialize_binding_direct(vm, find_binding_and_index(name)->index().value(), value, hint);
}
@ -137,7 +137,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(VM& vm
}
// 9.1.1.1.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(VM& vm, FlyString const& name, Value value, bool strict)
ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(VM& vm, Utf16FlyString const& name, Value value, bool strict)
{
// 1. If envRec does not have a binding for N, then
auto binding_and_index = find_binding_and_index(name);
@ -187,7 +187,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding_direct(VM& v
}
// 9.1.1.1.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-declarative-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(VM& vm, FlyString const& name, [[maybe_unused]] bool strict)
ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(VM& vm, Utf16FlyString const& name, [[maybe_unused]] bool strict)
{
// 1. Assert: envRec has a binding for N.
auto binding_and_index = find_binding_and_index(name);
@ -198,7 +198,7 @@ ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(VM& vm, FlySt
}
// 9.1.1.1.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-declarative-environment-records-deletebinding-n
ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(VM&, FlyString const& name)
ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(VM&, Utf16FlyString const& name)
{
// 1. Assert: envRec has a binding for the name that is the value of N.
auto binding_and_index = find_binding_and_index(name);
@ -218,7 +218,7 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(VM&, FlyString co
return true;
}
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_binding(VM& vm, FlyString const& name, Value value)
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_binding(VM& vm, Utf16FlyString const& name, Value value)
{
auto binding_and_index = find_binding_and_index(name);
VERIFY(binding_and_index.has_value());
@ -230,7 +230,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_bindin
return {};
}
void DeclarativeEnvironment::initialize_or_set_mutable_binding(Badge<ScopeNode>, VM& vm, FlyString const& name, Value value)
void DeclarativeEnvironment::initialize_or_set_mutable_binding(Badge<ScopeNode>, VM& vm, Utf16FlyString const& name, Value value)
{
MUST(initialize_or_set_mutable_binding(vm, name, value));
}

View File

@ -6,8 +6,8 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <AK/Utf16FlyString.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Environment.h>
@ -20,7 +20,7 @@ class DeclarativeEnvironment : public Environment {
GC_DECLARE_ALLOCATOR(DeclarativeEnvironment);
struct Binding {
FlyString name;
Utf16FlyString name;
Value value;
bool strict { false };
bool mutable_ { false };
@ -33,21 +33,21 @@ public:
virtual ~DeclarativeEnvironment() override = default;
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override final;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override final;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override final;
virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value, InitializeBindingHint) override final;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override final;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
virtual ThrowCompletionOr<bool> has_binding(Utf16FlyString const& name, Optional<size_t>* = nullptr) const override final;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, Utf16FlyString const& name, bool can_be_deleted) override final;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, Utf16FlyString const& name, bool strict) override final;
virtual ThrowCompletionOr<void> initialize_binding(VM&, Utf16FlyString const& name, Value, InitializeBindingHint) override final;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, Utf16FlyString const& name, Value, bool strict) override final;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, Utf16FlyString const& name) override;
void initialize_or_set_mutable_binding(Badge<ScopeNode>, VM&, FlyString const& name, Value value);
ThrowCompletionOr<void> initialize_or_set_mutable_binding(VM&, FlyString const& name, Value value);
void initialize_or_set_mutable_binding(Badge<ScopeNode>, VM&, Utf16FlyString const& name, Value value);
ThrowCompletionOr<void> initialize_or_set_mutable_binding(VM&, Utf16FlyString const& name, Value value);
// This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code.
[[nodiscard]] Vector<FlyString> bindings() const
[[nodiscard]] Vector<Utf16FlyString> bindings() const
{
Vector<FlyString> names;
Vector<Utf16FlyString> names;
names.ensure_capacity(m_bindings.size());
for (auto const& binding : m_bindings)
@ -114,7 +114,7 @@ protected:
friend class ModuleEnvironment;
virtual Optional<BindingAndIndex> find_binding_and_index(FlyString const& name) const
virtual Optional<BindingAndIndex> find_binding_and_index(Utf16FlyString const& name) const
{
if (auto it = m_bindings_assoc.find(name); it != m_bindings_assoc.end()) {
return BindingAndIndex { const_cast<Binding*>(&m_bindings.at(it->value)), it->value };
@ -125,7 +125,7 @@ protected:
private:
Vector<Binding> m_bindings;
HashMap<FlyString, size_t> m_bindings_assoc;
HashMap<Utf16FlyString, size_t> m_bindings_assoc;
DisposeCapability m_dispose_capability;
u64 m_environment_serial_number { 0 };

View File

@ -33,7 +33,7 @@ namespace JS {
GC_DEFINE_ALLOCATOR(ECMAScriptFunctionObject);
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
{
Object* prototype = nullptr;
switch (kind) {
@ -73,7 +73,7 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm,
*prototype);
}
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
{
auto shared_data = adopt_ref(*new SharedFunctionInstanceData(
realm.vm(),
@ -97,7 +97,7 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm,
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create_from_function_node(
FunctionNode const& function_node,
FlyString name,
Utf16FlyString name,
GC::Ref<Realm> realm,
GC::Ptr<Environment> parent_environment,
GC::Ptr<PrivateEnvironment> private_environment)
@ -145,7 +145,7 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create_from_function
SharedFunctionInstanceData::SharedFunctionInstanceData(
VM& vm,
FunctionKind kind,
FlyString name,
Utf16FlyString name,
i32 function_length,
NonnullRefPtr<FunctionParameters const> formal_parameters,
NonnullRefPtr<Statement const> ecmascript_code,
@ -210,7 +210,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
parameter.binding.visit(
[&](Identifier const& identifier) {
if (m_parameter_names.set(identifier.string(), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry)
if (m_parameter_names.set(Utf16FlyString::from_utf8(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(identifier.string(), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry)
if (m_parameter_names.set(Utf16FlyString::from_utf8(identifier.string()), identifier.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) != AK::HashSetResult::InsertedNewEntry)
m_has_duplicates = true;
else if (!identifier.is_local())
++parameters_in_environment;
@ -244,7 +244,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
m_arguments_object_needed = false;
}
HashTable<FlyString> function_names;
HashTable<Utf16FlyString> function_names;
// 18. Else if hasParameterExpressions is false, then
// a. If functionNames contains "arguments" or lexicalNames contains "arguments", then
@ -253,7 +253,9 @@ 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) {
if (function_names.set(function.name()) == AK::HashSetResult::InsertedNewEntry)
auto name = Utf16FlyString::from_utf8(function.name());
if (function_names.set(name) == AK::HashSetResult::InsertedNewEntry)
m_functions_to_initialize.append(function);
}));
@ -293,7 +295,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
*environment_size += parameters_in_environment;
HashMap<FlyString, ParameterIsLocal> parameter_bindings;
HashMap<Utf16FlyString, ParameterIsLocal> parameter_bindings;
auto arguments_object_needs_binding = m_arguments_object_needed && !m_local_variables_names.first_matching([](auto const& local) { return local.declaration_kind == LocalVariable::DeclarationKind::ArgumentsObject; }).has_value();
@ -310,7 +312,7 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
// a. Let parameterBindings be parameterNames.
}
HashMap<FlyString, ParameterIsLocal> instantiated_var_names;
HashMap<Utf16FlyString, ParameterIsLocal> instantiated_var_names;
size_t* var_environment_size = nullptr;
@ -321,9 +323,9 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
if (scope_body) {
// c. For each element n of varNames, do
MUST(scope_body->for_each_var_declared_identifier([&](auto const& id) {
MUST(scope_body->for_each_var_declared_identifier([&](Identifier const& id) {
// i. If instantiatedVarNames does not contain n, then
if (instantiated_var_names.set(id.string(), id.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) == AK::HashSetResult::InsertedNewEntry) {
if (instantiated_var_names.set(Utf16FlyString::from_utf8(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).
@ -353,16 +355,18 @@ SharedFunctionInstanceData::SharedFunctionInstanceData(
// NOTE: Steps a, b, c and d are executed in function_declaration_instantiation.
// e. For each element n of varNames, do
if (scope_body) {
MUST(scope_body->for_each_var_declared_identifier([&](auto const& id) {
MUST(scope_body->for_each_var_declared_identifier([&](Identifier const& id) {
auto name = Utf16FlyString::from_utf8(id.string());
// 1. Append n to instantiatedVarNames.
// Following steps will be executed in function_declaration_instantiation:
// 2. Perform ! env.CreateMutableBinding(n, false).
// 3. Perform ! env.InitializeBinding(n, undefined).
if (instantiated_var_names.set(id.string(), id.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) == AK::HashSetResult::InsertedNewEntry) {
if (instantiated_var_names.set(name, id.is_local() ? ParameterIsLocal::Yes : ParameterIsLocal::No) == AK::HashSetResult::InsertedNewEntry) {
m_var_names_to_initialize_binding.append({
.identifier = id,
.parameter_binding = parameter_bindings.contains(id.string()),
.function_name = function_names.contains(id.string()),
.parameter_binding = parameter_bindings.contains(name),
.function_name = function_names.contains(name),
});
if (!id.is_local())
@ -376,7 +380,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 = function_declaration.name();
auto function_name = Utf16FlyString::from_utf8(function_declaration.name());
if (parameter_bindings.contains(function_name))
return;
@ -826,7 +830,7 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
auto& running_context = vm.running_execution_context();
// 2. Let closure be a new Abstract Closure with no parameters that captures promiseCapability and asyncBody and performs the following steps when called:
auto closure = NativeFunction::create(realm, ""_fly_string, [&async_body, &promise_capability](auto& vm) -> ThrowCompletionOr<Value> {
auto closure = NativeFunction::create(realm, {}, [&async_body, &promise_capability](auto& vm) -> ThrowCompletionOr<Value> {
Completion result;
// a. Let acAsyncContext be the running execution context.
@ -834,7 +838,7 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
// b. If asyncBody is a Parse Node, then
if constexpr (!IsSame<T, GC::Function<Completion()>>) {
// i. Let result be Completion(Evaluation of asyncBody).
auto maybe_executable = Bytecode::compile(vm, async_body, FunctionKind::Async, "AsyncBlockStart"_fly_string);
auto maybe_executable = Bytecode::compile(vm, async_body, FunctionKind::Async, "AsyncBlockStart"_utf16_fly_string);
if (maybe_executable.is_error())
result = maybe_executable.release_error();
else
@ -931,7 +935,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::ordinary_call_evaluate_body(V
return generator_object;
}
void ECMAScriptFunctionObject::set_name(FlyString const& name)
void ECMAScriptFunctionObject::set_name(Utf16FlyString const& name)
{
auto& vm = this->vm();
const_cast<SharedFunctionInstanceData&>(shared_data()).m_name = name;

View File

@ -39,7 +39,7 @@ public:
SharedFunctionInstanceData(
VM& vm,
FunctionKind,
FlyString name,
Utf16FlyString name,
i32 function_length,
NonnullRefPtr<FunctionParameters const>,
NonnullRefPtr<Statement const> ecmascript_code,
@ -52,7 +52,7 @@ public:
RefPtr<FunctionParameters const> m_formal_parameters; // [[FormalParameters]]
RefPtr<Statement const> m_ecmascript_code; // [[ECMAScriptCode]]
FlyString m_name;
Utf16FlyString m_name;
ByteString m_source_text; // [[SourceText]]
Vector<LocalVariable> m_local_variables_names;
@ -81,13 +81,13 @@ public:
No,
Yes,
};
HashMap<FlyString, ParameterIsLocal> m_parameter_names;
HashMap<Utf16FlyString, ParameterIsLocal> m_parameter_names;
Vector<FunctionDeclaration const&> m_functions_to_initialize;
bool m_arguments_object_needed { false };
bool m_function_environment_needed { false };
bool m_uses_this { false };
Vector<VariableNameToInitialize> m_var_names_to_initialize_binding;
Vector<FlyString> m_function_names_to_initialize_binding;
Vector<Utf16FlyString> m_function_names_to_initialize_binding;
size_t m_function_environment_bindings_count { 0 };
size_t m_var_environment_bindings_count { 0 };
@ -104,12 +104,12 @@ class JS_API ECMAScriptFunctionObject final : public FunctionObject {
GC_DECLARE_ALLOCATOR(ECMAScriptFunctionObject);
public:
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, Utf16FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
static GC::Ref<ECMAScriptFunctionObject> create(Realm&, Utf16FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind, bool is_strict, FunctionParsingInsights, bool is_arrow_function = false, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name = {});
[[nodiscard]] static GC::Ref<ECMAScriptFunctionObject> create_from_function_node(
FunctionNode const&,
FlyString name,
Utf16FlyString name,
GC::Ref<Realm>,
GC::Ptr<Environment> parent_environment,
GC::Ptr<PrivateEnvironment>);
@ -129,8 +129,8 @@ public:
Statement const& ecmascript_code() const { return *shared_data().m_ecmascript_code; }
[[nodiscard]] virtual FunctionParameters const& formal_parameters() const override { return *shared_data().m_formal_parameters; }
FlyString const& name() const { return shared_data().m_name; }
void set_name(FlyString const& name);
Utf16FlyString const& name() const { return shared_data().m_name; }
void set_name(Utf16FlyString const& name);
void set_is_class_constructor() { const_cast<SharedFunctionInstanceData&>(shared_data()).m_is_class_constructor = true; }

View File

@ -35,13 +35,13 @@ public:
virtual Object* with_base_object() const { return nullptr; }
virtual ThrowCompletionOr<bool> has_binding([[maybe_unused]] FlyString const& name, [[maybe_unused]] Optional<size_t>* out_index = nullptr) const = 0;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool can_be_deleted) = 0;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<void> initialize_binding(VM&, [[maybe_unused]] FlyString const& name, Value, InitializeBindingHint) = 0;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, [[maybe_unused]] FlyString const& name, Value, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<bool> delete_binding(VM&, [[maybe_unused]] FlyString const& name) = 0;
virtual ThrowCompletionOr<bool> has_binding([[maybe_unused]] Utf16FlyString const& name, [[maybe_unused]] Optional<size_t>* out_index = nullptr) const = 0;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, [[maybe_unused]] Utf16FlyString const& name, [[maybe_unused]] bool can_be_deleted) = 0;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, [[maybe_unused]] Utf16FlyString const& name, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<void> initialize_binding(VM&, [[maybe_unused]] Utf16FlyString const& name, Value, InitializeBindingHint) = 0;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, [[maybe_unused]] Utf16FlyString const& name, Value, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, [[maybe_unused]] Utf16FlyString const& name, [[maybe_unused]] bool strict) = 0;
virtual ThrowCompletionOr<bool> delete_binding(VM&, [[maybe_unused]] Utf16FlyString const& name) = 0;
// [[OuterEnv]]
Environment* outer_environment() { return m_outer_environment; }

View File

@ -7,6 +7,7 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/String.h>
#include <LibJS/Export.h>
#include <LibJS/Runtime/Completion.h>

View File

@ -200,7 +200,7 @@ ThrowCompletionOr<GC::Ref<ECMAScriptFunctionObject>> FunctionConstructor::create
// 28. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
parsing_insights.might_need_arguments_object = true;
auto function = ECMAScriptFunctionObject::create(realm, "anonymous"_fly_string, *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), expr->local_variables_names(), &environment, private_environment, expr->kind(), expr->is_strict_mode(), parsing_insights);
auto function = ECMAScriptFunctionObject::create(realm, "anonymous"_utf16_fly_string, *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), expr->local_variables_names(), &environment, private_environment, expr->kind(), expr->is_strict_mode(), parsing_insights);
// FIXME: Remove the name argument from create() and do this instead.
// 29. Perform SetFunctionName(F, "anonymous").

View File

@ -28,7 +28,7 @@ GC::Ref<PrimitiveString> FunctionObject::make_function_name(Variant<PropertyKey,
{
auto& vm = this->vm();
String name;
Utf16String name;
// 2. If Type(name) is Symbol, then
if (auto const* property_key = name_arg.get_pointer<PropertyKey>(); property_key && property_key->is_symbol()) {
@ -37,15 +37,15 @@ GC::Ref<PrimitiveString> FunctionObject::make_function_name(Variant<PropertyKey,
// b. If description is undefined, set name to the empty String.
if (!description.has_value())
name = ""_string;
name = {};
// c. Else, set name to the string-concatenation of "[", description, and "]".
else
name = MUST(String::formatted("[{}]", *description));
name = Utf16String::formatted("[{}]", *description);
}
// 3. Else if name is a Private Name, then
else if (auto const* private_name = name_arg.get_pointer<PrivateName>()) {
// a. Set name to name.[[Description]].
name = private_name->description.to_string();
name = private_name->description.to_utf16_string();
}
// NOTE: This is necessary as we use a different parameter name.
else {
@ -61,7 +61,7 @@ GC::Ref<PrimitiveString> FunctionObject::make_function_name(Variant<PropertyKey,
// 5. If prefix is present, then
if (prefix.has_value()) {
// a. Set name to the string-concatenation of prefix, the code unit 0x0020 (SPACE), and name.
name = MUST(String::formatted("{} {}", *prefix, name));
name = Utf16String::formatted("{} {}", *prefix, name);
// b. If F has an [[InitialName]] internal slot, then
if (is<NativeFunction>(this)) {

View File

@ -41,7 +41,7 @@ ThrowCompletionOr<Value> GlobalEnvironment::get_this_binding(VM&) const
}
// 9.1.1.4.1 HasBinding ( N ), https://tc39.es/ecma262/#sec-global-environment-records-hasbinding-n
ThrowCompletionOr<bool> GlobalEnvironment::has_binding(FlyString const& name, Optional<size_t>*) const
ThrowCompletionOr<bool> GlobalEnvironment::has_binding(Utf16FlyString const& name, Optional<size_t>*) const
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, return true.
@ -54,7 +54,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::has_binding(FlyString const& name, Op
}
// 9.1.1.4.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-global-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(VM& vm, FlyString const& name, bool can_be_deleted)
ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(VM& vm, Utf16FlyString const& name, bool can_be_deleted)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
@ -66,7 +66,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(VM& vm, FlyStr
}
// 9.1.1.4.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(VM& vm, FlyString const& name, bool strict)
ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(VM& vm, Utf16FlyString const& name, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
@ -78,7 +78,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(VM& vm, FlyS
}
// 9.1.1.4.4 InitializeBinding ( N, V, hint ), https://tc39.es/ecma262/#sec-global-environment-records-initializebinding-n-v
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value, InitializeBindingHint hint)
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, Utf16FlyString const& name, Value value, InitializeBindingHint hint)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then
@ -96,7 +96,7 @@ ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(VM& vm, FlyString
}
// 9.1.1.4.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-global-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(VM& vm, FlyString const& name, Value value, bool strict)
ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(VM& vm, Utf16FlyString const& name, Value value, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then
@ -111,7 +111,7 @@ ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(VM& vm, FlyString
}
// 9.1.1.4.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-global-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(VM& vm, FlyString const& name, bool strict)
ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(VM& vm, Utf16FlyString const& name, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then
@ -129,7 +129,7 @@ ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(VM& vm, FlyString
}
// 9.1.1.4.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-global-environment-records-deletebinding-n
ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(VM& vm, FlyString const& name)
ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(VM& vm, Utf16FlyString const& name)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If ! DclRec.HasBinding(N) is true, then
@ -155,7 +155,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(VM& vm, FlyString cons
}
// 9.1.1.4.12 HasLexicalDeclaration ( envRec, N ), https://tc39.es/ecma262/#sec-haslexicaldeclaration
bool GlobalEnvironment::has_lexical_declaration(FlyString const& name) const
bool GlobalEnvironment::has_lexical_declaration(Utf16FlyString const& name) const
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. Return ! DclRec.HasBinding(N).
@ -163,7 +163,7 @@ bool GlobalEnvironment::has_lexical_declaration(FlyString const& name) const
}
// 9.1.1.4.13 HasRestrictedGlobalProperty ( envRec, N ), https://tc39.es/ecma262/#sec-hasrestrictedglobalproperty
ThrowCompletionOr<bool> GlobalEnvironment::has_restricted_global_property(FlyString const& name) const
ThrowCompletionOr<bool> GlobalEnvironment::has_restricted_global_property(Utf16FlyString const& name) const
{
// 1. Let ObjRec be envRec.[[ObjectRecord]].
// 2. Let globalObject be ObjRec.[[BindingObject]].
@ -185,7 +185,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::has_restricted_global_property(FlyStr
}
// 9.1.1.4.14 CanDeclareGlobalVar ( envRec, N ), https://tc39.es/ecma262/#sec-candeclareglobalvar
ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_var(FlyString const& name) const
ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_var(Utf16FlyString const& name) const
{
// 1. Let ObjRec be envRec.[[ObjectRecord]].
// 2. Let globalObject be ObjRec.[[BindingObject]].
@ -203,7 +203,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_var(FlyString cons
}
// 9.1.1.4.15 CanDeclareGlobalFunction ( envRec, N ), https://tc39.es/ecma262/#sec-candeclareglobalfunction
ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_function(FlyString const& name) const
ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_function(Utf16FlyString const& name) const
{
// 1. Let ObjRec be envRec.[[ObjectRecord]].
// 2. Let globalObject be ObjRec.[[BindingObject]].
@ -229,7 +229,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::can_declare_global_function(FlyString
}
// 9.1.1.4.16 CreateGlobalVarBinding ( envRec, N, D ), https://tc39.es/ecma262/#sec-createglobalvarbinding
ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString const& name, bool can_be_deleted)
ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(Utf16FlyString const& name, bool can_be_deleted)
{
auto& vm = this->vm();
@ -257,7 +257,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString c
}
// 9.1.1.4.17 CreateGlobalFunctionBinding ( envRec, N, V, D ), https://tc39.es/ecma262/#sec-createglobalfunctionbinding
ThrowCompletionOr<void> GlobalEnvironment::create_global_function_binding(FlyString const& name, Value value, bool can_be_deleted)
ThrowCompletionOr<void> GlobalEnvironment::create_global_function_binding(Utf16FlyString const& name, Value value, bool can_be_deleted)
{
// 1. Let ObjRec be envRec.[[ObjectRecord]].
// 2. Let globalObject be ObjRec.[[BindingObject]].

View File

@ -19,24 +19,24 @@ public:
virtual bool has_this_binding() const final { return true; }
virtual ThrowCompletionOr<Value> get_this_binding(VM&) const final;
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value, Environment::InitializeBindingHint) override;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
virtual ThrowCompletionOr<bool> has_binding(Utf16FlyString const& name, Optional<size_t>* = nullptr) const override;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, Utf16FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(VM&, Utf16FlyString const& name, Value, Environment::InitializeBindingHint) override;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, Utf16FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, Utf16FlyString const& name) override;
ObjectEnvironment& object_record() { return *m_object_record; }
Object& global_this_value() { return *m_global_this_value; }
DeclarativeEnvironment& declarative_record() { return *m_declarative_record; }
bool has_lexical_declaration(FlyString const& name) const;
ThrowCompletionOr<bool> has_restricted_global_property(FlyString const& name) const;
ThrowCompletionOr<bool> can_declare_global_var(FlyString const& name) const;
ThrowCompletionOr<bool> can_declare_global_function(FlyString const& name) const;
ThrowCompletionOr<void> create_global_var_binding(FlyString const& name, bool can_be_deleted);
ThrowCompletionOr<void> create_global_function_binding(FlyString const& name, Value, bool can_be_deleted);
bool has_lexical_declaration(Utf16FlyString const& name) const;
ThrowCompletionOr<bool> has_restricted_global_property(Utf16FlyString const& name) const;
ThrowCompletionOr<bool> can_declare_global_var(Utf16FlyString const& name) const;
ThrowCompletionOr<bool> can_declare_global_function(Utf16FlyString const& name) const;
ThrowCompletionOr<void> create_global_var_binding(Utf16FlyString const& name, bool can_be_deleted);
ThrowCompletionOr<void> create_global_function_binding(Utf16FlyString const& name, Value, bool can_be_deleted);
private:
GlobalEnvironment(Object&, Object& this_value);

View File

@ -203,7 +203,7 @@ static GC::Ref<ListFormat> construct_list_format(VM& vm, DurationFormat const& d
// 13.5.6.1 ValidateDurationUnitStyle ( unit, style, display, prevStyle ), https://tc39.es/ecma402/#sec-validatedurationunitstyle
// AD-HOC: Our implementation takes extra parameters for better exception messages.
static ThrowCompletionOr<void> validate_duration_unit_style(VM& vm, PropertyKey const& unit, DurationFormat::ValueStyle style, DurationFormat::Display display, Optional<DurationFormat::ValueStyle> previous_style, StringView display_field)
static ThrowCompletionOr<void> validate_duration_unit_style(VM& vm, PropertyKey const& unit, DurationFormat::ValueStyle style, DurationFormat::Display display, Optional<DurationFormat::ValueStyle> previous_style, Utf16View const& display_field)
{
// 1. If display is "always" and style is "fractional", throw a RangeError exception.
if (display == DurationFormat::Display::Always && style == DurationFormat::ValueStyle::Fractional)
@ -277,7 +277,7 @@ ThrowCompletionOr<DurationFormat::DurationUnitOptions> get_duration_unit_options
}
// 5. Let displayField be the string-concatenation of unit and "Display".
auto display_field = MUST(String::formatted("{}Display", unit_property_key));
auto display_field = Utf16String::formatted("{}Display", unit_property_key);
// 6. Let display be ? GetOption(options, displayField, STRING, « "auto", "always" », displayDefault).
auto display_value = TRY(get_option(vm, options, display_field, OptionType::String, { "auto"sv, "always"sv }, display_default));
@ -922,7 +922,7 @@ Vector<DurationFormatPart> partition_duration_format_pattern(VM& vm, DurationFor
for (auto& part : parts) {
// a. Append the Record { [[Type]]: part.[[Type]], [[Value]]: part.[[Value]], [[Unit]]: numberFormatUnit } to list.
list.unchecked_append({ .type = part.type, .value = move(part.value), .unit = number_format_unit.as_string() });
list.unchecked_append({ .type = part.type, .value = move(part.value), .unit = number_format_unit.as_string().view() });
}
// 11. Append list to result.

View File

@ -179,7 +179,7 @@ static constexpr auto duration_instances_components = to_array<DurationInstanceC
struct DurationFormatPart {
StringView type;
Utf16String value;
StringView unit;
Utf16View unit;
};
ThrowCompletionOr<DurationFormat::DurationUnitOptions> get_duration_unit_options(VM&, DurationFormat::Unit unit, Object const& options, DurationFormat::Style base_style, ReadonlySpan<StringView> styles_list, DurationFormat::ValueStyle digital_base, Optional<DurationFormat::ValueStyle> previous_style, bool two_digit_hours);

View File

@ -286,7 +286,7 @@ void Intrinsics::initialize_intrinsics(Realm& realm)
realm, [](VM& vm) {
return vm.throw_completion<TypeError>(ErrorType::RestrictedFunctionPropertiesAccess);
},
0, FlyString {}, &realm);
0, Utf16FlyString {}, &realm);
m_throw_type_error_function->define_direct_property(vm.names.length, Value(0), 0);
m_throw_type_error_function->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), 0);
MUST(m_throw_type_error_function->internal_prevent_extensions());

View File

@ -64,24 +64,24 @@ ThrowCompletionOr<Optional<String>> JSONObject::stringify_impl(VM& vm, Value val
if (is_array) {
auto& replacer_object = replacer.as_object();
auto replacer_length = TRY(length_of_array_like(vm, replacer_object));
Vector<String> list;
Vector<Utf16String> list;
for (size_t i = 0; i < replacer_length; ++i) {
auto replacer_value = TRY(replacer_object.get(i));
Optional<String> item;
Optional<Utf16String> item;
if (replacer_value.is_string()) {
item = replacer_value.as_string().utf8_string();
item = replacer_value.as_string().utf16_string();
} else if (replacer_value.is_number()) {
item = MUST(replacer_value.to_string(vm));
item = MUST(replacer_value.to_utf16_string(vm));
} else if (replacer_value.is_object()) {
auto& value_object = replacer_value.as_object();
if (is<StringObject>(value_object) || is<NumberObject>(value_object))
item = TRY(replacer_value.to_string(vm));
item = TRY(replacer_value.to_utf16_string(vm));
}
if (item.has_value() && !list.contains_slow(*item)) {
list.append(*item);
}
}
state.property_list = list;
state.property_list = move(list);
}
}
}
@ -109,8 +109,8 @@ ThrowCompletionOr<Optional<String>> JSONObject::stringify_impl(VM& vm, Value val
}
auto wrapper = Object::create(realm, realm.intrinsics().object_prototype());
MUST(wrapper->create_data_property_or_throw(String {}, value));
return serialize_json_property(vm, state, String {}, wrapper);
MUST(wrapper->create_data_property_or_throw(Utf16String {}, value));
return serialize_json_property(vm, state, Utf16String {}, wrapper);
}
// 25.5.2 JSON.stringify ( value [ , replacer [ , space ] ] ), https://tc39.es/ecma262/#sec-json.stringify
@ -197,7 +197,7 @@ ThrowCompletionOr<Optional<String>> JSONObject::serialize_json_property(VM& vm,
// 8. If Type(value) is String, return QuoteJSONString(value).
if (value.is_string())
return quote_json_string(value.as_string().utf8_string());
return quote_json_string(value.as_string().utf16_string_view());
// 9. If Type(value) is Number, then
if (value.is_number()) {
@ -262,7 +262,7 @@ ThrowCompletionOr<String> JSONObject::serialize_json_object(VM& vm, StringifySta
} else {
auto property_list = TRY(object.enumerable_own_property_names(PropertyKind::Key));
for (auto& property : property_list)
TRY(process_property(property.as_string().utf8_string()));
TRY(process_property(property.as_string().utf16_string()));
}
StringBuilder builder;
if (property_strings.is_empty()) {
@ -360,15 +360,14 @@ ThrowCompletionOr<String> JSONObject::serialize_json_array(VM& vm, StringifyStat
}
// 25.5.2.2 QuoteJSONString ( value ), https://tc39.es/ecma262/#sec-quotejsonstring
String JSONObject::quote_json_string(String string)
String JSONObject::quote_json_string(Utf16View const& string)
{
// 1. Let product be the String value consisting solely of the code unit 0x0022 (QUOTATION MARK).
StringBuilder builder;
builder.append('"');
// 2. For each code point C of StringToCodePoints(value), do
auto utf_view = Utf8View(string);
for (auto code_point : utf_view) {
for (auto code_point : string) {
// a. If C is listed in the “Code Point” column of Table 70, then
// i. Set product to the string-concatenation of product and the escape sequence for C as specified in the “Escape Sequence” column of the corresponding row.
switch (code_point) {
@ -407,6 +406,7 @@ String JSONObject::quote_json_string(String string)
}
}
}
// 3. Set product to the string-concatenation of product and the code unit 0x0022 (QUOTATION MARK).
builder.append('"');
@ -434,7 +434,7 @@ JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse)
auto root = Object::create(realm, realm.intrinsics().object_prototype());
// b. Let rootName be the empty String.
String root_name;
Utf16String root_name;
// c. Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered).
MUST(root->create_data_property_or_throw(root_name, unfiltered));
@ -492,7 +492,7 @@ Object* JSONObject::parse_json_object(VM& vm, JsonObject const& json_object)
auto& realm = *vm.current_realm();
auto object = Object::create(realm, realm.intrinsics().object_prototype());
json_object.for_each_member([&](auto& key, auto& value) {
object->define_direct_property(key, parse_json_value(vm, value), default_attributes);
object->define_direct_property(Utf16String::from_utf8(key), parse_json_value(vm, value), default_attributes);
});
return object;
}
@ -532,7 +532,7 @@ ThrowCompletionOr<Value> JSONObject::internalize_json_property(VM& vm, Object* h
} else {
auto property_list = TRY(value_object.enumerable_own_property_names(Object::PropertyKind::Key));
for (auto& property_key : property_list)
TRY(process_property(property_key.as_string().utf8_string()));
TRY(process_property(property_key.as_string().utf16_string()));
}
}

View File

@ -34,14 +34,14 @@ private:
HashTable<GC::Ptr<Object>> seen_objects;
String indent;
String gap;
Optional<Vector<String>> property_list;
Optional<Vector<Utf16String>> property_list;
};
// Stringify helpers
static ThrowCompletionOr<Optional<String>> serialize_json_property(VM&, StringifyState&, PropertyKey const& key, Object* holder);
static ThrowCompletionOr<String> serialize_json_object(VM&, StringifyState&, Object&);
static ThrowCompletionOr<String> serialize_json_array(VM&, StringifyState&, Object&);
static String quote_json_string(String);
static String quote_json_string(Utf16View const&);
// Parse helpers
static Object* parse_json_object(VM&, JsonObject const&);

View File

@ -20,7 +20,7 @@ ModuleEnvironment::ModuleEnvironment(Environment* outer_environment)
}
// 9.1.1.5.1 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-module-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(VM& vm, FlyString const& name, bool strict)
ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(VM& vm, Utf16FlyString const& name, bool strict)
{
// 1. Assert: S is true.
VERIFY(strict);
@ -51,7 +51,7 @@ ThrowCompletionOr<Value> ModuleEnvironment::get_binding_value(VM& vm, FlyString
}
// 9.1.1.5.2 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-module-environment-records-deletebinding-n
ThrowCompletionOr<bool> ModuleEnvironment::delete_binding(VM&, FlyString const&)
ThrowCompletionOr<bool> ModuleEnvironment::delete_binding(VM&, Utf16FlyString const&)
{
// The DeleteBinding concrete method of a module Environment Record is never used within this specification.
VERIFY_NOT_REACHED();
@ -65,7 +65,7 @@ ThrowCompletionOr<Value> ModuleEnvironment::get_this_binding(VM&) const
}
// 9.1.1.5.5 CreateImportBinding ( N, M, N2 ), https://tc39.es/ecma262/#sec-createimportbinding
ThrowCompletionOr<void> ModuleEnvironment::create_import_binding(FlyString name, Module* module, FlyString binding_name)
ThrowCompletionOr<void> ModuleEnvironment::create_import_binding(Utf16FlyString name, Module* module, Utf16FlyString binding_name)
{
// 1. Assert: envRec does not already have a binding for N.
VERIFY(!get_indirect_binding(name));
@ -82,7 +82,7 @@ ThrowCompletionOr<void> ModuleEnvironment::create_import_binding(FlyString name,
return {};
}
ModuleEnvironment::IndirectBinding const* ModuleEnvironment::get_indirect_binding(FlyString const& name) const
ModuleEnvironment::IndirectBinding const* ModuleEnvironment::get_indirect_binding(Utf16FlyString const& name) const
{
auto binding_or_end = m_indirect_bindings.find_if([&](IndirectBinding const& binding) {
return binding.name == name;
@ -93,7 +93,7 @@ ModuleEnvironment::IndirectBinding const* ModuleEnvironment::get_indirect_bindin
return &(*binding_or_end);
}
Optional<ModuleEnvironment::BindingAndIndex> ModuleEnvironment::find_binding_and_index(FlyString const& name) const
Optional<ModuleEnvironment::BindingAndIndex> ModuleEnvironment::find_binding_and_index(Utf16FlyString const& name) const
{
auto* indirect_binding = get_indirect_binding(name);
if (indirect_binding != nullptr) {

View File

@ -22,11 +22,11 @@ public:
// in Table 18 and share the same specifications for all of those methods except for
// GetBindingValue, DeleteBinding, HasThisBinding and GetThisBinding.
// In addition, module Environment Records support the methods listed in Table 24.
virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, Utf16FlyString const& name) override;
virtual bool has_this_binding() const final { return true; }
virtual ThrowCompletionOr<Value> get_this_binding(VM&) const final;
ThrowCompletionOr<void> create_import_binding(FlyString name, Module* module, FlyString binding_name);
ThrowCompletionOr<void> create_import_binding(Utf16FlyString name, Module* module, Utf16FlyString binding_name);
private:
explicit ModuleEnvironment(Environment* outer_environment);
@ -34,13 +34,13 @@ private:
virtual void visit_edges(Visitor&) override;
struct IndirectBinding {
FlyString name;
Utf16FlyString name;
GC::Ptr<Module> module;
FlyString binding_name;
Utf16FlyString binding_name;
};
IndirectBinding const* get_indirect_binding(FlyString const& name) const;
IndirectBinding const* get_indirect_binding(Utf16FlyString const& name) const;
virtual Optional<BindingAndIndex> find_binding_and_index(FlyString const& name) const override;
virtual Optional<BindingAndIndex> find_binding_and_index(Utf16FlyString const& name) const override;
// FIXME: Since we always access this via the name this could be a map.
Vector<IndirectBinding> m_indirect_bindings;

View File

@ -13,16 +13,14 @@ namespace JS {
GC_DEFINE_ALLOCATOR(ModuleNamespaceObject);
ModuleNamespaceObject::ModuleNamespaceObject(Realm& realm, Module* module, Vector<FlyString> exports)
ModuleNamespaceObject::ModuleNamespaceObject(Realm& realm, Module* module, Vector<Utf16FlyString> exports)
: Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype(), MayInterfereWithIndexedPropertyAccess::Yes)
, m_module(module)
, m_exports(move(exports))
{
// Note: We just perform step 6 of 10.4.6.12 ModuleNamespaceCreate ( module, exports ), https://tc39.es/ecma262/#sec-modulenamespacecreate
// 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.
quick_sort(m_exports, [&](FlyString const& lhs, FlyString const& rhs) {
return lhs.bytes_as_string_view() < rhs.bytes_as_string_view();
});
quick_sort(m_exports);
}
void ModuleNamespaceObject::initialize(Realm& realm)

View File

@ -33,12 +33,12 @@ public:
virtual void initialize(Realm&) override;
private:
ModuleNamespaceObject(Realm&, Module* module, Vector<FlyString> exports);
ModuleNamespaceObject(Realm&, Module* module, Vector<Utf16FlyString> exports);
virtual void visit_edges(Visitor&) override;
GC::Ptr<Module> m_module; // [[Module]]
Vector<FlyString> m_exports; // [[Exports]]
GC::Ptr<Module> m_module; // [[Module]]
Vector<Utf16FlyString> m_exports; // [[Exports]]
};
}

View File

@ -68,7 +68,7 @@ GC::Ref<NativeFunction> NativeFunction::create(Realm& allocating_realm, Function
return function;
}
GC::Ref<NativeFunction> NativeFunction::create(Realm& realm, FlyString const& name, Function<ThrowCompletionOr<Value>(VM&)> function)
GC::Ref<NativeFunction> NativeFunction::create(Realm& realm, Utf16FlyString const& name, Function<ThrowCompletionOr<Value>(VM&)> function)
{
return realm.create<NativeFunction>(name, move(function), realm.intrinsics().function_prototype());
}
@ -91,7 +91,7 @@ NativeFunction::NativeFunction(Object& prototype)
{
}
NativeFunction::NativeFunction(FlyString name, AK::Function<ThrowCompletionOr<Value>(VM&)> native_function, Object& prototype)
NativeFunction::NativeFunction(Utf16FlyString name, AK::Function<ThrowCompletionOr<Value>(VM&)> native_function, Object& prototype)
: FunctionObject(prototype)
, m_name(move(name))
, m_native_function(move(native_function))
@ -99,7 +99,7 @@ NativeFunction::NativeFunction(FlyString name, AK::Function<ThrowCompletionOr<Va
{
}
NativeFunction::NativeFunction(FlyString name, Object& prototype)
NativeFunction::NativeFunction(Utf16FlyString name, Object& prototype)
: FunctionObject(prototype)
, m_name(move(name))
, m_realm(&prototype.shape().realm())

View File

@ -23,8 +23,8 @@ class JS_API NativeFunction : public FunctionObject {
GC_DECLARE_ALLOCATOR(NativeFunction);
public:
static GC::Ref<NativeFunction> create(Realm&, ESCAPING Function<ThrowCompletionOr<Value>(VM&)> behaviour, i32 length, PropertyKey const& name = FlyString {}, Optional<Realm*> = {}, Optional<StringView> const& prefix = {}, Optional<Bytecode::Builtin> builtin = {});
static GC::Ref<NativeFunction> create(Realm&, FlyString const& name, ESCAPING Function<ThrowCompletionOr<Value>(VM&)>);
static GC::Ref<NativeFunction> create(Realm&, ESCAPING Function<ThrowCompletionOr<Value>(VM&)> behaviour, i32 length, PropertyKey const& name = Utf16FlyString {}, Optional<Realm*> = {}, Optional<StringView> const& prefix = {}, Optional<Bytecode::Builtin> builtin = {});
static GC::Ref<NativeFunction> create(Realm&, Utf16FlyString const& name, ESCAPING Function<ThrowCompletionOr<Value>(VM&)>);
virtual ~NativeFunction() override = default;
@ -36,13 +36,13 @@ public:
virtual ThrowCompletionOr<Value> call();
virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target);
FlyString const& name() const { return m_name; }
Utf16FlyString const& name() const { return m_name; }
virtual bool is_strict_mode() const override;
virtual bool has_constructor() const override { return false; }
virtual Realm* realm() const override { return m_realm; }
Optional<FlyString> const& initial_name() const { return m_initial_name; }
void set_initial_name(Badge<FunctionObject>, FlyString initial_name) { m_initial_name = move(initial_name); }
Optional<Utf16FlyString> const& initial_name() const { return m_initial_name; }
void set_initial_name(Badge<FunctionObject>, Utf16FlyString initial_name) { m_initial_name = move(initial_name); }
bool is_array_prototype_next_builtin() const { return m_builtin.has_value() && *m_builtin == Bytecode::Builtin::ArrayIteratorPrototypeNext; }
bool is_map_prototype_next_builtin() const { return m_builtin.has_value() && *m_builtin == Bytecode::Builtin::MapIteratorPrototypeNext; }
@ -50,9 +50,9 @@ public:
bool is_string_prototype_next_builtin() const { return m_builtin.has_value() && *m_builtin == Bytecode::Builtin::StringIteratorPrototypeNext; }
protected:
NativeFunction(FlyString name, Object& prototype);
NativeFunction(Utf16FlyString name, Object& prototype);
NativeFunction(AK::Function<ThrowCompletionOr<Value>(VM&)>, Object* prototype, Realm& realm, Optional<Bytecode::Builtin> builtin);
NativeFunction(FlyString name, AK::Function<ThrowCompletionOr<Value>(VM&)>, Object& prototype);
NativeFunction(Utf16FlyString name, AK::Function<ThrowCompletionOr<Value>(VM&)>, Object& prototype);
explicit NativeFunction(Object& prototype);
virtual void initialize(Realm&) override;
@ -61,9 +61,9 @@ protected:
private:
virtual bool is_native_function() const final { return true; }
FlyString m_name;
Utf16FlyString m_name;
GC::Ptr<PrimitiveString> m_name_string;
Optional<FlyString> m_initial_name; // [[InitialName]]
Optional<Utf16FlyString> m_initial_name; // [[InitialName]]
Optional<Bytecode::Builtin> m_builtin;
AK::Function<ThrowCompletionOr<Value>(VM&)> m_native_function;
GC::Ptr<Realm> m_realm;

View File

@ -29,7 +29,7 @@ namespace JS {
GC_DEFINE_ALLOCATOR(Object);
static HashMap<GC::Ptr<Object const>, HashMap<FlyString, Object::IntrinsicAccessor>> s_intrinsics;
static HashMap<GC::Ptr<Object const>, HashMap<Utf16FlyString, Object::IntrinsicAccessor>> s_intrinsics;
// 10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinaryobjectcreate
GC::Ref<Object> Object::create(Realm& realm, Object* prototype)
@ -1407,7 +1407,7 @@ Optional<Completion> Object::enumerate_object_properties(Function<Optional<Compl
// * Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively.
// * A property of a prototype is not processed if it has the same name as a property that has already been processed.
HashTable<FlyString> visited;
HashTable<Utf16FlyString> visited;
auto const* target = this;
while (target) {
@ -1415,7 +1415,7 @@ Optional<Completion> Object::enumerate_object_properties(Function<Optional<Compl
for (auto& key : own_keys) {
if (!key.is_string())
continue;
FlyString property_key = key.as_string().utf8_string();
Utf16FlyString property_key = key.as_string().utf16_string();
if (visited.contains(property_key))
continue;
auto descriptor = TRY(target->internal_get_own_property(property_key));

View File

@ -27,7 +27,7 @@ void ObjectEnvironment::visit_edges(Cell::Visitor& visitor)
}
// 9.1.1.2.1 HasBinding ( N ), https://tc39.es/ecma262/#sec-object-environment-records-hasbinding-n
ThrowCompletionOr<bool> ObjectEnvironment::has_binding(FlyString const& name, Optional<size_t>*) const
ThrowCompletionOr<bool> ObjectEnvironment::has_binding(Utf16FlyString const& name, Optional<size_t>*) const
{
auto& vm = this->vm();
@ -62,7 +62,7 @@ ThrowCompletionOr<bool> ObjectEnvironment::has_binding(FlyString const& name, Op
}
// 9.1.1.2.2 CreateMutableBinding ( N, D ), https://tc39.es/ecma262/#sec-object-environment-records-createmutablebinding-n-d
ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted)
ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(VM&, Utf16FlyString const& name, bool can_be_deleted)
{
// 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Perform ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
@ -73,14 +73,14 @@ ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(VM&, FlyString
}
// 9.1.1.2.3 CreateImmutableBinding ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s
ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(VM&, FlyString const&, bool)
ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(VM&, Utf16FlyString const&, bool)
{
// "The CreateImmutableBinding concrete method of an object Environment Record is never used within this specification."
VERIFY_NOT_REACHED();
}
// 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, FlyString const& name, Value value, Environment::InitializeBindingHint hint)
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, Utf16FlyString const& name, Value value, Environment::InitializeBindingHint hint)
{
// 1. Assert: hint is normal.
VERIFY(hint == Environment::InitializeBindingHint::Normal);
@ -93,7 +93,7 @@ ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(VM& vm, FlyString
}
// 9.1.1.2.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s
ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(VM&, FlyString const& name, Value value, bool strict)
ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(VM&, Utf16FlyString const& name, Value value, bool strict)
{
auto& vm = this->vm();
@ -135,7 +135,7 @@ ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(VM&, FlyString co
}
// 9.1.1.2.6 GetBindingValue ( N, S ), https://tc39.es/ecma262/#sec-object-environment-records-getbindingvalue-n-s
ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(VM&, FlyString const& name, bool strict)
ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(VM&, Utf16FlyString const& name, bool strict)
{
auto& vm = this->vm();
@ -164,7 +164,7 @@ ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(VM&, FlyString con
}
// 9.1.1.2.7 DeleteBinding ( N ), https://tc39.es/ecma262/#sec-object-environment-records-deletebinding-n
ThrowCompletionOr<bool> ObjectEnvironment::delete_binding(VM&, FlyString const& name)
ThrowCompletionOr<bool> ObjectEnvironment::delete_binding(VM&, Utf16FlyString const& name)
{
// 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Return ? bindingObject.[[Delete]](N).

View File

@ -20,13 +20,13 @@ public:
Yes,
};
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value, Environment::InitializeBindingHint) override;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override;
virtual ThrowCompletionOr<bool> has_binding(Utf16FlyString const& name, Optional<size_t>* = nullptr) const override;
virtual ThrowCompletionOr<void> create_mutable_binding(VM&, Utf16FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(VM&, Utf16FlyString const& name, Value, Environment::InitializeBindingHint) override;
virtual ThrowCompletionOr<void> set_mutable_binding(VM&, Utf16FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(VM&, Utf16FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(VM&, Utf16FlyString const& name) override;
// 9.1.1.2.10 WithBaseObject ( ), https://tc39.es/ecma262/#sec-object-environment-records-withbaseobject
virtual Object* with_base_object() const override

View File

@ -21,7 +21,7 @@ PrivateEnvironment::PrivateEnvironment(PrivateEnvironment* parent)
// Note: we start at one such that 0 can be invalid / default initialized.
u64 PrivateEnvironment::s_next_id = 1u;
PrivateName PrivateEnvironment::resolve_private_identifier(FlyString const& identifier) const
PrivateName PrivateEnvironment::resolve_private_identifier(Utf16FlyString const& identifier) const
{
auto name_or_end = find_private_name(identifier);
@ -34,7 +34,7 @@ PrivateName PrivateEnvironment::resolve_private_identifier(FlyString const& iden
return m_outer_environment->resolve_private_identifier(identifier);
}
void PrivateEnvironment::add_private_name(FlyString description)
void PrivateEnvironment::add_private_name(Utf16FlyString description)
{
if (!find_private_name(description).is_end())
return;

View File

@ -6,8 +6,8 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/StringView.h>
#include <AK/Utf16FlyString.h>
#include <AK/Vector.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Heap/Cell.h>
@ -16,14 +16,14 @@ namespace JS {
struct PrivateName {
PrivateName() = default;
PrivateName(u64 unique_id, FlyString description)
PrivateName(u64 unique_id, Utf16FlyString description)
: unique_id(unique_id)
, description(move(description))
{
}
u64 unique_id { 0 };
FlyString description;
Utf16FlyString description;
bool operator==(PrivateName const& rhs) const;
};
@ -33,9 +33,9 @@ class PrivateEnvironment : public Cell {
GC_DECLARE_ALLOCATOR(PrivateEnvironment);
public:
PrivateName resolve_private_identifier(FlyString const& identifier) const;
PrivateName resolve_private_identifier(Utf16FlyString const& identifier) const;
void add_private_name(FlyString description);
void add_private_name(Utf16FlyString description);
PrivateEnvironment* outer_environment() { return m_outer_environment; }
PrivateEnvironment const* outer_environment() const { return m_outer_environment; }
@ -45,7 +45,7 @@ private:
virtual void visit_edges(Visitor&) override;
auto find_private_name(FlyString const& description) const
auto find_private_name(Utf16FlyString const& description) const
{
return m_private_names.find_if([&](PrivateName const& private_name) {
return private_name.description == description;

View File

@ -7,7 +7,7 @@
#pragma once
#include <AK/FlyString.h>
#include <AK/Utf16FlyString.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Symbol.h>
@ -28,7 +28,7 @@ public:
return PropertyKey { value.as_symbol() };
if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::max())
return static_cast<u32>(value.as_double());
return TRY(value.to_string(vm));
return TRY(value.to_utf16_string(vm));
}
static constexpr uintptr_t NORMAL_STRING_FLAG = 0;
@ -45,7 +45,7 @@ public:
PropertyKey(PropertyKey const& other)
{
if (other.is_string())
new (&m_string) FlyString(other.m_string);
new (&m_string) Utf16FlyString(other.m_string);
else
m_bits = other.m_bits;
}
@ -53,7 +53,7 @@ public:
PropertyKey(PropertyKey&& other) noexcept
{
if (other.is_string())
new (&m_string) FlyString(move(other.m_string));
new (&m_string) Utf16FlyString(move(other.m_string));
else
m_bits = exchange(other.m_bits, 0);
}
@ -66,30 +66,30 @@ public:
VERIFY(index >= 0);
if constexpr (NumericLimits<T>::max() >= NumericLimits<u32>::max()) {
if (index >= NumericLimits<u32>::max()) {
new (&m_string) FlyString { String::number(index) };
new (&m_string) Utf16FlyString { Utf16String::number(index) };
return;
}
}
m_number = static_cast<u64>(index) << 2 | NUMBER_FLAG;
}
PropertyKey(FlyString string, StringMayBeNumber string_may_be_number = StringMayBeNumber::Yes)
PropertyKey(Utf16FlyString string, StringMayBeNumber string_may_be_number = StringMayBeNumber::Yes)
{
if (string_may_be_number == StringMayBeNumber::Yes) {
auto view = string.bytes_as_string_view();
if (!view.is_empty() && !(view[0] == '0' && view.length() > 1)) {
auto property_index = view.to_number<u32>(TrimWhitespace::No);
if (!string.is_empty() && !(string.code_unit_at(0) == '0' && string.length_in_code_units() > 1)) {
auto property_index = string.to_number<u32>(TrimWhitespace::No);
if (property_index.has_value() && property_index.value() < NumericLimits<u32>::max()) {
m_number = static_cast<u64>(property_index.release_value()) << 2 | NUMBER_FLAG;
return;
}
}
}
new (&m_string) FlyString(move(string));
new (&m_string) Utf16FlyString(move(string));
}
PropertyKey(String const& string)
: PropertyKey(FlyString(string))
PropertyKey(Utf16String const& string)
: PropertyKey(Utf16FlyString { string })
{
}
@ -102,7 +102,7 @@ public:
{
if (this != &other) {
if (is_string())
m_string.~FlyString();
m_string.~Utf16FlyString();
new (this) PropertyKey(other);
}
return *this;
@ -112,7 +112,7 @@ public:
{
if (this != &other) {
if (is_string())
m_string.~FlyString();
m_string.~Utf16FlyString();
new (this) PropertyKey(move(other));
}
return *this;
@ -121,7 +121,7 @@ public:
~PropertyKey()
{
if (is_string())
m_string.~FlyString();
m_string.~Utf16FlyString();
}
u32 as_number() const
@ -130,7 +130,7 @@ public:
return m_number >> 2;
}
FlyString const& as_string() const
Utf16FlyString const& as_string() const
{
VERIFY(is_string());
return m_string;
@ -151,13 +151,13 @@ public:
return Value { PrimitiveString::create(vm, String::number(as_number())) };
}
String to_string() const
Utf16String to_string() const
{
if (is_string())
return as_string().to_string();
return as_string().to_utf16_string();
if (is_symbol())
return MUST(as_symbol()->descriptive_string());
return String::number(as_number());
return as_symbol()->descriptive_string();
return Utf16String::number(as_number());
}
void visit_edges(Cell::Visitor& visitor) const
@ -181,7 +181,7 @@ private:
friend Traits<PropertyKey>;
union {
FlyString m_string;
Utf16FlyString m_string;
u64 m_number;
Symbol const* m_symbol;
uintptr_t m_bits;
@ -220,12 +220,12 @@ struct Traits<JS::PropertyKey> : public DefaultTraits<JS::PropertyKey> {
};
template<>
struct Formatter<JS::PropertyKey> : Formatter<StringView> {
struct Formatter<JS::PropertyKey> : Formatter<Utf16String> {
ErrorOr<void> format(FormatBuilder& builder, JS::PropertyKey const& property_key)
{
if (property_key.is_number())
return builder.put_u64(property_key.as_number());
return builder.put_string(property_key.to_string());
return Formatter<Utf16String>::format(builder, property_key.to_string());
}
};

View File

@ -208,7 +208,7 @@ ThrowCompletionOr<void> Reference::initialize_referenced_binding(VM& vm, Value v
}
// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
Reference make_private_reference(VM& vm, Value base_value, FlyString const& private_identifier)
Reference make_private_reference(VM& vm, Value base_value, Utf16FlyString const& private_identifier)
{
// 1. Let privEnv be the running execution context's PrivateEnvironment.
auto private_environment = vm.running_execution_context().private_environment;

View File

@ -13,7 +13,7 @@
namespace JS {
Reference make_private_reference(VM&, Value base_value, FlyString const& private_identifier);
Reference make_private_reference(VM&, Value base_value, Utf16FlyString const& private_identifier);
class Reference {
public:
@ -39,7 +39,7 @@ public:
{
}
Reference(Environment& base, FlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
Reference(Environment& base, Utf16FlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
: m_base_type(BaseType::Environment)
, m_base_environment(&base)
, m_name(move(referenced_name))

View File

@ -100,7 +100,7 @@ static Value get_match_index_pair(VM& vm, Utf16View const& string, Match const&
}
// 22.2.7.8 MakeMatchIndicesIndexPairArray ( S, indices, groupNames, hasGroups ), https://tc39.es/ecma262/#sec-makematchindicesindexpairarray
static Value make_match_indices_index_pair_array(VM& vm, Utf16View const& string, Vector<Optional<Match>> const& indices, HashMap<FlyString, Match> const& group_names, bool has_groups)
static Value make_match_indices_index_pair_array(VM& vm, Utf16View const& string, Vector<Optional<Match>> const& indices, HashMap<Utf16FlyString, Match> const& group_names, bool has_groups)
{
// Note: This implementation differs from the spec, but has the same behavior.
//
@ -277,7 +277,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
Vector<Utf16String> captured_values;
// 26. Let groupNames be a new empty List.
HashMap<FlyString, Match> group_names;
HashMap<Utf16FlyString, Match> group_names;
// 27. Add match as the last element of indices.
indices.append(move(match_indices));
@ -334,7 +334,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// e. If the ith capture of R was defined with a GroupName, then
if (capture.capture_group_name >= 0) {
// i. Let s be the CapturingGroupName of the corresponding RegExpIdentifierName.
auto group_name = regex.parser_result.bytecode.get_string(capture.capture_group_name);
auto group_name = Utf16FlyString::from_utf8(regex.parser_result.bytecode.get_string(capture.capture_group_name));
// ii. Perform ! CreateDataPropertyOrThrow(groups, s, capturedValue).
MUST(groups_object->create_data_property_or_throw(group_name, captured_value));

View File

@ -87,7 +87,7 @@ ThrowCompletionOr<void> copy_name_and_length(VM& vm, FunctionObject& function, F
target_name = PrimitiveString::create(vm, String {});
// 8. Perform SetFunctionName(F, targetName, prefix).
function.set_function_name({ target_name.as_string().utf8_string() }, move(prefix));
function.set_function_name({ target_name.as_string().utf16_string() }, move(prefix));
return {};
}
@ -149,7 +149,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(VM& vm, Value source, Realm&
// 5. If runningContext is not already suspended, suspend runningContext.
// NOTE: This would be unused due to step 9 and is omitted for that reason.
auto maybe_executable = Bytecode::compile(vm, program, FunctionKind::Normal, "ShadowRealmEval"_fly_string);
auto maybe_executable = Bytecode::compile(vm, program, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
if (maybe_executable.is_error())
return vm.throw_completion<TypeError>(ErrorType::ShadowRealmEvaluateAbruptCompletion);
auto executable = maybe_executable.release_value();
@ -242,7 +242,7 @@ ThrowCompletionOr<Value> 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 = move(export_name_string)](auto& vm) -> ThrowCompletionOr<Value> {
auto steps = [string = Utf16String::from_utf8(export_name_string)](auto& vm) -> ThrowCompletionOr<Value> {
// 1. Assert: exports is a module namespace exotic object.
VERIFY(vm.argument(0).is_object());
auto& exports = vm.argument(0).as_object();
@ -274,7 +274,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(VM& vm, String specifier_stri
// 10. Let onFulfilled be CreateBuiltinFunction(steps, 1, "", « [[ExportNameString]] », callerRealm).
// 11. Set onFulfilled.[[ExportNameString]] to exportNameString.
auto on_fulfilled = NativeFunction::create(realm, move(steps), 1, FlyString {}, &caller_realm);
auto on_fulfilled = NativeFunction::create(realm, move(steps), 1, Utf16FlyString {}, &caller_realm);
// 12. Let promiseCapability be ! NewPromiseCapability(%Promise%).
auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor()));

View File

@ -54,7 +54,7 @@ ThrowCompletionOr<Value> StringConstructor::call()
// 2. Else,
// a. If NewTarget is undefined and value is a Symbol, return SymbolDescriptiveString(value).
if (value.is_symbol())
return PrimitiveString::create(vm, MUST(value.as_symbol().descriptive_string()));
return PrimitiveString::create(vm, value.as_symbol().descriptive_string());
// b. Let s be ? ToString(value).
// 3. If NewTarget is undefined, return s.

View File

@ -13,31 +13,31 @@ namespace JS {
GC_DEFINE_ALLOCATOR(Symbol);
Symbol::Symbol(Optional<String> description, bool is_global)
Symbol::Symbol(Optional<Utf16String> description, bool is_global)
: m_description(move(description))
, m_is_global(is_global)
{
}
GC::Ref<Symbol> Symbol::create(VM& vm, Optional<String> description, bool is_global)
GC::Ref<Symbol> Symbol::create(VM& vm, Optional<Utf16String> description, bool is_global)
{
return vm.heap().allocate<Symbol>(move(description), is_global);
}
// 20.4.3.3.1 SymbolDescriptiveString ( sym ), https://tc39.es/ecma262/#sec-symboldescriptivestring
ErrorOr<String> Symbol::descriptive_string() const
Utf16String Symbol::descriptive_string() const
{
// 1. Let desc be sym's [[Description]] value.
// 2. If desc is undefined, set desc to the empty String.
// 3. Assert: desc is a String.
auto description = m_description.value_or(String {});
auto description = m_description.value_or({});
// 4. Return the string-concatenation of "Symbol(", desc, and ")".
return String::formatted("Symbol({})", description);
return Utf16String::formatted("Symbol({})", description);
}
// 20.4.5.1 KeyForSymbol ( sym ), https://tc39.es/ecma262/#sec-keyforsymbol
Optional<String> Symbol::key() const
Optional<Utf16String> Symbol::key() const
{
// 1. For each element e of the GlobalSymbolRegistry List, do
// a. If SameValue(e.[[Symbol]], sym) is true, return e.[[Key]].

View File

@ -7,7 +7,7 @@
#pragma once
#include <AK/String.h>
#include <AK/Utf16String.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Export.h>
#include <LibJS/Heap/Cell.h>
@ -19,20 +19,20 @@ class JS_API Symbol final : public Cell {
GC_DECLARE_ALLOCATOR(Symbol);
public:
[[nodiscard]] static GC::Ref<Symbol> create(VM&, Optional<String> description, bool is_global);
[[nodiscard]] static GC::Ref<Symbol> create(VM&, Optional<Utf16String> description, bool is_global);
virtual ~Symbol() = default;
Optional<String> const& description() const { return m_description; }
Optional<Utf16String> const& description() const { return m_description; }
bool is_global() const { return m_is_global; }
ErrorOr<String> descriptive_string() const;
Optional<String> key() const;
Utf16String descriptive_string() const;
Optional<Utf16String> key() const;
private:
Symbol(Optional<String>, bool);
Symbol(Optional<Utf16String>, bool);
Optional<String> m_description;
Optional<Utf16String> m_description;
bool m_is_global;
};

View File

@ -47,8 +47,8 @@ ThrowCompletionOr<Value> SymbolConstructor::call()
// 2. If description is undefined, let descString be undefined.
// 3. Else, let descString be ? ToString(description).
auto description_string = description.is_undefined()
? Optional<String> {}
: TRY(description.to_string(vm));
? Optional<Utf16String> {}
: TRY(description.to_utf16_string(vm));
// 4. Return a new Symbol whose [[Description]] is descString.
return Symbol::create(vm, move(description_string), false);
@ -65,7 +65,7 @@ ThrowCompletionOr<GC::Ref<Object>> SymbolConstructor::construct(FunctionObject&)
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
{
// 1. Let stringKey be ? ToString(key).
auto string_key = TRY(vm.argument(0).to_string(vm));
auto string_key = TRY(vm.argument(0).to_utf16_string(vm));
// 2. For each element e of the GlobalSymbolRegistry List, do
auto result = vm.global_symbol_registry().get(string_key);

View File

@ -79,7 +79,7 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::to_string)
auto symbol = TRY(this_symbol_value(vm, vm.this_value()));
// 2. Return SymbolDescriptiveString(sym).
return PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, symbol->descriptive_string()));
return PrimitiveString::create(vm, symbol->descriptive_string());
}
// 20.4.3.4 Symbol.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-symbol.prototype.valueof

View File

@ -78,7 +78,7 @@ static Vector<CalendarFieldData> sorted_calendar_fields(VM& vm, CalendarFieldLis
result.unchecked_append(data_for_field(field));
quick_sort(result, [](auto const& lhs, auto const& rhs) {
return StringView { lhs.property->as_string() } < StringView { rhs.property->as_string() };
return lhs.property->as_string() < rhs.property->as_string();
});
return result;

View File

@ -449,6 +449,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
GC_DEFINE_ALLOCATOR(ClassName); \
GC_DEFINE_ALLOCATOR(PrototypeName); \
GC_DEFINE_ALLOCATOR(ConstructorName); \
\
ThrowCompletionOr<GC::Ref<ClassName>> ClassName::create(Realm& realm, u32 length, FunctionObject& new_target) \
{ \
auto* prototype = TRY(get_prototype_from_constructor(realm.vm(), new_target, &Intrinsics::snake_name##_prototype)); \
@ -480,7 +481,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
{ \
} \
\
FlyString const& ClassName::element_name() const \
Utf16FlyString const& ClassName::element_name() const \
{ \
return vm().names.ClassName.as_string(); \
} \

View File

@ -50,7 +50,7 @@ public:
[[nodiscard]] Kind kind() const { return m_kind; }
u32 element_size() const { return m_element_size; }
virtual FlyString const& element_name() const = 0;
virtual Utf16FlyString const& element_name() const = 0;
// 25.1.3.11 IsUnclampedIntegerElementType ( type ), https://tc39.es/ecma262/#sec-isunclampedintegerelementtype
virtual bool is_unclamped_integer_element_type() const = 0;
@ -524,7 +524,7 @@ ThrowCompletionOr<double> compare_typed_array_elements(VM&, Value x, Value y, Fu
static ThrowCompletionOr<GC::Ref<ClassName>> create(Realm&, u32 length, FunctionObject& new_target); \
static ThrowCompletionOr<GC::Ref<ClassName>> create(Realm&, u32 length); \
static GC::Ref<ClassName> create(Realm&, u32 length, ArrayBuffer& buffer); \
virtual FlyString const& element_name() const override; \
virtual Utf16FlyString const& element_name() const override; \
virtual GC::Ref<NativeFunction> intrinsic_constructor(Realm&) const override; \
\
protected: \

View File

@ -13,7 +13,7 @@ namespace JS {
GC_DEFINE_ALLOCATOR(TypedArrayConstructor);
TypedArrayConstructor::TypedArrayConstructor(FlyString const& name, Object& prototype)
TypedArrayConstructor::TypedArrayConstructor(Utf16FlyString const& name, Object& prototype)
: NativeFunction(name, prototype)
{
}

View File

@ -23,7 +23,7 @@ public:
virtual ThrowCompletionOr<GC::Ref<Object>> construct(FunctionObject& new_target) override;
protected:
TypedArrayConstructor(FlyString const& name, Object& prototype);
TypedArrayConstructor(Utf16FlyString const& name, Object& prototype);
private:
virtual bool has_constructor() const override { return true; }

View File

@ -46,7 +46,7 @@ NonnullRefPtr<VM> VM::create()
WellKnownSymbols well_known_symbols {
#define __JS_ENUMERATE(SymbolName, snake_name) \
Symbol::create(*vm, "Symbol." #SymbolName##_string, false),
Symbol::create(*vm, "Symbol." #SymbolName##_utf16, false),
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
#undef __JS_ENUMERATE
};
@ -284,7 +284,7 @@ void VM::gather_roots(HashMap<GC::Cell*, GC::HeapRoot>& roots)
}
// 9.1.2.1 GetIdentifierReference ( env, name, strict ), https://tc39.es/ecma262/#sec-getidentifierreference
ThrowCompletionOr<Reference> VM::get_identifier_reference(Environment* environment, FlyString name, bool strict, size_t hops)
ThrowCompletionOr<Reference> VM::get_identifier_reference(Environment* environment, Utf16FlyString name, bool strict, size_t hops)
{
// 1. If env is the value null, then
if (!environment) {
@ -318,7 +318,7 @@ ThrowCompletionOr<Reference> VM::get_identifier_reference(Environment* environme
}
// 9.4.2 ResolveBinding ( name [ , env ] ), https://tc39.es/ecma262/#sec-resolvebinding
ThrowCompletionOr<Reference> VM::resolve_binding(FlyString const& name, Environment* environment)
ThrowCompletionOr<Reference> VM::resolve_binding(Utf16FlyString const& name, Environment* environment)
{
// 1. If env is not present or if env is undefined, then
if (!environment) {

View File

@ -196,14 +196,14 @@ public:
StackInfo const& stack_info() const { return m_stack_info; }
HashMap<String, GC::Ref<Symbol>> const& global_symbol_registry() const { return m_global_symbol_registry; }
HashMap<String, GC::Ref<Symbol>>& global_symbol_registry() { return m_global_symbol_registry; }
HashMap<Utf16String, GC::Ref<Symbol>> const& global_symbol_registry() const { return m_global_symbol_registry; }
HashMap<Utf16String, GC::Ref<Symbol>>& global_symbol_registry() { return m_global_symbol_registry; }
u32 execution_generation() const { return m_execution_generation; }
void finish_execution_generation() { ++m_execution_generation; }
ThrowCompletionOr<Reference> resolve_binding(FlyString const&, Environment* = nullptr);
ThrowCompletionOr<Reference> get_identifier_reference(Environment*, FlyString, bool strict, size_t hops = 0);
ThrowCompletionOr<Reference> resolve_binding(Utf16FlyString const&, Environment* = nullptr);
ThrowCompletionOr<Reference> get_identifier_reference(Environment*, Utf16FlyString, bool strict, size_t hops = 0);
// 5.2.3.2 Throw an Exception, https://tc39.es/ecma262/#sec-throw-an-exception
template<typename T, typename... Args>
@ -333,7 +333,7 @@ private:
StackInfo m_stack_info;
// GlobalSymbolRegistry, https://tc39.es/ecma262/#table-globalsymbolregistry-record-fields
HashMap<String, GC::Ref<Symbol>> m_global_symbol_registry;
HashMap<Utf16String, GC::Ref<Symbol>> m_global_symbol_registry;
Vector<GC::Ref<GC::Function<ThrowCompletionOr<Value>()>>> m_promise_jobs;

View File

@ -383,7 +383,7 @@ String Value::to_string_without_side_effects() const
case STRING_TAG:
return as_string().utf8_string();
case SYMBOL_TAG:
return as_symbol().descriptive_string().release_value();
return as_symbol().descriptive_string().to_utf8_but_should_be_ported_to_utf16();
case BIGINT_TAG:
return as_bigint().to_string().release_value();
case OBJECT_TAG:
@ -909,7 +909,7 @@ ThrowCompletionOr<PropertyKey> Value::to_property_key(VM& vm) const
// OPTIMIZATION: If this is already a string, we can skip all the ceremony.
if (is_string())
return PropertyKey { as_string().utf8_string() };
return PropertyKey { as_string().utf16_string() };
// 1. Let key be ? ToPrimitive(argument, string).
auto key = TRY(to_primitive(vm, PreferredType::String));
@ -921,7 +921,7 @@ ThrowCompletionOr<PropertyKey> Value::to_property_key(VM& vm) const
}
// 3. Return ! ToString(key).
return MUST(key.to_string(vm));
return MUST(key.to_utf16_string(vm));
}
// 7.1.6 ToInt32 ( argument ), https://tc39.es/ecma262/#sec-toint32

View File

@ -262,7 +262,7 @@ Result<GC::Ref<SourceTextModule>, Vector<ParserError>> SourceTextModule::parse(S
}
// 16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] ), https://tc39.es/ecma262/#sec-getexportednames
Vector<FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module const*>& export_star_set)
Vector<Utf16FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module const*>& export_star_set)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] get_export_names of {}", filename());
@ -285,7 +285,7 @@ Vector<FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module
export_star_set.set(this);
// 5. Let exportedNames be a new empty List.
Vector<FlyString> exported_names;
Vector<Utf16FlyString> exported_names;
// 6. For each ExportEntry Record e of module.[[LocalExportEntries]], do
for (auto const& entry : m_local_export_entries) {
@ -296,7 +296,7 @@ Vector<FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module
VERIFY(entry.export_name.has_value());
// c. Append e.[[ExportName]] to exportedNames.
exported_names.empend(entry.export_name.value());
exported_names.empend(Utf16FlyString::from_utf8(entry.export_name.value()));
}
// 7. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
@ -308,7 +308,7 @@ Vector<FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module
VERIFY(entry.export_name.has_value());
// c. Append e.[[ExportName]] to exportedNames.
exported_names.empend(entry.export_name.value());
exported_names.empend(Utf16FlyString::from_utf8(entry.export_name.value()));
}
// 8. For each ExportEntry Record e of module.[[StarExportEntries]], do
@ -346,7 +346,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
VERIFY(entry.export_name.has_value());
// a. Let resolution be module.ResolveExport(e.[[ExportName]]).
auto resolution = resolve_export(vm, entry.export_name.value());
auto resolution = resolve_export(vm, Utf16FlyString::from_utf8(entry.export_name.value()));
// b. If resolution is either null or AMBIGUOUS, throw a SyntaxError exception.
if (!resolution.is_valid())
@ -371,6 +371,8 @@ ThrowCompletionOr<void> 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());
@ -380,19 +382,21 @@ ThrowCompletionOr<void> 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, import_entry.local_name, true));
MUST(environment->create_immutable_binding(vm, local_name, true));
// iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_, Environment::InitializeBindingHint::Normal));
MUST(environment->initialize_binding(vm, local_name, namespace_, Environment::InitializeBindingHint::Normal));
}
// c. Else,
else {
auto import_name = Utf16FlyString::from_utf8(import_entry.import_name.value());
// i. Let resolution be importedModule.ResolveExport(in.[[ImportName]]).
auto resolution = imported_module->resolve_export(vm, import_entry.import_name.value());
auto resolution = imported_module->resolve_export(vm, import_name);
// ii. If resolution is either null or AMBIGUOUS, throw a SyntaxError exception.
if (!resolution.is_valid())
return vm.throw_completion<SyntaxError>(ErrorType::InvalidOrAmbiguousExportEntry, import_entry.import_name);
return vm.throw_completion<SyntaxError>(ErrorType::InvalidOrAmbiguousExportEntry, import_name);
// iii. If resolution.[[BindingName]] is NAMESPACE, then
if (resolution.is_namespace()) {
@ -400,15 +404,15 @@ ThrowCompletionOr<void> 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, import_entry.local_name, true));
MUST(environment->create_immutable_binding(vm, local_name, true));
// 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
MUST(environment->initialize_binding(vm, import_entry.local_name, namespace_, Environment::InitializeBindingHint::Normal));
MUST(environment->initialize_binding(vm, local_name, namespace_, Environment::InitializeBindingHint::Normal));
}
// iv. Else,
else {
// 1. Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
MUST(environment->create_import_binding(import_entry.local_name, resolution.module, resolution.export_name));
MUST(environment->create_import_binding(local_name, resolution.module, resolution.export_name));
}
}
}
@ -447,14 +451,15 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
// NOTE: We just loop through them in step 21.
// 20. Let declaredVarNames be a new empty List.
Vector<FlyString> declared_var_names;
Vector<Utf16FlyString> declared_var_names;
// 21. For each element d of varDeclarations, do
// a. For each element dn of the BoundNames of d, do
// 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([&](auto const& identifier) {
auto const& name = identifier.string();
MUST(m_ecmascript_code->for_each_var_declared_identifier([&](Identifier const& identifier) {
auto name = Utf16FlyString::from_utf8(identifier.string());
// i. If dn is not an element of declaredVarNames, then
if (!declared_var_names.contains_slow(name)) {
// 1. Perform ! env.CreateMutableBinding(dn, false).
@ -478,8 +483,9 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
// NOTE: Due to the use of MUST in the callback, an exception should not result from `for_each_lexically_scoped_declaration`.
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([&](auto const& identifier) {
auto const& name = identifier.string();
MUST(declaration.for_each_bound_identifier([&](Identifier const& identifier) {
auto name = Utf16FlyString::from_utf8(identifier.string());
// i. If IsConstantDeclaration of d is true, then
if (declaration.is_constant_declaration()) {
// 1. Perform ! env.CreateImmutableBinding(dn, true).
@ -504,7 +510,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
function_name = "default"_fly_string;
auto function = ECMAScriptFunctionObject::create_from_function_node(
function_declaration,
function_name,
Utf16FlyString::from_utf8(function_name),
realm,
environment,
private_environment);
@ -522,11 +528,11 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
VERIFY(m_default_export->has_statement());
if (auto const& statement = m_default_export->statement(); !is<Declaration>(statement)) {
auto const& name = m_default_export->entries()[0].local_or_import_name;
auto name = Utf16FlyString::from_utf8(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).
MUST(environment->create_mutable_binding(vm, name.value(), false));
MUST(environment->create_mutable_binding(vm, name, false));
// NOTE: Since this is not a function declaration 24.a.iii never applies
}
@ -540,7 +546,7 @@ ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
}
// 16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] ), https://tc39.es/ecma262/#sec-resolveexport
ResolvedBinding SourceTextModule::resolve_export(VM& vm, FlyString const& export_name, Vector<ResolvedBinding> resolve_set)
ResolvedBinding SourceTextModule::resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set)
{
// 1. Assert: module.[[Status]] is not NEW.
VERIFY(m_status != ModuleStatus::New);
@ -575,7 +581,7 @@ ResolvedBinding SourceTextModule::resolve_export(VM& vm, FlyString const& export
return ResolvedBinding {
ResolvedBinding::Type::BindingName,
this,
entry.local_or_import_name.value(),
Utf16FlyString::from_utf8(entry.local_or_import_name.value()),
};
}
@ -607,7 +613,7 @@ ResolvedBinding SourceTextModule::resolve_export(VM& vm, FlyString const& export
// FIXME: What does this mean? / How do we check this
// 2. Return importedModule.ResolveExport(e.[[ImportName]], resolveSet).
return imported_module->resolve_export(vm, entry.local_or_import_name.value(), resolve_set);
return imported_module->resolve_export(vm, Utf16FlyString::from_utf8(entry.local_or_import_name.value()), resolve_set);
}
}
@ -685,7 +691,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GC::Ptr<Promise
if (!m_has_top_level_await) {
Completion result;
auto maybe_executable = Bytecode::compile(vm, m_ecmascript_code, FunctionKind::Normal, "ShadowRealmEval"_fly_string);
auto maybe_executable = Bytecode::compile(vm, m_ecmascript_code, FunctionKind::Normal, "ShadowRealmEval"_utf16_fly_string);
if (maybe_executable.is_error()) {
result = maybe_executable.release_error();
} else {
@ -787,7 +793,7 @@ ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, GC::Ptr<Promise
parsing_insights.uses_this_from_environment = true;
parsing_insights.uses_this = true;
auto module_wrapper_function = ECMAScriptFunctionObject::create(
realm(), "module code with top-level await"_fly_string, StringView {}, this->m_ecmascript_code,
realm(), "module code with top-level await"_utf16_fly_string, StringView {}, this->m_ecmascript_code,
FunctionParameters::empty(), 0, {}, environment(), nullptr, FunctionKind::Async, true, parsing_insights);
module_wrapper_function->set_is_module_wrapper(true);

View File

@ -26,8 +26,8 @@ public:
Program const& parse_node() const { return *m_ecmascript_code; }
virtual Vector<FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) override;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) override;
Object* import_meta() { return m_import_meta; }
void set_import_meta(Badge<VM>, Object* import_meta) { m_import_meta = import_meta; }

View File

@ -18,7 +18,7 @@ namespace JS {
GC_DEFINE_ALLOCATOR(SyntheticModule);
SyntheticModule::SyntheticModule(Realm& realm, Vector<FlyString> export_names, SyntheticModule::EvaluationFunction evaluation_steps, ByteString filename)
SyntheticModule::SyntheticModule(Realm& realm, Vector<Utf16FlyString> export_names, SyntheticModule::EvaluationFunction evaluation_steps, ByteString filename)
: Module(realm, move(filename))
, m_export_names(move(export_names))
, m_evaluation_steps(evaluation_steps)
@ -40,14 +40,14 @@ GC::Ref<SyntheticModule> SyntheticModule::create_default_export_synthetic_module
// performs the following steps when called:
auto set_default_export = GC::create_function(realm.heap(), [default_export](SyntheticModule& module) -> ThrowCompletionOr<void> {
// a. Perform SetSyntheticModuleExport(module, "default", defaultExport).
TRY(module.set_synthetic_module_export("default"_fly_string, default_export));
TRY(module.set_synthetic_module_export("default"_utf16_fly_string, default_export));
// b. Return NormalCompletion(UNUSED).
return {};
});
// 2. Return the Synthetic Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }.
return realm.heap().allocate<SyntheticModule>(realm, Vector<FlyString> { "default"_fly_string }, set_default_export, move(filename));
return realm.heap().allocate<SyntheticModule>(realm, Vector<Utf16FlyString> { "default"_utf16_fly_string }, set_default_export, move(filename));
}
// 16.2.1.8.2 ParseJSONModule ( source ), https://tc39.es/ecma262/#sec-create-default-export-synthetic-module
@ -63,7 +63,7 @@ ThrowCompletionOr<GC::Ref<Module>> parse_json_module(Realm& realm, StringView so
}
// 16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue ), https://tc39.es/ecma262/#sec-setsyntheticmoduleexport
ThrowCompletionOr<void> SyntheticModule::set_synthetic_module_export(FlyString const& export_name, Value export_value)
ThrowCompletionOr<void> SyntheticModule::set_synthetic_module_export(Utf16FlyString const& export_name, Value export_value)
{
auto& vm = this->vm();
@ -99,14 +99,14 @@ PromiseCapability& SyntheticModule::load_requested_modules(GC::Ptr<GraphLoadingS
}
// 16.2.1.8.4.2 GetExportedNames ( ), https://tc39.es/ecma262/#sec-smr-getexportednames
Vector<FlyString> SyntheticModule::get_exported_names(VM&, HashTable<Module const*>&)
Vector<Utf16FlyString> SyntheticModule::get_exported_names(VM&, HashTable<Module const*>&)
{
// 1. Return module.[[ExportNames]].
return m_export_names;
}
// 16.2.1.8.4.3 ResolveExport ( exportName ), https://tc39.es/ecma262/#sec-smr-resolveexport
ResolvedBinding SyntheticModule::resolve_export(VM&, FlyString const& export_name, Vector<ResolvedBinding>)
ResolvedBinding SyntheticModule::resolve_export(VM&, Utf16FlyString const& export_name, Vector<ResolvedBinding>)
{
// 1. If module.[[ExportNames]] does not contain exportName, return null.
if (!m_export_names.contains_slow(export_name))

View File

@ -22,20 +22,20 @@ public:
static GC::Ref<SyntheticModule> create_default_export_synthetic_module(Realm& realm, Value default_export, ByteString filename);
ThrowCompletionOr<void> set_synthetic_module_export(FlyString const& export_name, Value export_value);
ThrowCompletionOr<void> set_synthetic_module_export(Utf16FlyString const& export_name, Value export_value);
virtual PromiseCapability& load_requested_modules(GC::Ptr<GraphLoadingState::HostDefined>) override;
virtual Vector<FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, FlyString const& export_name, Vector<ResolvedBinding> resolve_set) override;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set) override;
virtual ThrowCompletionOr<void> link(VM& vm) override;
virtual ThrowCompletionOr<GC::Ref<Promise>> evaluate(VM& vm) override;
private:
SyntheticModule(Realm& realm, Vector<FlyString> export_names, EvaluationFunction evaluation_steps, ByteString filename);
SyntheticModule(Realm& realm, Vector<Utf16FlyString> export_names, EvaluationFunction evaluation_steps, ByteString filename);
virtual void visit_edges(Cell::Visitor&) override;
Vector<FlyString> m_export_names; // [[ExportNames]]
Vector<Utf16FlyString> m_export_names; // [[ExportNames]]
EvaluationFunction m_evaluation_steps; // [[EvaluationSteps]]
};

View File

@ -55,9 +55,9 @@
} \
} __testjs_register_##fn {};
#define TESTJS_GLOBAL_FUNCTION(function, exposed_name, ...) \
JS_DECLARE_NATIVE_FUNCTION(function); \
__TESTJS_REGISTER_GLOBAL_FUNCTION(#exposed_name##_string, function, ##__VA_ARGS__); \
#define TESTJS_GLOBAL_FUNCTION(function, exposed_name, ...) \
JS_DECLARE_NATIVE_FUNCTION(function); \
__TESTJS_REGISTER_GLOBAL_FUNCTION(#exposed_name##_utf16, function, ##__VA_ARGS__); \
JS_DEFINE_NATIVE_FUNCTION(function)
#define TESTJS_MAIN_HOOK() \
@ -114,7 +114,7 @@ struct FunctionWithLength {
JS::ThrowCompletionOr<JS::Value> (*function)(JS::VM&);
size_t length { 0 };
};
extern HashMap<String, FunctionWithLength> s_exposed_global_functions;
extern HashMap<Utf16String, FunctionWithLength> s_exposed_global_functions;
extern ByteString g_test_root_fragment;
extern ByteString g_test_root;
extern int g_test_argc;
@ -182,11 +182,12 @@ inline void TestRunnerGlobalObject::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_direct_property("global"_fly_string, this, JS::Attribute::Enumerable);
define_direct_property("global"_utf16_fly_string, this, JS::Attribute::Enumerable);
for (auto& entry : s_exposed_global_functions) {
define_native_function(
realm,
entry.key, [fn = entry.value.function](auto& vm) {
entry.key,
[fn = entry.value.function](auto& vm) {
return fn(vm);
},
entry.value.length, JS::default_attributes);
@ -239,7 +240,7 @@ inline AK::Result<GC::Ref<JS::SourceTextModule>, ParserError> parse_module(Strin
inline ErrorOr<JsonValue> get_test_results(JS::Realm& realm)
{
auto results = MUST(realm.global_object().get("__TestResults__"_fly_string));
auto results = MUST(realm.global_object().get("__TestResults__"_utf16_fly_string));
auto maybe_json_string = MUST(JS::JSONObject::stringify_impl(*g_vm, results, JS::js_undefined(), JS::js_undefined()));
if (maybe_json_string.has_value())
return JsonValue::from_string(*maybe_json_string);
@ -359,7 +360,7 @@ inline JSFileResult TestRunner::run_file_test(ByteString const& test_path)
JSFileResult file_result { test_path.substring(m_test_root.length() + 1, test_path.length() - m_test_root.length() - 1) };
// Collect logged messages
auto user_output = MUST(realm->global_object().get("__UserOutput__"_fly_string));
auto user_output = MUST(realm->global_object().get("__UserOutput__"_utf16_fly_string));
auto& arr = user_output.as_array();
for (auto& entry : arr.indexed_properties()) {

View File

@ -24,7 +24,7 @@ namespace JS {
RefPtr<::JS::VM> g_vm;
bool g_collect_on_every_allocation = false;
ByteString g_currently_running_test;
HashMap<String, FunctionWithLength> s_exposed_global_functions;
HashMap<Utf16String, FunctionWithLength> s_exposed_global_functions;
Function<void()> g_main_hook;
HashMap<bool*, Tuple<ByteString, ByteString, char>> g_extra_args;
IntermediateRunFileResult (*g_run_file)(ByteString const&, JS::Realm&, JS::ExecutionContext&) = nullptr;

View File

@ -105,13 +105,13 @@ static WebIDL::ExceptionOr<KeyframeType<AL>> process_a_keyframe_like_object(JS::
return keyframe_output;
auto& keyframe_object = keyframe_input.as_object();
auto composite = TRY(keyframe_object.get("composite"_fly_string));
auto composite = TRY(keyframe_object.get("composite"_utf16_fly_string));
if (composite.is_undefined())
composite = JS::PrimitiveString::create(vm, "auto"_string);
auto easing = TRY(keyframe_object.get("easing"_fly_string));
auto easing = TRY(keyframe_object.get("easing"_utf16_fly_string));
if (easing.is_undefined())
easing = JS::PrimitiveString::create(vm, "linear"_string);
auto offset = TRY(keyframe_object.get("offset"_fly_string));
auto offset = TRY(keyframe_object.get("offset"_utf16_fly_string));
if constexpr (AL == AllowLists::Yes) {
keyframe_output.composite = TRY(convert_value_to_maybe_list(realm, composite, to_composite_operation));
@ -186,7 +186,7 @@ static WebIDL::ExceptionOr<KeyframeType<AL>> process_a_keyframe_like_object(JS::
// 1. Let raw value be the result of calling the [[Get]] internal method on keyframe input, with property name
// as the property key and keyframe input as the receiver.
// 2. Check the completion record of raw value.
JS::PropertyKey key { property_name, JS::PropertyKey::StringMayBeNumber::No };
JS::PropertyKey key { Utf16FlyString::from_utf8(property_name), JS::PropertyKey::StringMayBeNumber::No };
auto raw_value = TRY(keyframe_object.has_property(key)) ? TRY(keyframe_object.get(key)) : *all_value;
using PropertyValuesType = Conditional<AL == AllowLists::Yes, Vector<String>, String>;
@ -841,8 +841,9 @@ WebIDL::ExceptionOr<GC::RootVector<JS::Object*>> KeyframeEffect::get_keyframes()
}
for (auto const& [id, value] : keyframe.parsed_properties()) {
auto key = Utf16FlyString::from_utf8(CSS::camel_case_string_from_property_id(id));
auto value_string = JS::PrimitiveString::create(vm, value->to_string(CSS::SerializationMode::Normal));
TRY(object->set(JS::PropertyKey { CSS::camel_case_string_from_property_id(id), JS::PropertyKey::StringMayBeNumber::No }, value_string, ShouldThrowExceptions::Yes));
TRY(object->set(JS::PropertyKey { move(key), JS::PropertyKey::StringMayBeNumber::No }, value_string, ShouldThrowExceptions::Yes));
}
m_keyframe_objects.append(object);

View File

@ -411,8 +411,8 @@ void initialize_main_thread_vm(AgentType type)
// 5. Return « Record { [[Key]]: "url", [[Value]]: urlString }, Record { [[Key]]: "resolve", [[Value]]: resolveFunction } ».
HashMap<JS::PropertyKey, JS::Value> meta;
meta.set("url"_fly_string, JS::PrimitiveString::create(vm, move(url_string)));
meta.set("resolve"_fly_string, resolve_function);
meta.set("url"_utf16_fly_string, JS::PrimitiveString::create(vm, move(url_string)));
meta.set("resolve"_utf16_fly_string, resolve_function);
return meta;
};

View File

@ -41,7 +41,7 @@ JS::ThrowCompletionOr<bool> PlatformObject::is_named_property_exposed_on_object(
// 1. If P is not a supported property name of O, then return false.
// NOTE: This is in it's own variable to enforce the type.
if (!is_supported_property_name(property_key.to_string()))
if (!is_supported_property_name(property_key.to_string().to_utf8_but_should_be_ported_to_utf16()))
return false;
// 2. If O has an own property named P, then return false.
@ -118,7 +118,7 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> PlatformObject::legacy_p
// 1. If the result of running the named property visibility algorithm with property name P and object O is true, then:
if (TRY(is_named_property_exposed_on_object(property_name))) {
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
auto property_name_string = property_name.to_string();
auto property_name_string = property_name.to_string().to_utf8_but_should_be_ported_to_utf16();
// 1. Let operation be the operation used to declare the named property getter.
// 2. Let value be an uninitialized variable.
@ -236,7 +236,7 @@ JS::ThrowCompletionOr<bool> PlatformObject::internal_set(JS::PropertyKey const&
// 2. If O implements an interface with a named property setter and P is a String, then:
if (m_legacy_platform_object_flags->has_named_property_setter && property_name.is_string()) {
// 1. Invoke the named property setter on O with P and V.
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(property_name.as_string(), value); }));
TRY(throw_dom_exception_if_needed(vm, [&] { return invoke_named_property_setter(property_name.as_string().view().to_utf8_but_should_be_ported_to_utf16(), value); }));
// 2. Return true.
return true;
@ -282,7 +282,7 @@ JS::ThrowCompletionOr<bool> PlatformObject::internal_define_own_property(JS::Pro
// 2. If O supports named properties, O does not implement an interface with the [Global] extended attribute, P is a String, and P is not an unforgeable property name of O, then:
// FIXME: Check if P is not an unforgeable property name of O
if (m_legacy_platform_object_flags->supports_named_properties && !m_legacy_platform_object_flags->has_global_interface_extended_attribute && property_name.is_string()) {
auto const property_name_as_string = property_name.as_string();
auto const property_name_as_string = property_name.as_string().view().to_utf8_but_should_be_ported_to_utf16();
// 1. Let creating be true if P is not a supported property name, and false otherwise.
bool creating = !is_supported_property_name(property_name_as_string);
@ -351,7 +351,7 @@ JS::ThrowCompletionOr<bool> PlatformObject::internal_delete(JS::PropertyKey cons
return false;
// FIXME: It's unfortunate that this is done twice, once in is_named_property_exposed_on_object and here.
auto property_name_string = property_name.to_string();
auto property_name_string = property_name.to_string().to_utf8_but_should_be_ported_to_utf16();
// 2. Let operation be the operation used to declare the named property deleter.
// 3. If operation was defined without an identifier, then:
@ -423,7 +423,7 @@ JS::ThrowCompletionOr<GC::RootVector<JS::Value>> PlatformObject::internal_own_pr
// 3. If O supports named properties, then for each P of Os supported property names that is visible according to the named property visibility algorithm, append P to keys.
if (m_legacy_platform_object_flags->supports_named_properties) {
for (auto& named_property : supported_property_names()) {
if (TRY(is_named_property_exposed_on_object(named_property)))
if (TRY(is_named_property_exposed_on_object(Utf16FlyString::from_utf8(named_property))))
keys.append(JS::PrimitiveString::create(vm, named_property));
}
}

View File

@ -52,7 +52,7 @@ WebIDL::ExceptionOr<GC::Root<WebIDL::ArrayBufferView>> Crypto::get_random_values
return WebIDL::TypeMismatchError::create(realm(), "array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array"_string);
auto const& typed_array = *array->bufferable_object().get<GC::Ref<JS::TypedArrayBase>>();
if (!typed_array.element_name().is_one_of("Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "BigInt64Array", "BigUint64Array"))
if (!typed_array.element_name().is_one_of("Int8Array"sv, "Uint8Array"sv, "Uint8ClampedArray"sv, "Int16Array"sv, "Uint16Array"sv, "Int32Array"sv, "Uint32Array"sv, "BigInt64Array"sv, "BigUint64Array"sv))
return WebIDL::TypeMismatchError::create(realm(), "array must be one of Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, or BigUint64Array"_string);
auto typed_array_record = JS::make_typed_array_with_buffer_witness_record(typed_array, JS::ArrayBuffer::Order::SeqCst);

View File

@ -287,7 +287,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> AesCbcParams::from_value(J
{
auto& object = value.as_object();
auto iv_value = TRY(object.get("iv"_fly_string));
auto iv_value = TRY(object.get("iv"_utf16_fly_string));
if (!iv_value.is_object() || !(is<JS::TypedArrayBase>(iv_value.as_object()) || is<JS::ArrayBuffer>(iv_value.as_object()) || is<JS::DataView>(iv_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto iv = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(iv_value.as_object()));
@ -301,12 +301,12 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> AesCtrParams::from_value(J
{
auto& object = value.as_object();
auto iv_value = TRY(object.get("counter"_fly_string));
auto iv_value = TRY(object.get("counter"_utf16_fly_string));
if (!iv_value.is_object() || !(is<JS::TypedArrayBase>(iv_value.as_object()) || is<JS::ArrayBuffer>(iv_value.as_object()) || is<JS::DataView>(iv_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto iv = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(iv_value.as_object()));
auto length_value = TRY(object.get("length"_fly_string));
auto length_value = TRY(object.get("length"_utf16_fly_string));
auto length = TRY(length_value.to_u8(vm));
return adopt_own<AlgorithmParams>(*new AesCtrParams { iv, length });
@ -318,22 +318,22 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> AesGcmParams::from_value(J
{
auto& object = value.as_object();
auto iv_value = TRY(object.get("iv"_fly_string));
auto iv_value = TRY(object.get("iv"_utf16_fly_string));
if (!iv_value.is_object() || !(is<JS::TypedArrayBase>(iv_value.as_object()) || is<JS::ArrayBuffer>(iv_value.as_object()) || is<JS::DataView>(iv_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto iv = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(iv_value.as_object()));
auto maybe_additional_data = Optional<ByteBuffer> {};
if (MUST(object.has_property("additionalData"_fly_string))) {
auto additional_data_value = TRY(object.get("additionalData"_fly_string));
if (MUST(object.has_property("additionalData"_utf16_fly_string))) {
auto additional_data_value = TRY(object.get("additionalData"_utf16_fly_string));
if (!additional_data_value.is_object() || !(is<JS::TypedArrayBase>(additional_data_value.as_object()) || is<JS::ArrayBuffer>(additional_data_value.as_object()) || is<JS::DataView>(additional_data_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
maybe_additional_data = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(additional_data_value.as_object()));
}
auto maybe_tag_length = Optional<u8> {};
if (MUST(object.has_property("tagLength"_fly_string))) {
auto tag_length_value = TRY(object.get("tagLength"_fly_string));
if (MUST(object.has_property("tagLength"_utf16_fly_string))) {
auto tag_length_value = TRY(object.get("tagLength"_utf16_fly_string));
maybe_tag_length = TRY(tag_length_value.to_u8(vm));
}
@ -346,15 +346,15 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> HKDFParams::from_value(JS:
{
auto& object = value.as_object();
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
auto salt_value = TRY(object.get("salt"_fly_string));
auto salt_value = TRY(object.get("salt"_utf16_fly_string));
if (!salt_value.is_object() || !(is<JS::TypedArrayBase>(salt_value.as_object()) || is<JS::ArrayBuffer>(salt_value.as_object()) || is<JS::DataView>(salt_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto salt = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(salt_value.as_object()));
auto info_value = TRY(object.get("info"_fly_string));
auto info_value = TRY(object.get("info"_utf16_fly_string));
if (!info_value.is_object() || !(is<JS::TypedArrayBase>(info_value.as_object()) || is<JS::ArrayBuffer>(info_value.as_object()) || is<JS::DataView>(info_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto info = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(info_value.as_object()));
@ -368,17 +368,17 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> PBKDF2Params::from_value(J
{
auto& object = value.as_object();
auto salt_value = TRY(object.get("salt"_fly_string));
auto salt_value = TRY(object.get("salt"_utf16_fly_string));
if (!salt_value.is_object() || !(is<JS::TypedArrayBase>(salt_value.as_object()) || is<JS::ArrayBuffer>(salt_value.as_object()) || is<JS::DataView>(salt_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
auto salt = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(salt_value.as_object()));
auto iterations_value = TRY(object.get("iterations"_fly_string));
auto iterations_value = TRY(object.get("iterations"_utf16_fly_string));
auto iterations = TRY(iterations_value.to_u32(vm));
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
return adopt_own<AlgorithmParams>(*new PBKDF2Params { salt, iterations, hash });
@ -390,10 +390,10 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaKeyGenParams::from_valu
{
auto& object = value.as_object();
auto modulus_length_value = TRY(object.get("modulusLength"_fly_string));
auto modulus_length_value = TRY(object.get("modulusLength"_utf16_fly_string));
auto modulus_length = TRY(modulus_length_value.to_u32(vm));
auto public_exponent_value = TRY(object.get("publicExponent"_fly_string));
auto public_exponent_value = TRY(object.get("publicExponent"_utf16_fly_string));
GC::Ptr<JS::Uint8Array> public_exponent;
if (!public_exponent_value.is_object() || !is<JS::Uint8Array>(public_exponent_value.as_object()))
@ -410,10 +410,10 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaHashedKeyGenParams::fro
{
auto& object = value.as_object();
auto modulus_length_value = TRY(object.get("modulusLength"_fly_string));
auto modulus_length_value = TRY(object.get("modulusLength"_utf16_fly_string));
auto modulus_length = TRY(modulus_length_value.to_u32(vm));
auto public_exponent_value = TRY(object.get("publicExponent"_fly_string));
auto public_exponent_value = TRY(object.get("publicExponent"_utf16_fly_string));
GC::Ptr<JS::Uint8Array> public_exponent;
if (!public_exponent_value.is_object() || !is<JS::Uint8Array>(public_exponent_value.as_object()))
@ -421,7 +421,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaHashedKeyGenParams::fro
public_exponent = static_cast<JS::Uint8Array&>(public_exponent_value.as_object());
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
return adopt_own<AlgorithmParams>(*new RsaHashedKeyGenParams { modulus_length, big_integer_from_api_big_integer(public_exponent), hash });
@ -433,7 +433,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaHashedImportParams::fro
{
auto& object = value.as_object();
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
return adopt_own<AlgorithmParams>(*new RsaHashedImportParams { hash });
@ -445,7 +445,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaOaepParams::from_value(
{
auto& object = value.as_object();
auto label_value = TRY(object.get("label"_fly_string));
auto label_value = TRY(object.get("label"_utf16_fly_string));
ByteBuffer label;
if (!label_value.is_nullish()) {
@ -465,7 +465,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> RsaPssParams::from_value(J
{
auto& object = value.as_object();
auto salt_length_value = TRY(object.get("saltLength"_fly_string));
auto salt_length_value = TRY(object.get("saltLength"_utf16_fly_string));
auto salt_length = TRY(salt_length_value.to_u32(vm));
return adopt_own<AlgorithmParams>(*new RsaPssParams { salt_length });
@ -477,7 +477,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> EcdsaParams::from_value(JS
{
auto& object = value.as_object();
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
return adopt_own<AlgorithmParams>(*new EcdsaParams { hash });
@ -489,7 +489,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> EcKeyGenParams::from_value
{
auto& object = value.as_object();
auto curve_value = TRY(object.get("namedCurve"_fly_string));
auto curve_value = TRY(object.get("namedCurve"_utf16_fly_string));
auto curve = TRY(curve_value.to_string(vm));
return adopt_own<AlgorithmParams>(*new EcKeyGenParams { curve });
@ -501,7 +501,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> AesKeyGenParams::from_valu
{
auto& object = value.as_object();
auto length_value = TRY(object.get("length"_fly_string));
auto length_value = TRY(object.get("length"_utf16_fly_string));
auto length = TRY(length_value.to_u16(vm));
return adopt_own<AlgorithmParams>(*new AesKeyGenParams { length });
@ -513,7 +513,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> AesDerivedKeyParams::from_
{
auto& object = value.as_object();
auto length_value = TRY(object.get("length"_fly_string));
auto length_value = TRY(object.get("length"_utf16_fly_string));
auto length = TRY(length_value.to_u16(vm));
return adopt_own<AlgorithmParams>(*new AesDerivedKeyParams { length });
@ -525,7 +525,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> EcdhKeyDeriveParams::from_
{
auto& object = value.as_object();
auto key_value = TRY(object.get("public"_fly_string));
auto key_value = TRY(object.get("public"_utf16_fly_string));
auto key_object = TRY(key_value.to_object(vm));
if (!is<CryptoKey>(*key_object)) {
@ -543,7 +543,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> EcKeyImportParams::from_va
{
auto& object = value.as_object();
auto named_curve_value = TRY(object.get("namedCurve"_fly_string));
auto named_curve_value = TRY(object.get("namedCurve"_utf16_fly_string));
auto named_curve = TRY(named_curve_value.to_string(vm));
return adopt_own<AlgorithmParams>(*new EcKeyImportParams { named_curve });
@ -555,12 +555,12 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> HmacImportParams::from_val
{
auto& object = value.as_object();
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
auto maybe_length = Optional<WebIDL::UnsignedLong> {};
if (MUST(object.has_property("length"_fly_string))) {
auto length_value = TRY(object.get("length"_fly_string));
if (MUST(object.has_property("length"_utf16_fly_string))) {
auto length_value = TRY(object.get("length"_utf16_fly_string));
maybe_length = TRY(length_value.to_u32(vm));
}
@ -573,12 +573,12 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> HmacKeyGenParams::from_val
{
auto& object = value.as_object();
auto hash_value = TRY(object.get("hash"_fly_string));
auto hash_value = TRY(object.get("hash"_utf16_fly_string));
auto hash = TRY(hash_algorithm_identifier_from_value(vm, hash_value));
auto maybe_length = Optional<WebIDL::UnsignedLong> {};
if (MUST(object.has_property("length"_fly_string))) {
auto length_value = TRY(object.get("length"_fly_string));
if (MUST(object.has_property("length"_utf16_fly_string))) {
auto length_value = TRY(object.get("length"_utf16_fly_string));
maybe_length = TRY(length_value.to_u32(vm));
}
@ -592,8 +592,8 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> Ed448Params::from_value(JS
auto& object = value.as_object();
auto maybe_context = Optional<ByteBuffer> {};
if (MUST(object.has_property("context"_fly_string))) {
auto context_value = TRY(object.get("context"_fly_string));
if (MUST(object.has_property("context"_utf16_fly_string))) {
auto context_value = TRY(object.get("context"_utf16_fly_string));
if (!context_value.is_object() || !(is<JS::TypedArrayBase>(context_value.as_object()) || is<JS::ArrayBuffer>(context_value.as_object()) || is<JS::DataView>(context_value.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
maybe_context = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(context_value.as_object()));

View File

@ -34,7 +34,7 @@ struct HashAlgorithmIdentifier : public AlgorithmIdentifier {
auto value = visit(
[](String const& name) -> JS::ThrowCompletionOr<String> { return name; },
[&](GC::Root<JS::Object> const& obj) -> JS::ThrowCompletionOr<String> {
auto name_property = TRY(obj->get("name"_fly_string));
auto name_property = TRY(obj->get("name"_utf16_fly_string));
return name_property.to_string(vm);
});

View File

@ -91,63 +91,63 @@ JS::ThrowCompletionOr<GC::Ref<JS::Object>> JsonWebKey::to_object(JS::Realm& real
auto object = JS::Object::create(realm, realm.intrinsics().object_prototype());
if (kty.has_value())
TRY(object->create_data_property("kty"_fly_string, JS::PrimitiveString::create(vm, kty.value())));
TRY(object->create_data_property("kty"_utf16_fly_string, JS::PrimitiveString::create(vm, kty.value())));
if (use.has_value())
TRY(object->create_data_property("use"_fly_string, JS::PrimitiveString::create(vm, use.value())));
TRY(object->create_data_property("use"_utf16_fly_string, JS::PrimitiveString::create(vm, use.value())));
if (key_ops.has_value()) {
auto key_ops_array = JS::Array::create_from<String>(realm, key_ops.value().span(), [&](auto& key_usage) -> JS::Value {
return JS::PrimitiveString::create(realm.vm(), key_usage);
});
TRY(object->create_data_property("key_ops"_fly_string, move(key_ops_array)));
TRY(object->create_data_property("key_ops"_utf16_fly_string, move(key_ops_array)));
}
if (alg.has_value())
TRY(object->create_data_property("alg"_fly_string, JS::PrimitiveString::create(vm, alg.value())));
TRY(object->create_data_property("alg"_utf16_fly_string, JS::PrimitiveString::create(vm, alg.value())));
if (ext.has_value())
TRY(object->create_data_property("ext"_fly_string, JS::Value(ext.value())));
TRY(object->create_data_property("ext"_utf16_fly_string, JS::Value(ext.value())));
if (crv.has_value())
TRY(object->create_data_property("crv"_fly_string, JS::PrimitiveString::create(vm, crv.value())));
TRY(object->create_data_property("crv"_utf16_fly_string, JS::PrimitiveString::create(vm, crv.value())));
if (x.has_value())
TRY(object->create_data_property("x"_fly_string, JS::PrimitiveString::create(vm, x.value())));
TRY(object->create_data_property("x"_utf16_fly_string, JS::PrimitiveString::create(vm, x.value())));
if (y.has_value())
TRY(object->create_data_property("y"_fly_string, JS::PrimitiveString::create(vm, y.value())));
TRY(object->create_data_property("y"_utf16_fly_string, JS::PrimitiveString::create(vm, y.value())));
if (d.has_value())
TRY(object->create_data_property("d"_fly_string, JS::PrimitiveString::create(vm, d.value())));
TRY(object->create_data_property("d"_utf16_fly_string, JS::PrimitiveString::create(vm, d.value())));
if (n.has_value())
TRY(object->create_data_property("n"_fly_string, JS::PrimitiveString::create(vm, n.value())));
TRY(object->create_data_property("n"_utf16_fly_string, JS::PrimitiveString::create(vm, n.value())));
if (e.has_value())
TRY(object->create_data_property("e"_fly_string, JS::PrimitiveString::create(vm, e.value())));
TRY(object->create_data_property("e"_utf16_fly_string, JS::PrimitiveString::create(vm, e.value())));
if (p.has_value())
TRY(object->create_data_property("p"_fly_string, JS::PrimitiveString::create(vm, p.value())));
TRY(object->create_data_property("p"_utf16_fly_string, JS::PrimitiveString::create(vm, p.value())));
if (q.has_value())
TRY(object->create_data_property("q"_fly_string, JS::PrimitiveString::create(vm, q.value())));
TRY(object->create_data_property("q"_utf16_fly_string, JS::PrimitiveString::create(vm, q.value())));
if (dp.has_value())
TRY(object->create_data_property("dp"_fly_string, JS::PrimitiveString::create(vm, dp.value())));
TRY(object->create_data_property("dp"_utf16_fly_string, JS::PrimitiveString::create(vm, dp.value())));
if (dq.has_value())
TRY(object->create_data_property("dq"_fly_string, JS::PrimitiveString::create(vm, dq.value())));
TRY(object->create_data_property("dq"_utf16_fly_string, JS::PrimitiveString::create(vm, dq.value())));
if (qi.has_value())
TRY(object->create_data_property("qi"_fly_string, JS::PrimitiveString::create(vm, qi.value())));
TRY(object->create_data_property("qi"_utf16_fly_string, JS::PrimitiveString::create(vm, qi.value())));
if (oth.has_value()) {
TODO();
}
if (k.has_value())
TRY(object->create_data_property("k"_fly_string, JS::PrimitiveString::create(vm, k.value())));
TRY(object->create_data_property("k"_utf16_fly_string, JS::PrimitiveString::create(vm, k.value())));
return object;
}

View File

@ -75,7 +75,7 @@ void CryptoKey::set_usages(Vector<Bindings::KeyUsage> usages)
String CryptoKey::algorithm_name() const
{
if (m_algorithm_name.is_empty()) {
auto name = MUST(m_algorithm->get("name"_fly_string));
auto name = MUST(m_algorithm->get("name"_utf16_fly_string));
m_algorithm_name = MUST(name.to_string(vm()));
}
return m_algorithm_name;
@ -95,8 +95,8 @@ CryptoKeyPair::CryptoKeyPair(JS::Realm& realm, GC::Ref<CryptoKey> public_key, GC
void CryptoKeyPair::initialize(JS::Realm& realm)
{
define_native_accessor(realm, "publicKey"_fly_string, public_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "privateKey"_fly_string, private_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "publicKey"_utf16_fly_string, public_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "privateKey"_utf16_fly_string, private_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
Base::initialize(realm);
}

View File

@ -49,7 +49,7 @@ KeyAlgorithm::KeyAlgorithm(JS::Realm& realm)
void KeyAlgorithm::initialize(JS::Realm& realm)
{
define_native_accessor(realm, "name"_fly_string, name_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "name"_utf16_fly_string, name_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
Base::initialize(realm);
}
@ -81,8 +81,8 @@ void RsaKeyAlgorithm::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_native_accessor(realm, "modulusLength"_fly_string, modulus_length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "publicExponent"_fly_string, public_exponent_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "modulusLength"_utf16_fly_string, modulus_length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "publicExponent"_utf16_fly_string, public_exponent_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
}
void RsaKeyAlgorithm::visit_edges(Visitor& visitor)
@ -133,7 +133,7 @@ void EcKeyAlgorithm::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_native_accessor(realm, "namedCurve"_fly_string, named_curve_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "namedCurve"_utf16_fly_string, named_curve_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
}
JS_DEFINE_NATIVE_FUNCTION(EcKeyAlgorithm::named_curve_getter)
@ -157,7 +157,7 @@ void RsaHashedKeyAlgorithm::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_native_accessor(realm, "hash"_fly_string, hash_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "hash"_utf16_fly_string, hash_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
}
JS_DEFINE_NATIVE_FUNCTION(RsaHashedKeyAlgorithm::hash_getter)
@ -191,7 +191,7 @@ void AesKeyAlgorithm::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_native_accessor(realm, "length"_fly_string, length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "length"_utf16_fly_string, length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
}
JS_DEFINE_NATIVE_FUNCTION(AesKeyAlgorithm::length_getter)
@ -214,8 +214,8 @@ HmacKeyAlgorithm::HmacKeyAlgorithm(JS::Realm& realm)
void HmacKeyAlgorithm::initialize(JS::Realm& realm)
{
Base::initialize(realm);
define_native_accessor(realm, "hash"_fly_string, hash_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "length"_fly_string, length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "hash"_utf16_fly_string, hash_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_accessor(realm, "length"_utf16_fly_string, length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
}
void HmacKeyAlgorithm::visit_edges(JS::Cell::Visitor& visitor)

View File

@ -72,7 +72,7 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
// Return the result of running the normalize an algorithm algorithm,
// with the alg set to a new Algorithm dictionary whose name attribute is alg, and with the op set to op.
auto dictionary = GC::make_root(JS::Object::create(realm, realm.intrinsics().object_prototype()));
TRY(dictionary->create_data_property("name"_fly_string, JS::PrimitiveString::create(vm, algorithm.get<String>())));
TRY(dictionary->create_data_property("name"_utf16_fly_string, JS::PrimitiveString::create(vm, algorithm.get<String>())));
return normalize_an_algorithm(realm, dictionary, operation);
}
@ -89,7 +89,7 @@ WebIDL::ExceptionOr<NormalizedAlgorithmAndParameter> normalize_an_algorithm(JS::
// 3. If an error occurred, return the error and terminate this algorithm.
// Note: We're not going to bother creating an Algorithm object, all we want is the name attribute so that we can
// fetch the actual algorithm factory from the registeredAlgorithms map.
auto initial_algorithm = TRY(algorithm.get<GC::Root<JS::Object>>()->get("name"_fly_string));
auto initial_algorithm = TRY(algorithm.get<GC::Root<JS::Object>>()->get("name"_utf16_fly_string));
if (initial_algorithm.is_undefined()) {
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Algorithm");

View File

@ -4821,7 +4821,7 @@ void Document::start_intersection_observing_a_lazy_loading_element(Element& elem
// 2. If doc's lazy load intersection observer is null, set it to a new IntersectionObserver instance, initialized as follows:
if (!m_lazy_load_intersection_observer) {
// - The callback is these steps, with arguments entries and observer:
auto callback = JS::NativeFunction::create(realm, ""_fly_string, [this](JS::VM& vm) -> JS::ThrowCompletionOr<JS::Value> {
auto callback = JS::NativeFunction::create(realm, Utf16FlyString {}, [this](JS::VM& vm) -> JS::ThrowCompletionOr<JS::Value> {
// For each entry in entries using a method of iteration which does not trigger developer-modifiable array accessors or iteration hooks:
auto& entries = as<JS::Array>(vm.argument(0).as_object());
auto entries_length = MUST(MUST(entries.get(vm.names.length)).to_length(vm));

View File

@ -2712,7 +2712,7 @@ void Element::enqueue_a_custom_element_callback_reaction(FlyString const& callba
if (connected_callback)
(void)WebIDL::invoke_callback(*connected_callback, this, WebIDL::ExceptionBehavior::Report, no_arguments);
return JS::js_undefined(); }, 0, FlyString {}, &realm());
return JS::js_undefined(); }, 0, Utf16FlyString {}, &realm());
callback = realm().heap().allocate<WebIDL::CallbackType>(steps, realm());
}

View File

@ -91,7 +91,7 @@ bool EventDispatcher::inner_invoke(Event& event, Vector<GC::Root<DOM::DOMEventLi
// FIXME: These should be wrapped for us in call_user_object_operation, but it currently doesn't do that.
auto* this_value = event.current_target().ptr();
auto* wrapped_event = &event;
auto result = WebIDL::call_user_object_operation(callback, "handleEvent"_string, this_value, { { wrapped_event } });
auto result = WebIDL::call_user_object_operation(callback, "handleEvent"_utf16_fly_string, this_value, { { wrapped_event } });
// If this throws an exception, then:
if (result.is_error()) {

View File

@ -516,7 +516,7 @@ WebIDL::CallbackType* EventTarget::get_current_value_of_event_handler(FlyString
// 6. Return scope. (NOTE: Not necessary)
auto function = JS::ECMAScriptFunctionObject::create(realm, name, builder.to_byte_string(), program->body(), program->parameters(), program->function_length(), program->local_variables_names(), scope, nullptr, JS::FunctionKind::Normal, program->is_strict_mode(),
auto function = JS::ECMAScriptFunctionObject::create(realm, Utf16FlyString::from_utf8(name), builder.to_byte_string(), program->body(), program->parameters(), program->function_length(), program->local_variables_names(), scope, nullptr, JS::FunctionKind::Normal, program->is_strict_mode(),
program->parsing_insights(), is_arrow_function);
// 10. Remove settings object's realm execution context from the JavaScript execution context stack.
@ -617,7 +617,7 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl
TRY(event_target->process_event_handler_for_event(name, event));
return JS::js_undefined();
},
0, FlyString {}, &realm);
0, Utf16FlyString {}, &realm);
// NOTE: As per the spec, the callback context is arbitrary.
auto callback = realm.heap().allocate<WebIDL::CallbackType>(*callback_function, realm);

View File

@ -169,7 +169,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> NodeIterator::filter(Node& node)
// 6. Let result be the return value of call a user objects operation with traversers filter, "acceptNode", and « node ».
// If this throws an exception, then unset traversers active flag and rethrow the exception.
auto result = WebIDL::call_user_object_operation(m_filter->callback(), "acceptNode"_string, {}, { { &node } });
auto result = WebIDL::call_user_object_operation(m_filter->callback(), "acceptNode"_utf16_fly_string, {}, { { &node } });
if (result.is_abrupt()) {
m_active = false;
return result;

View File

@ -274,7 +274,7 @@ JS::ThrowCompletionOr<NodeFilter::Result> TreeWalker::filter(Node& node)
// 6. Let result be the return value of call a user objects operation with traversers filter, "acceptNode", and « node ».
// If this throws an exception, then unset traversers active flag and rethrow the exception.
auto result = WebIDL::call_user_object_operation(m_filter->callback(), "acceptNode"_string, {}, { { &node } });
auto result = WebIDL::call_user_object_operation(m_filter->callback(), "acceptNode"_utf16_fly_string, {}, { { &node } });
if (result.is_abrupt()) {
m_active = false;
return result;

View File

@ -22,13 +22,13 @@ JS::ThrowCompletionOr<Web::HTML::CanvasRenderingContext2DSettings> Web::HTML::Ca
auto& value_object = value.as_object();
JS::Value alpha = TRY(value_object.get("alpha"_fly_string));
JS::Value alpha = TRY(value_object.get("alpha"_utf16_fly_string));
settings.alpha = alpha.is_undefined() ? true : alpha.to_boolean();
JS::Value desynchronized = TRY(value_object.get("desynchronized"_fly_string));
JS::Value desynchronized = TRY(value_object.get("desynchronized"_utf16_fly_string));
settings.desynchronized = desynchronized.is_undefined() ? false : desynchronized.to_boolean();
JS::Value color_space = TRY(value_object.get("colorSpace"_fly_string));
JS::Value color_space = TRY(value_object.get("colorSpace"_utf16_fly_string));
if (!color_space.is_undefined()) {
auto color_space_string = TRY(color_space.to_string(vm));
if (color_space_string == "srgb"sv)
@ -39,7 +39,7 @@ JS::ThrowCompletionOr<Web::HTML::CanvasRenderingContext2DSettings> Web::HTML::Ca
return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, color_space_string, "colorSpace");
}
JS::Value color_type = TRY(value_object.get("colorType"_fly_string));
JS::Value color_type = TRY(value_object.get("colorType"_utf16_fly_string));
if (!color_type.is_undefined()) {
auto color_type_string = TRY(color_type.to_string(vm));
if (color_type_string == "unorm8"sv)
@ -50,7 +50,7 @@ JS::ThrowCompletionOr<Web::HTML::CanvasRenderingContext2DSettings> Web::HTML::Ca
return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, color_type_string, "colorType");
}
JS::Value will_read_frequently = TRY(value_object.get("willReadFrequently"_fly_string));
JS::Value will_read_frequently = TRY(value_object.get("willReadFrequently"_utf16_fly_string));
settings.will_read_frequently = will_read_frequently.is_undefined() ? false : will_read_frequently.to_boolean();
return settings;

View File

@ -209,7 +209,7 @@ JS::ThrowCompletionOr<void> CustomElementRegistry::define(String const& name, We
// 4. For each callbackName of the keys of lifecycleCallbacks:
for (auto const& callback_name : { CustomElementReactionNames::connectedCallback, CustomElementReactionNames::disconnectedCallback, CustomElementReactionNames::adoptedCallback, CustomElementReactionNames::connectedMoveCallback, CustomElementReactionNames::attributeChangedCallback }) {
// 1. Let callbackValue be ? Get(prototype, callbackName).
auto callback_value = TRY(prototype.get(callback_name));
auto callback_value = TRY(prototype.get(Utf16FlyString::from_utf8(callback_name)));
// 2. If callbackValue is not undefined, then set the value of the entry in lifecycleCallbacks with key callbackName to the result of
// converting callbackValue to the Web IDL Function callback type.
@ -260,7 +260,7 @@ JS::ThrowCompletionOr<void> CustomElementRegistry::define(String const& name, We
if (form_associated) {
for (auto const& callback_name : { CustomElementReactionNames::formAssociatedCallback, CustomElementReactionNames::formResetCallback, CustomElementReactionNames::formDisabledCallback, CustomElementReactionNames::formStateRestoreCallback }) {
// 1. Let callbackValue be ? Get(prototype, callbackName).
auto callback_value = TRY(prototype.get(callback_name));
auto callback_value = TRY(prototype.get(Utf16FlyString::from_utf8(callback_name)));
// 2. If callbackValue is not undefined, then set lifecycleCallbacks[callbackName] to the result of converting callbackValue
// to the Web IDL Function callback type.

View File

@ -118,7 +118,7 @@ Variant<GC::Ref<DOM::HTMLCollection>, GC::Ref<DOM::Element>, Empty> HTMLAllColle
return Empty {};
// 2. Return the result of getting the "all"-indexed or named element(s) from this, given nameOrIndex.
return get_the_all_indexed_or_named_elements(name_or_index.value());
return get_the_all_indexed_or_named_elements(Utf16FlyString::from_utf8(name_or_index.value()));
}
// https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#dom-htmlallcollection-nameditem
@ -211,7 +211,7 @@ Variant<GC::Ref<DOM::HTMLCollection>, GC::Ref<DOM::Element>, Empty> HTMLAllColle
}
// 2. Return the result of getting the "all"-named element(s) from collection given nameOrIndex.
return get_the_all_named_elements(name_or_index.as_string());
return get_the_all_named_elements(name_or_index.as_string().view().to_utf8_but_should_be_ported_to_utf16());
}
Optional<JS::Value> HTMLAllCollection::item_value(size_t index) const

View File

@ -412,7 +412,7 @@ void HTMLDialogElement::set_close_watcher()
event.prevent_default();
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto cancel_callback = realm().heap().allocate<WebIDL::CallbackType>(*cancel_callback_function, realm());
m_close_watcher->add_event_listener_without_options(HTML::EventNames::cancel, DOM::IDLEventListener::create(realm(), cancel_callback));
// - closeAction being to close the dialog given dialog, dialog's request close return value, and dialog's request close source element.
@ -422,7 +422,7 @@ void HTMLDialogElement::set_close_watcher()
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto close_callback = realm().heap().allocate<WebIDL::CallbackType>(*close_callback_function, realm());
m_close_watcher->add_event_listener_without_options(HTML::EventNames::close, DOM::IDLEventListener::create(realm(), close_callback));
// - getEnabledState being to return true if dialog's enable close watcher for requestClose() is true or dialog's computed closed-by state is not None; otherwise false.

View File

@ -1432,7 +1432,7 @@ WebIDL::ExceptionOr<void> HTMLElement::show_popover(ThrowExceptions throw_except
return JS::js_undefined();
},
0, FlyString {}, &realm());
0, Utf16FlyString {}, &realm());
auto close_callback = realm().heap().allocate<WebIDL::CallbackType>(*close_callback_function, realm());
m_popover_close_watcher->add_event_listener_without_options(HTML::EventNames::close, DOM::IDLEventListener::create(realm(), close_callback));
// - getEnabledState being to return true.

View File

@ -1090,7 +1090,7 @@ void HTMLInputElement::create_text_input_shadow_tree()
commit_pending_changes();
return JS::js_undefined();
},
0, FlyString {}, &realm());
0, Utf16FlyString {}, &realm());
auto mouseup_callback = realm().heap().allocate<WebIDL::CallbackType>(*mouseup_callback_function, realm());
DOM::AddEventListenerOptions mouseup_listener_options;
mouseup_listener_options.once = true;
@ -1103,7 +1103,7 @@ void HTMLInputElement::create_text_input_shadow_tree()
}
return JS::js_undefined();
},
0, FlyString {}, &realm());
0, Utf16FlyString {}, &realm());
auto step_up_callback = realm().heap().allocate<WebIDL::CallbackType>(*up_callback_function, realm());
up_button->add_event_listener_without_options(UIEvents::EventNames::mousedown, DOM::IDLEventListener::create(realm(), step_up_callback));
up_button->add_event_listener_without_options(UIEvents::EventNames::mouseup, DOM::IDLEventListener::create(realm(), mouseup_callback));
@ -1125,7 +1125,7 @@ void HTMLInputElement::create_text_input_shadow_tree()
}
return JS::js_undefined();
},
0, FlyString {}, &realm());
0, Utf16FlyString {}, &realm());
auto step_down_callback = realm().heap().allocate<WebIDL::CallbackType>(*down_callback_function, realm());
down_button->add_event_listener_without_options(UIEvents::EventNames::mousedown, DOM::IDLEventListener::create(realm(), step_down_callback));
down_button->add_event_listener_without_options(UIEvents::EventNames::mouseup, DOM::IDLEventListener::create(realm(), mouseup_callback));
@ -1186,7 +1186,7 @@ void HTMLInputElement::create_file_input_shadow_tree()
return JS::js_undefined();
};
auto on_button_click_function = JS::NativeFunction::create(realm, move(on_button_click), 0, FlyString {}, &realm);
auto on_button_click_function = JS::NativeFunction::create(realm, move(on_button_click), 0, Utf16FlyString {}, &realm);
auto on_button_click_callback = realm.heap().allocate<WebIDL::CallbackType>(on_button_click_function, realm);
m_file_button->add_event_listener_without_options(UIEvents::EventNames::click, DOM::IDLEventListener::create(realm, on_button_click_callback));
@ -1237,7 +1237,7 @@ void HTMLInputElement::create_range_input_shadow_tree()
auto keydown_callback_function = JS::NativeFunction::create(
realm(), [this](JS::VM& vm) {
auto key = MUST(vm.argument(0).get(vm, "key"_fly_string)).as_string().utf8_string();
auto key = MUST(vm.argument(0).get(vm, "key"_utf16_fly_string)).as_string().utf8_string();
if (key == "ArrowLeft" || key == "ArrowDown")
MUST(step_down());
@ -1252,13 +1252,13 @@ void HTMLInputElement::create_range_input_shadow_tree()
user_interaction_did_change_input_value();
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto keydown_callback = realm().heap().allocate<WebIDL::CallbackType>(*keydown_callback_function, realm());
add_event_listener_without_options(UIEvents::EventNames::keydown, DOM::IDLEventListener::create(realm(), keydown_callback));
auto wheel_callback_function = JS::NativeFunction::create(
realm(), [this](JS::VM& vm) {
auto delta_y = MUST(vm.argument(0).get(vm, "deltaY"_fly_string)).as_i32();
auto delta_y = MUST(vm.argument(0).get(vm, "deltaY"_utf16_fly_string)).as_i32();
if (delta_y > 0) {
MUST(step_down());
} else {
@ -1267,12 +1267,12 @@ void HTMLInputElement::create_range_input_shadow_tree()
user_interaction_did_change_input_value();
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto wheel_callback = realm().heap().allocate<WebIDL::CallbackType>(*wheel_callback_function, realm());
add_event_listener_without_options(UIEvents::EventNames::wheel, DOM::IDLEventListener::create(realm(), wheel_callback));
auto update_slider_by_mouse = [this](JS::VM& vm) {
auto client_x = MUST(vm.argument(0).get(vm, "clientX"_fly_string)).as_double();
auto client_x = MUST(vm.argument(0).get(vm, "clientX"_utf16_fly_string)).as_double();
auto rect = get_bounding_client_rect();
double minimum = *min();
double maximum = *max();
@ -1290,7 +1290,7 @@ void HTMLInputElement::create_range_input_shadow_tree()
update_slider_by_mouse(vm);
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto mousemove_callback = realm().heap().allocate<WebIDL::CallbackType>(*mousemove_callback_function, realm());
auto mousemove_listener = DOM::IDLEventListener::create(realm(), mousemove_callback);
auto& window = static_cast<HTML::Window&>(relevant_global_object(*this));
@ -1302,7 +1302,7 @@ void HTMLInputElement::create_range_input_shadow_tree()
window.remove_event_listener_without_options(UIEvents::EventNames::mousemove, mousemove_listener);
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto mouseup_callback = realm().heap().allocate<WebIDL::CallbackType>(*mouseup_callback_function, realm());
DOM::AddEventListenerOptions mouseup_listener_options;
mouseup_listener_options.once = true;
@ -1310,7 +1310,7 @@ void HTMLInputElement::create_range_input_shadow_tree()
return JS::js_undefined();
},
0, ""_fly_string, &realm());
0, Utf16FlyString {}, &realm());
auto mousedown_callback = realm().heap().allocate<WebIDL::CallbackType>(*mousedown_callback_function, realm());
add_event_listener_without_options(UIEvents::EventNames::mousedown, DOM::IDLEventListener::create(realm(), mousedown_callback));
}

View File

@ -34,8 +34,8 @@ WebIDL::ExceptionOr<ImportMap> parse_import_map_string(JS::Realm& realm, ByteStr
ModuleSpecifierMap sorted_and_normalized_imports;
// 4. If parsed["imports"] exists, then:
if (TRY(parsed_object.has_property("imports"_fly_string))) {
auto imports = TRY(parsed_object.get("imports"_fly_string));
if (TRY(parsed_object.has_property("imports"_utf16_fly_string))) {
auto imports = TRY(parsed_object.get("imports"_utf16_fly_string));
// If parsed["imports"] is not an ordered map, then throw a TypeError indicating that the value for the "imports" top-level key needs to be a JSON object.
if (!imports.is_object())
@ -49,8 +49,8 @@ WebIDL::ExceptionOr<ImportMap> parse_import_map_string(JS::Realm& realm, ByteStr
HashMap<URL::URL, ModuleSpecifierMap> sorted_and_normalized_scopes;
// 6. If parsed["scopes"] exists, then:
if (TRY(parsed_object.has_property("scopes"_fly_string))) {
auto scopes = TRY(parsed_object.get("scopes"_fly_string));
if (TRY(parsed_object.has_property("scopes"_utf16_fly_string))) {
auto scopes = TRY(parsed_object.get("scopes"_utf16_fly_string));
// If parsed["scopes"] is not an ordered map, then throw a TypeError indicating that the value for the "scopes" top-level key needs to be a JSON object.
if (!scopes.is_object())
@ -64,8 +64,8 @@ WebIDL::ExceptionOr<ImportMap> parse_import_map_string(JS::Realm& realm, ByteStr
ModuleIntegrityMap normalized_integrity;
// 8. If parsed["integrity"] exists, then:
if (TRY(parsed_object.has_property("integrity"_fly_string))) {
auto integrity = TRY(parsed_object.get("integrity"_fly_string));
if (TRY(parsed_object.has_property("integrity"_utf16_fly_string))) {
auto integrity = TRY(parsed_object.get("integrity"_utf16_fly_string));
// 1. If parsed["integrity"] is not an ordered map, then throw a TypeError indicating that the value for the "integrity" top-level key needs to be a JSON object.
if (!integrity.is_object())
@ -77,7 +77,7 @@ WebIDL::ExceptionOr<ImportMap> parse_import_map_string(JS::Realm& realm, ByteStr
// 9. If parsed's keys contains any items besides "imports", "scopes", or "integrity", then the user agent should report a warning to the console indicating that an invalid top-level key was present in the import map.
for (auto& key : parsed_object.shape().property_table().keys()) {
if (key.as_string().is_one_of("imports", "scopes", "integrity"))
if (key.as_string().is_one_of("imports"sv, "scopes"sv, "integrity"sv))
continue;
auto& console = realm.intrinsics().console_object()->console();
@ -127,7 +127,7 @@ WebIDL::ExceptionOr<ModuleSpecifierMap> sort_and_normalise_module_specifier_map(
auto value = TRY(original_map.get(specifier_key.as_string()));
// 1. Let normalizedSpecifierKey be the result of normalizing a specifier key given specifierKey and baseURL.
auto normalized_specifier_key = normalize_specifier_key(realm, specifier_key.as_string(), base_url);
auto normalized_specifier_key = normalize_specifier_key(realm, specifier_key.as_string().view().to_utf8_but_should_be_ported_to_utf16(), base_url);
// 2. If normalizedSpecifierKey is null, then continue.
if (!normalized_specifier_key.has_value())
@ -163,7 +163,7 @@ WebIDL::ExceptionOr<ModuleSpecifierMap> sort_and_normalise_module_specifier_map(
}
// 6. If specifierKey ends with U+002F (/), and the serialization of addressURL does not end with U+002F (/), then:
if (specifier_key.as_string().bytes_as_string_view().ends_with("/"sv) && !address_url->serialize().ends_with('/')) {
if (specifier_key.as_string().view().ends_with("/"sv) && !address_url->serialize().ends_with('/')) {
// 1. The user agent may report a warning to the console indicating that an invalid address was given for the specifier key specifierKey; since specifierKey ends with a slash, the address needs to as well.
auto& console = realm.intrinsics().console_object()->console();
console.output_debug_message(JS::Console::LogLevel::Warn,
@ -199,7 +199,7 @@ WebIDL::ExceptionOr<HashMap<URL::URL, ModuleSpecifierMap>> sort_and_normalise_sc
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, String::formatted("The value of the scope with the prefix '{}' needs to be a JSON object.", scope_prefix.as_string()).release_value_but_fixme_should_propagate_errors() };
// 2. Let scopePrefixURL be the result of URL parsing scopePrefix with baseURL.
auto scope_prefix_url = DOMURL::parse(scope_prefix.as_string(), base_url);
auto scope_prefix_url = DOMURL::parse(scope_prefix.as_string().view().to_utf8_but_should_be_ported_to_utf16(), base_url);
// 3. If scopePrefixURL is failure, then:
if (!scope_prefix_url.has_value()) {
@ -232,7 +232,7 @@ WebIDL::ExceptionOr<ModuleIntegrityMap> normalize_module_integrity_map(JS::Realm
auto value = TRY(original_map.get(key.as_string()));
// 1. Let resolvedURL be the result of resolving a URL-like module specifier given key and baseURL.
auto resolved_url = resolve_url_like_module_specifier(key.as_string().to_string().to_byte_string(), base_url);
auto resolved_url = resolve_url_like_module_specifier(key.as_string().view().to_utf8_but_should_be_ported_to_utf16(), base_url);
// 2. If resolvedURL is null, then:
if (!resolved_url.has_value()) {

View File

@ -223,7 +223,7 @@ static WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Trans
if constexpr (IsSame<ViewType, JS::DataView>) {
data_holder.encode(ValueTag::ArrayBufferView);
data_holder.append(move(buffer_serialized)); // [[ArrayBufferSerialized]]
data_holder.encode("DataView"_string); // [[Constructor]]
data_holder.encode("DataView"_utf16); // [[Constructor]]
data_holder.encode(JS::get_view_byte_length(view_record));
data_holder.encode(view.byte_offset());
}
@ -235,8 +235,8 @@ static WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Trans
// [[ArrayBufferSerialized]]: bufferSerialized, [[ByteLength]]: value.[[ByteLength]],
// [[ByteOffset]]: value.[[ByteOffset]], [[ArrayLength]]: value.[[ArrayLength]] }.
data_holder.encode(ValueTag::ArrayBufferView);
data_holder.append(move(buffer_serialized)); // [[ArrayBufferSerialized]]
data_holder.encode(view.element_name().to_string()); // [[Constructor]]
data_holder.append(move(buffer_serialized)); // [[ArrayBufferSerialized]]
data_holder.encode(view.element_name().to_utf16_string()); // [[Constructor]]
data_holder.encode(JS::typed_array_byte_length(view_record));
data_holder.encode(view.byte_offset());
data_holder.encode(JS::typed_array_length(view_record));
@ -542,7 +542,7 @@ public:
auto output_value = TRY(structured_serialize_internal(m_vm, input_value, m_for_storage, m_memory));
// 3. Append { [[Key]]: key, [[Value]]: outputValue } to serialized.[[Properties]].
serialized.encode(key.as_string().utf8_string());
serialized.encode(key.as_string().utf16_string());
serialized.append(move(output_value));
++property_count;
@ -724,7 +724,7 @@ public:
auto array_buffer_value = TRY(deserialize());
auto& array_buffer = as<JS::ArrayBuffer>(array_buffer_value.as_object());
auto constructor_name = m_serialized.decode<String>();
auto constructor_name = m_serialized.decode<Utf16String>();
auto byte_length = m_serialized.decode<u32>();
auto byte_offset = m_serialized.decode<u32>();
@ -884,7 +884,7 @@ public:
// 1. For each Record { [[Key]], [[Value]] } entry of serialized.[[Properties]]:
for (u64 i = 0u; i < length; ++i) {
auto key = m_serialized.decode<String>();
auto key = m_serialized.decode<Utf16String>();
// 1. Let deserializedValue be ? StructuredDeserialize(entry.[[Value]], targetRealm, memory).
auto deserialized_value = TRY(deserialize());

View File

@ -118,7 +118,7 @@ GC::Ref<WebIDL::CallbackType> UniversalGlobalScopeMixin::count_queuing_strategy_
};
// 2. Let F be ! CreateBuiltinFunction(steps, 0, "size", « », globalObjects relevant Realm).
auto function = JS::NativeFunction::create(realm, move(steps), 0, "size"_fly_string, &realm);
auto function = JS::NativeFunction::create(realm, move(steps), 0, "size"_utf16_fly_string, &realm);
// 3. Set globalObjects count queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObjects relevant settings object.
// FIXME: Update spec comment to pass globalObject's relevant realm once Streams spec is updated for ShadowRealm spec
@ -143,7 +143,7 @@ GC::Ref<WebIDL::CallbackType> UniversalGlobalScopeMixin::byte_length_queuing_str
};
// 2. Let F be ! CreateBuiltinFunction(steps, 1, "size", « », globalObjects relevant Realm).
auto function = JS::NativeFunction::create(realm, move(steps), 1, "size"_fly_string, &realm);
auto function = JS::NativeFunction::create(realm, move(steps), 1, "size"_utf16_fly_string, &realm);
// 3. Set globalObjects byte length queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObjects relevant settings object.
// FIXME: Update spec comment to pass globalObject's relevant realm once Streams spec is updated for ShadowRealm spec

View File

@ -748,7 +748,7 @@ WebIDL::ExceptionOr<void> Window::initialize_web_interfaces(Badge<WindowEnvironm
WindowOrWorkerGlobalScopeMixin::initialize(realm);
if (s_internals_object_exposed)
define_direct_property("internals"_fly_string, realm.create<Internals::Internals>(realm), JS::default_attributes);
define_direct_property("internals"_utf16_fly_string, realm.create<Internals::Internals>(realm), JS::default_attributes);
return {};
}

View File

@ -867,7 +867,7 @@ void WindowOrWorkerGlobalScopeMixin::queue_the_performance_observer_task()
// droppedEntriesCount if droppedEntriesCount is not null, otherwise unset.
auto callback_options = JS::Object::create(realm, realm.intrinsics().object_prototype());
if (dropped_entries_count.has_value())
MUST(callback_options->create_data_property("droppedEntriesCount"_fly_string, JS::Value(dropped_entries_count.value())));
MUST(callback_options->create_data_property("droppedEntriesCount"_utf16_fly_string, JS::Value(dropped_entries_count.value())));
// 9. Call pos observer callback with observerEntryList as the first argument, with po as the second
// argument and as callback this value, and with callbackOptions as the third argument.

View File

@ -117,7 +117,7 @@ JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> WindowProxy::internal_ge
// 6. If property is undefined and P is in W's document-tree child navigable target name property set, then:
auto navigable_property_set = m_window->document_tree_child_navigable_target_name_property_set();
auto property_key_string = property_key.to_string();
auto property_key_string = property_key.to_string().to_utf8_but_should_be_ported_to_utf16();
if (auto navigable = navigable_property_set.get(property_key_string); navigable.has_value()) {
// 1. Let value be the active WindowProxy of the named object of W with the name P.

View File

@ -219,10 +219,10 @@ GC::Ref<WebIDL::Promise> IDBFactory::databases()
auto info = JS::Object::create(realm, realm.intrinsics().object_prototype());
// 3. Set infos name dictionary member to dbs name.
MUST(info->create_data_property("name"_fly_string, JS::PrimitiveString::create(realm.vm(), db->name())));
MUST(info->create_data_property("name"_utf16_fly_string, JS::PrimitiveString::create(realm.vm(), db->name())));
// 4. Set infos version dictionary member to dbs version.
MUST(info->create_data_property("version"_fly_string, JS::Value(db->version())));
MUST(info->create_data_property("version"_utf16_fly_string, JS::Value(db->version())));
// 4. Append info to result.
MUST(result->create_data_property_or_throw(i, info));

Some files were not shown because too many files have changed in this diff Show More