LibJS: Remove implicit wrapping/unwrapping of completion records

This is an editorial change in the ECMA-262 spec, with similar changes
in some proposals.

See:
- https://github.com/tc39/ecma262/commit/7575f74
- https://github.com/tc39/proposal-array-grouping/commit/df899eb
- https://github.com/tc39/proposal-shadowrealm/commit/9eb5a12
- https://github.com/tc39/proposal-shadowrealm/commit/c81f527
This commit is contained in:
Linus Groh 2022-05-02 20:54:39 +02:00
parent 15f32379bb
commit 9f3f3b0864
Notes: sideshowbarker 2024-07-17 11:22:30 +09:00
88 changed files with 792 additions and 735 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -84,7 +84,8 @@ TESTJS_GLOBAL_FUNCTION(detach_array_buffer, detachArrayBuffer)
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "ArrayBuffer");
auto& array_buffer_object = static_cast<JS::ArrayBuffer&>(array_buffer.as_object());
return JS::detach_array_buffer(global_object, array_buffer_object, vm.argument(1));
TRY(JS::detach_array_buffer(global_object, array_buffer_object, vm.argument(1)));
return JS::js_null();
}
TESTJS_RUN_FILE_FUNCTION(String const& test_file, JS::Interpreter& interpreter, JS::ExecutionContext&)

View file

@ -105,7 +105,7 @@ Completion ScopeNode::evaluate_statements(Interpreter& interpreter, GlobalObject
// BreakableStatement : IterationStatement
static Completion labelled_evaluation(Interpreter& interpreter, GlobalObject& global_object, IterationStatement const& statement, Vector<FlyString> const& label_set)
{
// 1. Let stmtResult be LoopEvaluation of IterationStatement with argument labelSet.
// 1. Let stmtResult be Completion(LoopEvaluation of IterationStatement with argument labelSet).
auto result = statement.loop_evaluation(interpreter, global_object, label_set);
// 2. If stmtResult.[[Type]] is break, then
@ -118,7 +118,7 @@ static Completion labelled_evaluation(Interpreter& interpreter, GlobalObject& gl
}
}
// 3. Return Completion(stmtResult).
// 3. Return ? stmtResult.
return result;
}
@ -139,7 +139,7 @@ static Completion labelled_evaluation(Interpreter& interpreter, GlobalObject& gl
}
}
// 3. Return Completion(stmtResult).
// 3. Return ? stmtResult.
return result;
}
@ -160,7 +160,7 @@ static Completion labelled_evaluation(Interpreter& interpreter, GlobalObject& gl
new_label_set->append(label);
}
// 3. Let stmtResult be LabelledEvaluation of LabelledItem with argument newLabelSet.
// 3. Let stmtResult be Completion(LabelledEvaluation of LabelledItem with argument newLabelSet).
Completion result;
if (is<IterationStatement>(labelled_item))
result = labelled_evaluation(interpreter, global_object, static_cast<IterationStatement const&>(labelled_item), *new_label_set);
@ -177,7 +177,7 @@ static Completion labelled_evaluation(Interpreter& interpreter, GlobalObject& gl
result = normal_completion(result.value());
}
// 5. Return Completion(stmtResult).
// 5. Return ? stmtResult.
return result;
}
@ -187,7 +187,7 @@ Completion LabelledStatement::execute(Interpreter& interpreter, GlobalObject& gl
InterpreterNodeScope node_scope { interpreter, *this };
// 1. Let newLabelSet be a new empty List.
// 2. Return LabelledEvaluation of this LabelledStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this LabelledStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -267,12 +267,12 @@ Completion FunctionDeclaration::execute(Interpreter& interpreter, GlobalObject&
// iv. Perform ? genv.SetMutableBinding(F, fobj, false).
TRY(variable_environment->set_mutable_binding(global_object, name(), function_object, false));
// v. Return NormalCompletion(empty).
return normal_completion({});
// v. Return unused.
return Optional<Value> {};
}
// 1. Return NormalCompletion(empty).
return normal_completion({});
// 1. Return unused.
return Optional<Value> {};
}
// 15.2.6 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-evaluation
@ -315,8 +315,8 @@ Value FunctionExpression::instantiate_ordinary_function_expression(Interpreter&
// 14.4.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-empty-statement-runtime-semantics-evaluation
Completion EmptyStatement::execute(Interpreter&, GlobalObject&) const
{
// 1. Return NormalCompletion(empty).
return normal_completion({});
// 1. Return empty.
return Optional<Value> {};
}
// 14.5.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-expression-statement-runtime-semantics-evaluation
@ -452,7 +452,7 @@ Completion SuperCall::execute(Interpreter& interpreter, GlobalObject& global_obj
// 2. Assert: Type(newTarget) is Object.
VERIFY(new_target.is_function());
// 3. Let func be ! GetSuperConstructor().
// 3. Let func be GetSuperConstructor().
auto* func = get_super_constructor(interpreter.vm());
// 4. Let argList be ? ArgumentListEvaluation of Arguments.
@ -521,7 +521,7 @@ Completion ReturnStatement::execute(Interpreter& interpreter, GlobalObject& glob
auto value = TRY(m_argument->execute(interpreter, global_object));
// NOTE: Generators are not supported in the AST interpreter
// 3. If ! GetGeneratorKind() is async, set exprValue to ? Await(exprValue).
// 3. If GetGeneratorKind() is async, set exprValue to ? Await(exprValue).
// 4. Return Completion Record { [[Type]]: return, [[Value]]: exprValue, [[Target]]: empty }.
return { Completion::Type::Return, value, {} };
@ -534,27 +534,27 @@ Completion IfStatement::execute(Interpreter& interpreter, GlobalObject& global_o
// IfStatement : if ( Expression ) Statement else Statement
// 1. Let exprRef be the result of evaluating Expression.
// 2. Let exprValue be ! ToBoolean(? GetValue(exprRef)).
// 2. Let exprValue be ToBoolean(? GetValue(exprRef)).
auto predicate_result = TRY(m_predicate->execute(interpreter, global_object)).release_value();
// 3. If exprValue is true, then
if (predicate_result.to_boolean()) {
// a. Let stmtCompletion be the result of evaluating the first Statement.
// 5. Return Completion(UpdateEmpty(stmtCompletion, undefined)).
// 5. Return ? UpdateEmpty(stmtCompletion, undefined).
return m_consequent->execute(interpreter, global_object).update_empty(js_undefined());
}
// 4. Else,
if (m_alternate) {
// a. Let stmtCompletion be the result of evaluating the second Statement.
// 5. Return Completion(UpdateEmpty(stmtCompletion, undefined)).
// 5. Return ? UpdateEmpty(stmtCompletion, undefined).
return m_alternate->execute(interpreter, global_object).update_empty(js_undefined());
}
// IfStatement : if ( Expression ) Statement
// 3. If exprValue is false, then
// a. Return NormalCompletion(undefined).
return normal_completion(js_undefined());
// a. Return undefined.
return js_undefined();
}
// 14.11.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-with-statement-runtime-semantics-evaluation
@ -584,7 +584,7 @@ Completion WithStatement::execute(Interpreter& interpreter, GlobalObject& global
// 7. Set the running execution context's LexicalEnvironment to oldEnv.
interpreter.vm().running_execution_context().lexical_environment = old_environment;
// 8. Return Completion(UpdateEmpty(C, undefined)).
// 8. Return ? UpdateEmpty(C, undefined).
return result.update_empty(js_undefined());
}
@ -616,7 +616,7 @@ static bool loop_continues(Completion const& completion, Vector<FlyString> const
Completion WhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -634,14 +634,14 @@ Completion WhileStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
// b. Let exprValue be ? GetValue(exprRef).
auto test_result = TRY(m_test->execute(interpreter, global_object)).release_value();
// c. If ! ToBoolean(exprValue) is false, return NormalCompletion(V).
// c. If ToBoolean(exprValue) is false, return V.
if (!test_result.to_boolean())
return normal_completion(last_value);
return last_value;
// d. Let stmtResult be the result of evaluating Statement.
auto body_result = m_body->execute(interpreter, global_object);
// e. If LoopContinues(stmtResult, labelSet) is false, return Completion(UpdateEmpty(stmtResult, V)).
// e. If LoopContinues(stmtResult, labelSet) is false, return ? UpdateEmpty(stmtResult, V).
if (!loop_continues(body_result, label_set))
return body_result.update_empty(last_value);
@ -658,7 +658,7 @@ Completion WhileStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
Completion DoWhileStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -675,7 +675,7 @@ Completion DoWhileStatement::loop_evaluation(Interpreter& interpreter, GlobalObj
// a. Let stmtResult be the result of evaluating Statement.
auto body_result = m_body->execute(interpreter, global_object);
// b. If LoopContinues(stmtResult, labelSet) is false, return Completion(UpdateEmpty(stmtResult, V)).
// b. If LoopContinues(stmtResult, labelSet) is false, return ? UpdateEmpty(stmtResult, V).
if (!loop_continues(body_result, label_set))
return body_result.update_empty(last_value);
@ -687,9 +687,9 @@ Completion DoWhileStatement::loop_evaluation(Interpreter& interpreter, GlobalObj
// e. Let exprValue be ? GetValue(exprRef).
auto test_result = TRY(m_test->execute(interpreter, global_object)).release_value();
// f. If ! ToBoolean(exprValue) is false, return NormalCompletion(V).
// f. If ToBoolean(exprValue) is false, return V.
if (!test_result.to_boolean())
return normal_completion(last_value);
return last_value;
}
VERIFY_NOT_REACHED();
@ -700,7 +700,7 @@ Completion DoWhileStatement::loop_evaluation(Interpreter& interpreter, GlobalObj
Completion ForStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -767,7 +767,7 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, GlobalObject&
// f. Set the running execution context's LexicalEnvironment to thisIterationEnv.
interpreter.vm().running_execution_context().lexical_environment = this_iteration_env;
// 2. Return undefined.
// 2. Return unused.
};
// 14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet ), https://tc39.es/ecma262/#sec-forbodyevaluation
@ -786,15 +786,15 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, GlobalObject&
// ii. Let testValue be ? GetValue(testRef).
auto test_value = TRY(m_test->execute(interpreter, global_object)).release_value();
// iii. If ! ToBoolean(testValue) is false, return NormalCompletion(V).
// iii. If ToBoolean(testValue) is false, return V.
if (!test_value.to_boolean())
return normal_completion(last_value);
return last_value;
}
// b. Let result be the result of evaluating stmt.
auto result = m_body->execute(interpreter, global_object);
// c. If LoopContinues(result, labelSet) is false, return Completion(UpdateEmpty(result, V)).
// c. If LoopContinues(result, labelSet) is false, return ? UpdateEmpty(result, V).
if (!loop_continues(result, label_set))
return result.update_empty(last_value);
@ -987,7 +987,7 @@ static ThrowCompletionOr<ForInOfHeadState> for_in_of_head_execute(Interpreter& i
Completion ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -1033,7 +1033,7 @@ Completion ForInStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
// n. If LoopContinues(result, labelSet) is false, then
if (!loop_continues(result, label_set)) {
// 1. Return Completion(UpdateEmpty(result, V)).
// 1. Return UpdateEmpty(result, V).
return result.update_empty(last_value);
}
@ -1052,7 +1052,7 @@ Completion ForInStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
Completion ForOfStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -1106,8 +1106,8 @@ Completion ForOfStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
}));
// Return `status` set during step n.2. in the callback, or...
// e. If done is true, return NormalCompletion(V).
return status.value_or(normal_completion(last_value));
// e. If done is true, return V.
return status.value_or(last_value);
}
// 14.1.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-statement-semantics-runtime-semantics-evaluation
@ -1115,7 +1115,7 @@ Completion ForOfStatement::loop_evaluation(Interpreter& interpreter, GlobalObjec
Completion ForAwaitOfStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -1164,7 +1164,7 @@ Completion ForAwaitOfStatement::loop_evaluation(Interpreter& interpreter, Global
// d. Let done be ? IteratorComplete(nextResult).
auto done = TRY(iterator_complete(global_object, next_result.as_object()));
// e. If done is true, return NormalCompletion(V).
// e. If done is true, return V.
if (done)
return last_value;
@ -1289,7 +1289,7 @@ Completion LogicalExpression::execute(Interpreter& interpreter, GlobalObject& gl
switch (m_op) {
// LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
case LogicalOp::And:
// 3. Let lbool be ! ToBoolean(lval).
// 3. Let lbool be ToBoolean(lval).
// 4. If lbool is false, return lval.
if (!lhs_result.to_boolean())
return lhs_result;
@ -1300,7 +1300,7 @@ Completion LogicalExpression::execute(Interpreter& interpreter, GlobalObject& gl
// LogicalORExpression : LogicalORExpression || LogicalANDExpression
case LogicalOp::Or:
// 3. Let lbool be ! ToBoolean(lval).
// 3. Let lbool be ToBoolean(lval).
// 4. If lbool is true, return lval.
if (lhs_result.to_boolean())
return lhs_result;
@ -1594,7 +1594,7 @@ public:
VERIFY(!m_class_field_identifier_name.is_empty());
// 3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
// a. Let value be NamedEvaluation of Initializer with argument functionObject.[[ClassFieldInitializerName]].
// a. Let value be ? NamedEvaluation of Initializer with argument functionObject.[[ClassFieldInitializerName]].
// 4. Else,
// a. Let rhs be the result of evaluating AssignmentExpression.
// b. Let value be ? GetValue(rhs).
@ -1746,8 +1746,8 @@ Completion ClassDeclaration::execute(Interpreter& interpreter, GlobalObject& glo
// 1. Perform ? BindingClassDeclarationEvaluation of this ClassDeclaration.
(void)TRY(binding_class_declaration_evaluation(interpreter, global_object, m_class_expression));
// 2. Return NormalCompletion(empty).
return normal_completion({});
// 2. Return empty.
return Optional<Value> {};
}
// 15.7.14 Runtime Semantics: ClassDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classdefinitionevaluation
@ -2550,7 +2550,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
// c. If IsAnonymousFunctionDefinition(AssignmentExpression) and IsIdentifierRef of LeftHandSideExpression are both true, then
if (lhs->is_identifier()) {
// i. Let rval be NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
// i. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
auto& identifier_name = static_cast<Identifier const&>(*lhs).string();
rhs_result = TRY(interpreter.vm().named_evaluation_if_anonymous_function(global_object, m_rhs, identifier_name));
}
@ -2594,7 +2594,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
switch (m_op) {
// AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
case AssignmentOp::AndAssignment:
// 3. Let lbool be ! ToBoolean(lval).
// 3. Let lbool be ToBoolean(lval).
// 4. If lbool is false, return lval.
if (!lhs_result.to_boolean())
return lhs_result;
@ -2602,7 +2602,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
// AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
case AssignmentOp::OrAssignment:
// 3. Let lbool be ! ToBoolean(lval).
// 3. Let lbool be ToBoolean(lval).
// 4. If lbool is true, return lval.
if (lhs_result.to_boolean())
return lhs_result;
@ -2623,7 +2623,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
// 5. If IsAnonymousFunctionDefinition(AssignmentExpression) is true and IsIdentifierRef of LeftHandSideExpression is true, then
if (lhs_expression.is_identifier()) {
// a. Let rval be NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
// a. Let rval be ? NamedEvaluation of AssignmentExpression with argument lref.[[ReferencedName]].
auto& identifier_name = static_cast<Identifier const&>(lhs_expression).string();
rhs_result = TRY(interpreter.vm().named_evaluation_if_anonymous_function(global_object, m_rhs, identifier_name));
}
@ -2649,7 +2649,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
// 5. Let assignmentOpText be the source text matched by AssignmentOperator.
// 6. Let opText be the sequence of Unicode code points associated with assignmentOpText in the following table:
// 7. Let r be ApplyStringOrNumericBinaryOperator(lval, opText, rval).
// 7. Let r be ? ApplyStringOrNumericBinaryOperator(lval, opText, rval).
switch (m_op) {
case AssignmentOp::AdditionAssignment:
rhs_result = TRY(add(global_object, lhs_result, rhs_result));
@ -2721,26 +2721,26 @@ Completion UpdateExpression::execute(Interpreter& interpreter, GlobalObject& glo
case UpdateOp::Increment:
// 3. If Type(oldValue) is Number, then
if (old_value.is_number()) {
// a. Let newValue be ! Number::add(oldValue, 1𝔽).
// a. Let newValue be Number::add(oldValue, 1𝔽).
new_value = Value(old_value.as_double() + 1);
}
// 4. Else,
else {
// a. Assert: Type(oldValue) is BigInt.
// b. Let newValue be ! BigInt::add(oldValue, 1).
// b. Let newValue be BigInt::add(oldValue, 1).
new_value = js_bigint(interpreter.heap(), old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 }));
}
break;
case UpdateOp::Decrement:
// 3. If Type(oldValue) is Number, then
if (old_value.is_number()) {
// a. Let newValue be ! Number::subtract(oldValue, 1𝔽).
// a. Let newValue be Number::subtract(oldValue, 1𝔽).
new_value = Value(old_value.as_double() - 1);
}
// 4. Else,
else {
// a. Assert: Type(oldValue) is BigInt.
// b. Let newValue be ! BigInt::subtract(oldValue, 1).
// b. Let newValue be BigInt::subtract(oldValue, 1).
new_value = js_bigint(interpreter.heap(), old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 }));
}
break;
@ -2974,7 +2974,7 @@ Completion ObjectExpression::execute(Interpreter& interpreter, GlobalObject& glo
{
InterpreterNodeScope node_scope { interpreter, *this };
// 1. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
// 1. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// 2. Perform ? PropertyDefinitionEvaluation of PropertyDefinitionList with argument obj.
@ -2983,8 +2983,10 @@ Completion ObjectExpression::execute(Interpreter& interpreter, GlobalObject& glo
// PropertyDefinition : ... AssignmentExpression
if (property.type() == ObjectProperty::Type::Spread) {
// 4. Return ? CopyDataProperties(object, fromValue, excludedNames).
// 4. Perform ? CopyDataProperties(object, fromValue, excludedNames).
TRY(object->copy_data_properties(key, {}, global_object));
// 5. Return unused.
continue;
}
@ -3191,7 +3193,7 @@ Completion MetaProperty::execute(Interpreter& interpreter, GlobalObject& global_
// ImportMeta : import . meta
if (m_type == MetaProperty::Type::ImportMeta) {
// 1. Let module be ! GetActiveScriptOrModule().
// 1. Let module be GetActiveScriptOrModule().
auto script_or_module = interpreter.vm().get_active_script_or_module();
// 2. Assert: module is a Source Text Module Record.
@ -3205,10 +3207,10 @@ Completion MetaProperty::execute(Interpreter& interpreter, GlobalObject& global_
// 4. If importMeta is empty, then
if (import_meta == nullptr) {
// a. Set importMeta to ! OrdinaryObjectCreate(null).
// a. Set importMeta to OrdinaryObjectCreate(null).
import_meta = Object::create(global_object, nullptr);
// b. Let importMetaValues be ! HostGetImportMetaProperties(module).
// b. Let importMetaValues be HostGetImportMetaProperties(module).
auto import_meta_values = interpreter.vm().host_get_import_meta_properties(module);
// c. For each Record { [[Key]], [[Value]] } p of importMetaValues, do
@ -3217,7 +3219,7 @@ Completion MetaProperty::execute(Interpreter& interpreter, GlobalObject& global_
MUST(import_meta->create_data_property_or_throw(entry.key, entry.value));
}
// d. Perform ! HostFinalizeImportMeta(importMeta, module).
// d. Perform HostFinalizeImportMeta(importMeta, module).
interpreter.vm().host_finalize_import_meta(import_meta, module);
// e. Set module.[[ImportMeta]] to importMeta.
@ -3258,7 +3260,7 @@ Completion ImportCall::execute(Interpreter& interpreter, GlobalObject& global_ob
InterpreterNodeScope node_scope { interpreter, *this };
// 2.1.1.1 EvaluateImportCall ( specifierExpression [ , optionsExpression ] ), https://tc39.es/proposal-import-assertions/#sec-evaluate-import-call
// 1. Let referencingScriptOrModule be ! GetActiveScriptOrModule().
// 1. Let referencingScriptOrModule be GetActiveScriptOrModule().
auto referencing_script_or_module = interpreter.vm().get_active_script_or_module();
// 2. Let specifierRef be the result of evaluating specifierExpression.
@ -3279,7 +3281,7 @@ Completion ImportCall::execute(Interpreter& interpreter, GlobalObject& global_ob
// 6. Let promiseCapability be ! NewPromiseCapability(%Promise%).
auto promise_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
// 7. Let specifierString be ToString(specifier).
// 7. Let specifierString be Completion(ToString(specifier)).
// 8. IfAbruptRejectPromise(specifierString, promiseCapability).
auto specifier_string = TRY_OR_REJECT_WITH_VALUE(global_object, promise_capability, specifier->to_string(global_object));
@ -3353,7 +3355,7 @@ Completion ImportCall::execute(Interpreter& interpreter, GlobalObject& global_ob
// 11. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Assertions]]: assertions }.
ModuleRequest request { specifier_string, assertions };
// 12. Perform ! HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability).
// 12. Perform HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability).
interpreter.vm().host_import_module_dynamically(referencing_script_or_module, move(request), promise_capability);
// 13. Return promiseCapability.[[Promise]].
@ -3427,13 +3429,13 @@ Completion RegExpLiteral::execute(Interpreter& interpreter, GlobalObject& global
{
InterpreterNodeScope node_scope { interpreter, *this };
// 1. Let pattern be ! CodePointsToString(BodyText of RegularExpressionLiteral).
// 1. Let pattern be CodePointsToString(BodyText of RegularExpressionLiteral).
auto pattern = this->pattern();
// 2. Let flags be ! CodePointsToString(FlagText of RegularExpressionLiteral).
// 2. Let flags be CodePointsToString(FlagText of RegularExpressionLiteral).
auto flags = this->flags();
// 3. Return RegExpCreate(pattern, flags).
// 3. Return ! RegExpCreate(pattern, flags).
Regex<ECMA262> regex(parsed_regex(), parsed_pattern(), parsed_flags());
return Value { RegExpObject::create(global_object, move(regex), move(pattern), move(flags)) };
}
@ -3459,8 +3461,7 @@ Completion ArrayExpression::execute(Interpreter& interpreter, GlobalObject& glob
// 1. Let array be ! ArrayCreate(0).
auto* array = MUST(Array::create(global_object, 0));
// 2. Let len be the result of performing ArrayAccumulation of ElementList with arguments array and 0.
// 3. ReturnIfAbrupt(len).
// 2. Perform ? ArrayAccumulation of ElementList with arguments array and 0.
array->indexed_properties();
size_t index = 0;
@ -3480,7 +3481,7 @@ Completion ArrayExpression::execute(Interpreter& interpreter, GlobalObject& glob
array->indexed_properties().put(index++, value, default_attributes);
}
// 4. Return array.
// 3. Return array.
return Value { array };
}
@ -3637,7 +3638,7 @@ Completion TryStatement::execute(Interpreter& interpreter, GlobalObject& global_
// 4. Set the running execution context's LexicalEnvironment to catchEnv.
vm.running_execution_context().lexical_environment = catch_environment;
// 5. Let status be BindingInitialization of CatchParameter with arguments thrownValue and catchEnv.
// 5. Let status be Completion(BindingInitialization of CatchParameter with arguments thrownValue and catchEnv).
auto status = m_handler->parameter().visit(
[&](FlyString const& parameter) {
return catch_environment->initialize_binding(global_object, parameter, thrown_value);
@ -3651,7 +3652,7 @@ Completion TryStatement::execute(Interpreter& interpreter, GlobalObject& global_
// a. Set the running execution context's LexicalEnvironment to oldEnv.
vm.running_execution_context().lexical_environment = old_environment;
// b. Return Completion(status).
// b. Return ? status.
return status.release_error();
}
@ -3661,7 +3662,7 @@ Completion TryStatement::execute(Interpreter& interpreter, GlobalObject& global_
// 8. Set the running execution context's LexicalEnvironment to oldEnv.
vm.running_execution_context().lexical_environment = old_environment;
// 9. Return Completion(B).
// 9. Return ? B.
return handler_result;
};
@ -3673,7 +3674,7 @@ Completion TryStatement::execute(Interpreter& interpreter, GlobalObject& global_
// TryStatement : try Block Catch
// TryStatement : try Block Catch Finally
if (m_handler) {
// 2. If B.[[Type]] is throw, let C be CatchClauseEvaluation of Catch with argument B.[[Value]].
// 2. If B.[[Type]] is throw, let C be Completion(CatchClauseEvaluation of Catch with argument B.[[Value]]).
if (block_result.type() == Completion::Type::Throw)
result = catch_clause_evaluation(*block_result.value());
// 3. Else, let C be B.
@ -3695,11 +3696,11 @@ Completion TryStatement::execute(Interpreter& interpreter, GlobalObject& global_
if (finalizer_result.type() == Completion::Type::Normal)
finalizer_result = move(result);
// 6. Return Completion(UpdateEmpty(F, undefined)).
// 6. Return ? UpdateEmpty(F, undefined).
return finalizer_result.update_empty(js_undefined());
}
// 4. Return Completion(UpdateEmpty(C, undefined)).
// 4. Return ? UpdateEmpty(C, undefined).
return result.update_empty(js_undefined());
}
@ -3730,7 +3731,7 @@ Completion ThrowStatement::execute(Interpreter& interpreter, GlobalObject& globa
Completion SwitchStatement::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
// 1. Let newLabelSet be a new empty List.
// 2. Return the result of performing LabelledEvaluation of this BreakableStatement with argument newLabelSet.
// 2. Return ? LabelledEvaluation of this BreakableStatement with argument newLabelSet.
return labelled_evaluation(interpreter, global_object, *this, {});
}
@ -3757,11 +3758,11 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
};
// 14.12.2 Runtime Semantics: CaseBlockEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-caseblockevaluation
auto case_block_evaluation = [&](auto input) {
auto case_block_evaluation = [&](auto input) -> Completion {
// CaseBlock : { }
if (m_cases.is_empty()) {
// 1. Return NormalCompletion(undefined).
return normal_completion(js_undefined());
// 1. Return undefined.
return js_undefined();
}
NonnullRefPtrVector<SwitchCase> case_clauses_1;
@ -3807,14 +3808,14 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
if (result.value().has_value())
last_value = *result.value();
// iii. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
// iii. If R is an abrupt completion, return ? UpdateEmpty(R, V).
if (result.is_abrupt())
return result.update_empty(last_value);
}
}
// 5. Return NormalCompletion(V).
return normal_completion(last_value);
// 5. Return V.
return last_value;
}
// CaseBlock : { CaseClauses[opt] DefaultClause CaseClauses[opt] }
else {
@ -3847,7 +3848,7 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
if (result.value().has_value())
last_value = *result.value();
// iii. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
// iii. If R is an abrupt completion, return ? UpdateEmpty(R, V).
if (result.is_abrupt())
return result.update_empty(last_value);
}
@ -3881,16 +3882,16 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
if (result.value().has_value())
last_value = *result.value();
// 3. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
// 3. If R is an abrupt completion, return ? UpdateEmpty(R, V).
if (result.is_abrupt())
return result.update_empty(last_value);
}
}
}
// 10. If foundInB is true, return NormalCompletion(V).
// 10. If foundInB is true, return V.
if (found_in_b)
return normal_completion(last_value);
return last_value;
// 11. Let R be the result of evaluating DefaultClause.
auto result = default_clause->evaluate_statements(interpreter, global_object);
@ -3899,7 +3900,7 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
if (result.value().has_value())
last_value = *result.value();
// 13. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
// 13. If R is an abrupt completion, return ? UpdateEmpty(R, V).
if (result.is_abrupt())
return result.update_empty(last_value);
@ -3913,13 +3914,13 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
if (result.value().has_value())
last_value = *result.value();
// c. If R is an abrupt completion, return Completion(UpdateEmpty(R, V)).
// c. If R is an abrupt completion, return ? UpdateEmpty(R, V).
if (result.is_abrupt())
return result.update_empty(last_value);
}
// 16. Return NormalCompletion(V).
return normal_completion(last_value);
// 16. Return V.
return last_value;
}
VERIFY_NOT_REACHED();
@ -3945,7 +3946,7 @@ Completion SwitchStatement::execute_impl(Interpreter& interpreter, GlobalObject&
vm.running_execution_context().lexical_environment = block_environment;
}
// 7. Let R be CaseBlockEvaluation of CaseBlock with argument switchValue.
// 7. Let R be Completion(CaseBlockEvaluation of CaseBlock with argument switchValue).
auto result = case_block_evaluation(switch_value);
// 8. Set the running execution context's LexicalEnvironment to oldEnv.
@ -4027,7 +4028,7 @@ Completion ConditionalExpression::execute(Interpreter& interpreter, GlobalObject
InterpreterNodeScope node_scope { interpreter, *this };
// 1. Let lref be the result of evaluating ShortCircuitExpression.
// 2. Let lval be ! ToBoolean(? GetValue(lref)).
// 2. Let lval be ToBoolean(? GetValue(lref)).
auto test_result = TRY(m_test->execute(interpreter, global_object)).release_value();
// 3. If lval is true, then
@ -4091,17 +4092,15 @@ Completion DebuggerStatement::execute(Interpreter& interpreter, GlobalObject&) c
// 1. If an implementation-defined debugging facility is available and enabled, then
if (false) {
// a. Perform an implementation-defined debugging action.
// b. Let result be an implementation-defined Completion value.
// b. Return a new implementation-defined Completion Record.
}
// 2. Else,
else {
// a. Let result be NormalCompletion(empty).
result = normal_completion({});
// a. Return empty.
return Optional<Value> {};
}
// 3. Return result.
return result;
}
ThrowCompletionOr<void> ScopeNode::for_each_lexically_scoped_declaration(ThrowCompletionOrVoidCallback<Declaration const&>&& callback) const
{
for (auto& declaration : m_lexical_declarations)
@ -4180,8 +4179,8 @@ Completion ImportStatement::execute(Interpreter& interpreter, GlobalObject&) con
{
InterpreterNodeScope node_scope { interpreter, *this };
// 1. Return NormalCompletion(empty).
return normal_completion({});
// 1. Return empty.
return Optional<Value> {};
}
FlyString ExportStatement::local_name_for_default = "*default*";
@ -4197,8 +4196,8 @@ Completion ExportStatement::execute(Interpreter& interpreter, GlobalObject& glob
return m_statement->execute(interpreter, global_object);
}
// 1. Return NormalCompletion(empty).
return normal_completion({});
// 1. Return empty.
return Optional<Value> {};
}
VERIFY(m_statement);
@ -4222,8 +4221,8 @@ Completion ExportStatement::execute(Interpreter& interpreter, GlobalObject& glob
// Note: We never go into step 3. since a ClassDeclaration always has a name and "*default*" is not a class name.
(void)value;
// 4. Return NormalCompletion(empty).
return normal_completion({});
// 4. Return empty.
return Optional<Value> {};
}
// ExportDeclaration : export default ClassDeclaration
@ -4246,8 +4245,8 @@ Completion ExportStatement::execute(Interpreter& interpreter, GlobalObject& glob
TRY(initialize_bound_name(global_object, ExportStatement::local_name_for_default, value, env));
}
// 4. Return NormalCompletion(empty).
return normal_completion({});
// 4. Return empty.
return Optional<Value> {};
}
// ExportDeclaration : export default AssignmentExpression ;
@ -4265,8 +4264,8 @@ Completion ExportStatement::execute(Interpreter& interpreter, GlobalObject& glob
// 4. Perform ? InitializeBoundName("*default*", value, env).
TRY(initialize_bound_name(global_object, ExportStatement::local_name_for_default, value, env));
// 5. Return NormalCompletion(empty).
return normal_completion({});
// 5. Return empty.
return Optional<Value> {};
}
static void dump_assert_clauses(ModuleRequest const& request)
@ -4516,7 +4515,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
// ii. Let benv be the running execution context's LexicalEnvironment.
// iii. Let fobj be ! benv.GetBindingValue(F, false).
// iv. Perform ? genv.SetMutableBinding(F, fobj, false).
// v. Return NormalCompletion(empty).
// v. Return unused.
function_declaration.set_should_do_additional_annexB_steps();
return {};
@ -4566,7 +4565,7 @@ ThrowCompletionOr<void> Program::global_declaration_instantiation(Interpreter& i
TRY(global_environment.create_global_var_binding(var_name, false));
}
// 18. Return NormalCompletion(empty).
// 18. Return unused.
return {};
}

View file

@ -194,7 +194,7 @@ Bytecode::CodeGenerationErrorOr<void> ScopeNode::generate_bytecode(Bytecode::Gen
// ii. Let benv be the running execution context's LexicalEnvironment.
// iii. Let fobj be ! benv.GetBindingValue(F, false).
// iv. Perform ? genv.SetMutableBinding(F, fobj, false).
// v. Return NormalCompletion(empty).
// v. Return unused.
function_declaration.set_should_do_additional_annexB_steps();
});
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -69,7 +69,8 @@ JS_DEFINE_NATIVE_FUNCTION($262Object::detach_array_buffer)
return vm.throw_completion<TypeError>(global_object);
auto& array_buffer_object = static_cast<ArrayBuffer&>(array_buffer.as_object());
return JS::detach_array_buffer(global_object, array_buffer_object, vm.argument(1));
TRY(JS::detach_array_buffer(global_object, array_buffer_object, vm.argument(1)));
return js_null();
}
JS_DEFINE_NATIVE_FUNCTION($262Object::eval_script)

View file

@ -26,11 +26,11 @@ ThrowCompletionOr<void> CyclicModule::link(VM& vm)
// 2. Let stack be a new empty List.
Vector<Module*> stack;
// 3. Let result be InnerModuleLinking(module, stack, 0).
auto inner_module_linked_or_error = inner_module_linking(vm, stack, 0);
// 3. Let result be Completion(InnerModuleLinking(module, stack, 0)).
auto result = inner_module_linking(vm, stack, 0);
// 4. If result is an abrupt completion, then
if (inner_module_linked_or_error.is_error()) {
if (result.is_throw_completion()) {
// a. For each Cyclic Module Record m of stack, do
for (auto* module : stack) {
if (is<CyclicModule>(module)) {
@ -46,7 +46,7 @@ ThrowCompletionOr<void> CyclicModule::link(VM& vm)
VERIFY(m_status == ModuleStatus::Unlinked);
// c. Return result.
return inner_module_linked_or_error.release_error();
return result.release_error();
}
// 5. Assert: module.[[Status]] is linked, evaluating-async, or evaluated.
@ -54,8 +54,7 @@ ThrowCompletionOr<void> CyclicModule::link(VM& vm)
// 6. Assert: stack is empty.
VERIFY(stack.is_empty());
// 7. Return undefined.
// Note: We return void since the result of this is never used.
// 7. Return unused.
return {};
}
@ -130,7 +129,7 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_linking(VM& vm, Vector<Module*
}
// 10. Perform ? module.InitializeEnvironment().
(void)TRY(initialize_environment(vm));
TRY(initialize_environment(vm));
// 11. Assert: module occurs exactly once in stack.
size_t count = 0;
@ -204,7 +203,7 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
// 7. Set module.[[TopLevelCapability]] to capability.
m_top_level_capability = MUST(new_promise_capability(global_object, global_object.promise_constructor()));
// 8. Let result be InnerModuleEvaluation(module, stack, 0).
// 8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
auto result = inner_module_evaluation(vm, stack, 0);
// 9. If result is an abrupt completion, then
@ -273,7 +272,7 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Modu
if (!m_evaluation_error.is_error())
return index;
// b. Otherwise, return module.[[EvaluationError]].
// b. Otherwise, return ? module.[[EvaluationError]].
return m_evaluation_error.throw_completion();
}
@ -336,7 +335,7 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Modu
// 2. Assert: requiredModule.[[Status]] is evaluating-async or evaluated.
VERIFY(cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated);
// 3. If requiredModule.[[EvaluationError]] is not empty, return requiredModule.[[EvaluationError]].
// 3. If requiredModule.[[EvaluationError]] is not empty, return ? requiredModule.[[EvaluationError]].
if (cyclic_module->m_evaluation_error.is_error())
return cyclic_module->m_evaluation_error.throw_completion();
}
@ -361,13 +360,13 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Modu
m_async_evaluation = true;
// c. NOTE: The order in which module records have their [[AsyncEvaluation]] fields transition to true is significant. (See 16.2.1.5.2.4.)
// d. If module.[[PendingAsyncDependencies]] is 0, perform ! ExecuteAsyncModule(module).
// d. If module.[[PendingAsyncDependencies]] is 0, perform ExecuteAsyncModule(module).
if (m_pending_async_dependencies.value() == 0)
MUST(execute_async_module(vm));
execute_async_module(vm);
}
// 13. Otherwise, perform ? module.ExecuteModule().
else {
(void)TRY(execute_module(vm));
TRY(execute_module(vm));
}
// 14. Assert: module occurs exactly once in stack.
@ -417,24 +416,22 @@ ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Modu
return index;
}
Completion CyclicModule::initialize_environment(VM&)
ThrowCompletionOr<void> CyclicModule::initialize_environment(VM&)
{
// Note: In ecma262 this is never called on a cyclic module only on SourceTextModules.
// So this check is to make sure we don't accidentally call this.
VERIFY_NOT_REACHED();
return normal_completion({});
}
Completion CyclicModule::execute_module(VM&, Optional<PromiseCapability>)
ThrowCompletionOr<void> CyclicModule::execute_module(VM&, Optional<PromiseCapability>)
{
// Note: In ecma262 this is never called on a cyclic module only on SourceTextModules.
// So this check is to make sure we don't accidentally call this.
VERIFY_NOT_REACHED();
return js_undefined();
}
// 16.2.1.5.2.2 ExecuteAsyncModule ( module ), https://tc39.es/ecma262/#sec-execute-async-module
ThrowCompletionOr<void> CyclicModule::execute_async_module(VM& vm)
void CyclicModule::execute_async_module(VM& vm)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] executing async module {}", filename());
// 1. Assert: module.[[Status]] is evaluating or evaluating-async.
@ -449,43 +446,43 @@ ThrowCompletionOr<void> CyclicModule::execute_async_module(VM& vm)
// 4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and performs the following steps when called:
auto fulfilled_closure = [&](VM& vm, GlobalObject&) -> ThrowCompletionOr<Value> {
// a. Perform ! AsyncModuleExecutionFulfilled(module).
MUST(async_module_execution_fulfilled(vm));
// a. Perform AsyncModuleExecutionFulfilled(module).
async_module_execution_fulfilled(vm);
// b. Return undefined.
return js_undefined();
};
// 5. Let onFulfilled be ! CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
// 5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
auto* on_fulfilled = NativeFunction::create(global_object, move(fulfilled_closure), 0, "");
// 6. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures module and performs the following steps when called:
auto rejected_closure = [&](VM& vm, GlobalObject&) -> ThrowCompletionOr<Value> {
auto error = vm.argument(0);
// a. Perform ! AsyncModuleExecutionRejected(module, error).
MUST(async_module_execution_rejected(vm, error));
// a. Perform AsyncModuleExecutionRejected(module, error).
async_module_execution_rejected(vm, error);
// b. Return undefined.
return js_undefined();
};
// 7. Let onRejected be ! CreateBuiltinFunction(rejectedClosure, 0, "", « »).
// 7. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »).
auto* on_rejected = NativeFunction::create(global_object, move(rejected_closure), 0, "");
VERIFY(is<Promise>(*capability.promise));
// 8. Perform ! PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
// 8. Perform PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
static_cast<Promise*>(capability.promise)->perform_then(on_fulfilled, on_rejected, {});
// 9. Perform ! module.ExecuteModule(capability).
(void)MUST(execute_module(vm, capability));
MUST(execute_module(vm, capability));
return {};
// 10. Return unused.
}
// 16.2.1.5.2.3 GatherAvailableAncestors ( module, execList ), https://tc39.es/ecma262/#sec-gather-available-ancestors
ThrowCompletionOr<void> CyclicModule::gather_available_ancestors(Vector<CyclicModule*>& exec_list)
void CyclicModule::gather_available_ancestors(Vector<CyclicModule*>& exec_list)
{
// 1. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
for (auto* module : m_async_parent_modules) {
@ -511,25 +508,26 @@ ThrowCompletionOr<void> CyclicModule::gather_available_ancestors(Vector<CyclicMo
// 1. Append m to execList.
exec_list.append(module);
// 2. If m.[[HasTLA]] is false, perform ! GatherAvailableAncestors(m, execList).
// 2. If m.[[HasTLA]] is false, perform GatherAvailableAncestors(m, execList).
if (!module->m_has_top_level_await)
MUST(module->gather_available_ancestors(exec_list));
module->gather_available_ancestors(exec_list);
}
}
}
return {};
// 2. Return unused.
}
// 16.2.1.5.2.4 AsyncModuleExecutionFulfilled ( module ), https://tc39.es/ecma262/#sec-async-module-execution-fulfilled
ThrowCompletionOr<void> CyclicModule::async_module_execution_fulfilled(VM& vm)
void CyclicModule::async_module_execution_fulfilled(VM& vm)
{
// 1. If module.[[Status]] is evaluated, then
if (m_status == ModuleStatus::Evaluated) {
// a. Assert: module.[[EvaluationError]] is not empty.
VERIFY(m_evaluation_error.is_error());
// b. Return.
return {};
// b. Return unused.
return;
}
// 2. Assert: module.[[Status]] is evaluating-async.
@ -560,8 +558,8 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_fulfilled(VM& vm)
// 8. Let execList be a new empty List.
Vector<CyclicModule*> exec_list;
// 9. Perform ! GatherAvailableAncestors(module, execList).
MUST(gather_available_ancestors(exec_list));
// 9. Perform GatherAvailableAncestors(module, execList).
gather_available_ancestors(exec_list);
// 10. Let sortedExecList be a List whose elements are the elements of execList, in the order in which they had their [[AsyncEvaluation]] fields set to true in InnerModuleEvaluation.
// FIXME: Sort the list. To do this we need to use more than an Optional<bool> to track [[AsyncEvaluation]].
@ -578,8 +576,8 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_fulfilled(VM& vm)
}
// b. Else if m.[[HasTLA]] is true, then
else if (module->m_has_top_level_await) {
// i. Perform ! ExecuteAsyncModule(m).
MUST(module->execute_async_module(vm));
// i. Perform ExecuteAsyncModule(m).
module->execute_async_module(vm);
}
// c. Else,
else {
@ -587,9 +585,9 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_fulfilled(VM& vm)
auto result = module->execute_module(vm);
// ii. If result is an abrupt completion, then
if (result.is_abrupt()) {
// 1. Perform ! AsyncModuleExecutionRejected(m, result.[[Value]]).
module->async_module_execution_rejected(vm, *result.value());
if (result.is_throw_completion()) {
// 1. Perform AsyncModuleExecutionRejected(m, result.[[Value]]).
module->async_module_execution_rejected(vm, *result.throw_completion().value());
}
// iii. Else,
else {
@ -608,18 +606,20 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_fulfilled(VM& vm)
}
}
}
return {};
// 13. Return unused.
}
// 16.2.1.5.2.5 AsyncModuleExecutionRejected ( module, error ), https://tc39.es/ecma262/#sec-async-module-execution-rejected
ThrowCompletionOr<void> CyclicModule::async_module_execution_rejected(VM& vm, Value error)
void CyclicModule::async_module_execution_rejected(VM& vm, Value error)
{
// 1. If module.[[Status]] is evaluated, then
if (m_status == ModuleStatus::Evaluated) {
// a. Assert: module.[[EvaluationError]] is not empty.
VERIFY(m_evaluation_error.is_error());
// b. Return.
return {};
// b. Return unused.
return;
}
// 2. Assert: module.[[Status]] is evaluating-async.
@ -640,8 +640,8 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_rejected(VM& vm, Va
// 7. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
for (auto* module : m_async_parent_modules) {
// a. Perform ! AsyncModuleExecutionRejected(m, error).
MUST(module->async_module_execution_rejected(vm, error));
// a. Perform AsyncModuleExecutionRejected(m, error).
module->async_module_execution_rejected(vm, error);
}
// 8. If module.[[TopLevelCapability]] is not empty, then
@ -654,7 +654,7 @@ ThrowCompletionOr<void> CyclicModule::async_module_execution_rejected(VM& vm, Va
MUST(call(vm.current_realm()->global_object(), m_top_level_capability->reject, js_undefined(), error));
}
return {};
// 9. Return unused.
}
}

View file

@ -37,13 +37,13 @@ protected:
virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index) override;
virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) override;
virtual Completion initialize_environment(VM& vm);
virtual Completion execute_module(VM& vm, Optional<PromiseCapability> capability = {});
virtual ThrowCompletionOr<void> initialize_environment(VM& vm);
virtual ThrowCompletionOr<void> execute_module(VM& vm, Optional<PromiseCapability> capability = {});
ThrowCompletionOr<void> execute_async_module(VM& vm);
ThrowCompletionOr<void> gather_available_ancestors(Vector<CyclicModule*>& exec_list);
ThrowCompletionOr<void> async_module_execution_fulfilled(VM& vm);
ThrowCompletionOr<void> async_module_execution_rejected(VM& vm, Value error);
void execute_async_module(VM& vm);
void gather_available_ancestors(Vector<CyclicModule*>& exec_list);
void async_module_execution_fulfilled(VM& vm);
void async_module_execution_rejected(VM& vm, Value error);
ModuleStatus m_status { ModuleStatus::Unlinked }; // [[Status]]
ThrowCompletionOr<void> m_evaluation_error; // [[EvaluationError]]

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -80,7 +80,7 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record)
// 11. Let script be scriptRecord.[[ECMAScriptCode]].
auto& script = script_record.parse_node();
// 12. Let result be GlobalDeclarationInstantiation(script, globalEnv).
// 12. Let result be Completion(GlobalDeclarationInstantiation(script, globalEnv)).
auto instantiation_result = script.global_declaration_instantiation(*this, global_object, global_environment);
Completion result = instantiation_result.is_throw_completion() ? instantiation_result.throw_completion() : normal_completion({});
@ -116,7 +116,7 @@ ThrowCompletionOr<Value> Interpreter::run(Script& script_record)
vm.finish_execution_generation();
// 18. Return Completion(result).
// 18. Return ? result.
if (result.is_abrupt()) {
VERIFY(result.type() == Completion::Type::Throw);
return result.release_error();

View file

@ -90,7 +90,7 @@ public:
// 11. Create any host-defined global object properties on globalObj.
static_cast<GlobalObjectType*>(global_object)->initialize_global_object();
// 12. Return NormalCompletion(empty).
// 12. Return unused.
return interpreter;
}

View file

@ -91,7 +91,7 @@ Object* Module::module_namespace_create(VM& vm, Vector<FlyString> unambiguous_na
VERIFY(m_namespace.is_null());
// 2. Let internalSlotsList be the internal slots listed in Table 34.
// 3. Let M be ! MakeBasicObject(internalSlotsList).
// 3. Let M be MakeBasicObject(internalSlotsList).
// 4. Set M's essential internal methods to the definitions specified in 10.4.6.
// 5. Set M.[[Module]] to module.
// 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.

View file

@ -217,17 +217,16 @@ ThrowCompletionOr<void> initialize_bound_name(GlobalObject& global_object, FlySt
// 1. If environment is not undefined, then
if (environment) {
// a. Perform environment.InitializeBinding(name, value).
// a. Perform ! environment.InitializeBinding(name, value).
MUST(environment->initialize_binding(global_object, name, value));
// b. Return NormalCompletion(undefined).
// b. Return unused.
return {};
}
// 2. Else,
else {
// a. Let lhs be ResolveBinding(name).
// NOTE: Although the spec pretends resolve_binding cannot fail it can just not in this case.
auto lhs = MUST(vm.resolve_binding(name));
// a. Let lhs be ? ResolveBinding(name).
auto lhs = TRY(vm.resolve_binding(name));
// b. Return ? PutValue(lhs, value).
return TRY(lhs.put_value(global_object, value));
@ -246,7 +245,7 @@ bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const
// 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ), https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& property_key, bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
{
// 1. Assert: ! IsPropertyKey(P) is true.
// 1. Assert: IsPropertyKey(P) is true.
VERIFY(property_key.is_valid());
// 2. If current is undefined, then
@ -288,21 +287,21 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
if (descriptor.configurable.has_value() && *descriptor.configurable)
return false;
// b. If Desc has an [[Enumerable]] field and ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
// b. If Desc has an [[Enumerable]] field and SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
if (descriptor.enumerable.has_value() && *descriptor.enumerable != *current->enumerable)
return false;
// c. If ! IsGenericDescriptor(Desc) is false and ! SameValue(IsAccessorDescriptor(Desc), IsAccessorDescriptor(current)) is false, return false.
// c. If IsGenericDescriptor(Desc) is false and SameValue(IsAccessorDescriptor(Desc), IsAccessorDescriptor(current)) is false, return false.
if (!descriptor.is_generic_descriptor() && (descriptor.is_accessor_descriptor() != current->is_accessor_descriptor()))
return false;
// d. If ! IsAccessorDescriptor(Desc) is true, then
// d. If IsAccessorDescriptor(Desc) is true, then
if (descriptor.is_accessor_descriptor()) {
// i. If Desc has a [[Get]] field and ! SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
// i. If Desc has a [[Get]] field and SameValue(Desc.[[Get]], current.[[Get]]) is false, return false.
if (descriptor.get.has_value() && *descriptor.get != *current->get)
return false;
// ii. If Desc has a [[Set]] field and ! SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
// ii. If Desc has a [[Set]] field and SameValue(Desc.[[Set]], current.[[Set]]) is false, return false.
if (descriptor.set.has_value() && *descriptor.set != *current->set)
return false;
}
@ -313,7 +312,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
if (descriptor.writable.has_value() && *descriptor.writable)
return false;
// ii. If Desc has a [[Value]] field and ! SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
// ii. If Desc has a [[Value]] field and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
if (descriptor.value.has_value() && (*descriptor.value != *current->value))
return false;
}
@ -321,7 +320,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
// 6. If O is not undefined, then
if (object != nullptr) {
// a. If ! IsDataDescriptor(current) is true and ! IsAccessorDescriptor(Desc) is true, then
// a. If IsDataDescriptor(current) is true and IsAccessorDescriptor(Desc) is true, then
if (current->is_data_descriptor() && descriptor.is_accessor_descriptor()) {
// i. If Desc has a [[Configurable]] field, let configurable be Desc.[[Configurable]], else let configurable be current.[[Configurable]].
auto configurable = descriptor.configurable.value_or(*current->configurable);
@ -336,7 +335,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
attributes.set_configurable(configurable);
object->storage_set(property_key, { accessor, attributes });
}
// b. Else if ! IsAccessorDescriptor(current) is true and ! IsDataDescriptor(Desc) is true, then
// b. Else if IsAccessorDescriptor(current) is true and IsDataDescriptor(Desc) is true, then
else if (current->is_accessor_descriptor() && descriptor.is_data_descriptor()) {
// i. If Desc has a [[Configurable]] field, let configurable be Desc.[[Configurable]], else let configurable be current.[[Configurable]].
auto configurable = descriptor.configurable.value_or(*current->configurable);
@ -488,7 +487,6 @@ ThrowCompletionOr<Reference> make_super_property_reference(GlobalObject& global_
// 4. Let bv be ? RequireObjectCoercible(baseValue).
auto bv = TRY(require_object_coercible(global_object, base_value));
// 5. Return the Reference Record { [[Base]]: bv, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }.
// 6. NOTE: This returns a Super Reference Record.
return Reference { bv, property_key, actual_this, strict };
}
@ -730,7 +728,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
// 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_name([&](auto const& name) -> ThrowCompletionOr<void> {
// a. If thisEnv.HasBinding(name) is true, then
// a. If ! thisEnv.HasBinding(name) is true, then
if (MUST(this_environment->has_binding(name))) {
// i. Throw a SyntaxError exception.
return vm.throw_completion<SyntaxError>(global_object, ErrorType::TopLevelVariableAlreadyDeclared, name);
@ -821,8 +819,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
while (this_environment != variable_environment) {
// a. If thisEnv is not an object Environment Record, then
if (!is<ObjectEnvironment>(*this_environment)) {
// i. If thisEnv.HasBinding(F) is true, then
// i. If ! thisEnv.HasBinding(F) is true, then
if (MUST(this_environment->has_binding(function_name))) {
// i. Let bindingExists be true.
// Note: When bindingExists is true we skip all the other steps.
@ -866,7 +863,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
// ii. Else,
else {
// i. Let bindingExists be varEnv.HasBinding(F).
// i. Let bindingExists be ! varEnv.HasBinding(F).
// ii. If bindingExists is false, then
if (!MUST(variable_environment->has_binding(function_name))) {
// i. Perform ! varEnv.CreateMutableBinding(F, true).
@ -885,7 +882,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
// ii. Let benv be the running execution context's LexicalEnvironment.
// iii. Let fobj be ! benv.GetBindingValue(F, false).
// iv. Perform ? genv.SetMutableBinding(F, fobj, false).
// v. Return NormalCompletion(empty).
// v. Return unused.
function_declaration.set_should_do_additional_annexB_steps();
return {};
@ -958,13 +955,13 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
}
// d. Else,
else {
// i. Let bindingExists be varEnv.HasBinding(fn).
// i. Let bindingExists be ! varEnv.HasBinding(fn).
auto binding_exists = MUST(variable_environment->has_binding(declaration.name()));
// ii. If bindingExists is false, then
if (!binding_exists) {
// 1. Let status be ! varEnv.CreateMutableBinding(fn, true).
// 2. Assert: status is not an abrupt completion because of validation preceding step 14.
// 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(global_object, declaration.name(), true));
// 3. Perform ! varEnv.InitializeBinding(fn, fo).
@ -988,13 +985,13 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
}
// b. Else,
else {
// i. Let bindingExists be varEnv.HasBinding(vn).
// i. Let bindingExists be ! varEnv.HasBinding(vn).
auto binding_exists = MUST(variable_environment->has_binding(var_name));
// ii. If bindingExists is false, then
if (!binding_exists) {
// 1. Let status be ! varEnv.CreateMutableBinding(vn, true).
// 2. Assert: status is not an abrupt completion because of validation preceding step 14.
// 1. NOTE: The following invocation cannot return an abrupt completion because of the validation preceding step 14.
// 2. Perform ! varEnv.CreateMutableBinding(vn, true).
MUST(variable_environment->create_mutable_binding(global_object, var_name, true));
// 3. Perform ! varEnv.InitializeBinding(vn, undefined).
@ -1003,7 +1000,7 @@ ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, GlobalObject& glo
}
}
// 19. Return NormalCompletion(empty).
// 19. Return unused.
return {};
}
@ -1015,12 +1012,12 @@ Object* create_unmapped_arguments_object(GlobalObject& global_object, Span<Value
// 1. Let len be the number of elements in argumentsList.
auto length = arguments.size();
// 2. Let obj be ! OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »).
// 2. Let obj be OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »).
// 3. Set obj.[[ParameterMap]] to undefined.
auto* object = Object::create(global_object, global_object.object_prototype());
object->set_has_parameter_map();
// 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
// 4. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }).
MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true }));
// 5. Let index be 0.
@ -1058,7 +1055,7 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
VERIFY(arguments.size() <= NumericLimits<i32>::max());
i32 length = static_cast<i32>(arguments.size());
// 3. Let obj be ! MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »).
// 3. Let obj be MakeBasicObject(« [[Prototype]], [[Extensible]], [[ParameterMap]] »).
// 4. Set obj.[[GetOwnProperty]] as specified in 10.4.4.1.
// 5. Set obj.[[DefineOwnProperty]] as specified in 10.4.4.2.
// 6. Set obj.[[Get]] as specified in 10.4.4.3.
@ -1103,7 +1100,7 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
if (index < length) {
// 1. Let g be MakeArgGetter(name, env).
// 2. Let p be MakeArgSetter(name, env).
// 3. Perform map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
// 3. Perform ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true }).
object->parameter_map().define_native_accessor(
PropertyKey { index },
[&environment, name](VM&, GlobalObject& global_object_getter) -> ThrowCompletionOr<Value> {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -46,7 +46,7 @@ ThrowCompletionOr<Object*> AggregateErrorConstructor::construct(FunctionObject&
if (!vm.argument(1).is_undefined()) {
auto message = TRY(vm.argument(1).to_string(global_object));
MUST(aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message)));
aggregate_error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, message));
}
TRY(aggregate_error->install_error_cause(vm.argument(2)));

View file

@ -41,14 +41,15 @@ ThrowCompletionOr<Value> ArgumentsObject::internal_get(PropertyKey const& proper
// 3. If isMapped is false, then
if (!is_mapped) {
// a. Return ? OrdinaryGet(args, P, Receiver).
// a. Return ! OrdinaryGet(args, P, Receiver).
// FIXME: Using MUST here breaks one test in test262 (spec issue).
return Object::internal_get(property_key, receiver);
}
// FIXME: a. Assert: map contains a formal parameter mapping for P.
// b. Return Get(map, P).
return map.get(property_key);
// b. Return ! Get(map, P).
return MUST(map.get(property_key));
}
// 10.4.4.4 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-set-p-v-receiver
@ -68,11 +69,10 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_set(PropertyKey const& propert
// 3. If isMapped is true, then
if (is_mapped) {
// a. Let setStatus be Set(map, P, V, false).
auto set_status = MUST(m_parameter_map->set(property_key, value, Object::ShouldThrowExceptions::No));
// a. Assert: The following Set will succeed, since formal parameters mapped by arguments objects are always writable.
// b. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
VERIFY(set_status);
// b. Perform ! Set(map, P, V, false).
MUST(m_parameter_map->set(property_key, value, Object::ShouldThrowExceptions::No));
}
// 4. Return ? OrdinarySet(args, P, V, Receiver).
@ -93,7 +93,7 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_delete(PropertyKey const& prop
// 4. If result is true and isMapped is true, then
if (result && is_mapped) {
// a. Call map.[[Delete]](P).
// a. Perform ! map.[[Delete]](P).
MUST(map.internal_delete(property_key));
}
@ -117,8 +117,8 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_ow
// 5. If isMapped is true, then
if (is_mapped) {
// a. Set desc.[[Value]] to Get(map, P).
desc->value = TRY(m_parameter_map->get(property_key));
// a. Set desc.[[Value]] to ! Get(map, P).
desc->value = MUST(m_parameter_map->get(property_key));
}
// 6. Return desc.
@ -131,7 +131,7 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
// 1. Let map be args.[[ParameterMap]].
auto& map = parameter_map();
// 2. Let isMapped be HasOwnProperty(map, P).
// 2. Let isMapped be ! HasOwnProperty(map, P).
bool is_mapped = MUST(map.has_own_property(property_key));
// 3. Let newArgDesc be Desc.
@ -143,13 +143,13 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
if (!descriptor.value.has_value() && descriptor.writable.has_value() && descriptor.writable == false) {
// i. Set newArgDesc to a copy of Desc.
new_arg_desc = descriptor;
// ii. Set newArgDesc.[[Value]] to Get(map, P).
new_arg_desc.value = TRY(map.get(property_key));
// ii. Set newArgDesc.[[Value]] to ! Get(map, P).
new_arg_desc.value = MUST(map.get(property_key));
}
}
// 5. Let allowed be ? OrdinaryDefineOwnProperty(args, P, newArgDesc).
bool allowed = TRY(Object::internal_define_own_property(property_key, new_arg_desc));
// 5. Let allowed be ! OrdinaryDefineOwnProperty(args, P, newArgDesc).
bool allowed = MUST(Object::internal_define_own_property(property_key, new_arg_desc));
// 6. If allowed is false, return false.
if (!allowed)
@ -159,20 +159,19 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
if (is_mapped) {
// a. If IsAccessorDescriptor(Desc) is true, then
if (descriptor.is_accessor_descriptor()) {
// i. Call map.[[Delete]](P).
// i. Perform ! map.[[Delete]](P).
MUST(map.internal_delete(property_key));
} else {
// i. If Desc has a [[Value]] field, then
if (descriptor.value.has_value()) {
// 1. Let setStatus be Set(map, P, Desc.[[Value]], false).
bool set_status = MUST(map.set(property_key, descriptor.value.value(), Object::ShouldThrowExceptions::No));
// 1. Assert: The following Set will succeed, since formal parameters mapped by arguments objects are always writable.
// 2. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
VERIFY(set_status);
// 2. Perform ! Set(map, P, Desc.[[Value]], false).
MUST(map.set(property_key, descriptor.value.value(), Object::ShouldThrowExceptions::No));
}
// ii. If Desc has a [[Writable]] field and Desc.[[Writable]] is false, then
if (descriptor.writable == false) {
// 1. Call map.[[Delete]](P).
// 1. Perform ! map.[[Delete]](P).
MUST(map.internal_delete(property_key));
}
}

View file

@ -57,7 +57,7 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
auto& vm = this->vm();
// 1. If Desc does not have a [[Value]] field, then
// a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
// a. Return ! OrdinaryDefineOwnProperty(A, "length", Desc).
// 2. Let newLenDesc be a copy of Desc.
// NOTE: Handled by step 16
@ -74,11 +74,11 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
// 6. Set newLenDesc.[[Value]] to newLen.
// 7. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
// 8. Assert: ! IsDataDescriptor(oldLenDesc) is true.
// 8. Assert: IsDataDescriptor(oldLenDesc) is true.
// 9. Assert: oldLenDesc.[[Configurable]] is false.
// 10. Let oldLen be oldLenDesc.[[Value]].
// 11. If newLen ≥ oldLen, then
// a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
// a. Return ! OrdinaryDefineOwnProperty(A, "length", newLenDesc).
// 12. If oldLenDesc.[[Writable]] is false, return false.
// NOTE: Handled by step 16
@ -100,10 +100,10 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
// a. If Desc has a [[Configurable]] field and Desc.[[Configurable]] is true, return false.
if (property_descriptor.configurable.has_value() && *property_descriptor.configurable)
return false;
// b. If Desc has an [[Enumerable]] field and ! SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
// b. If Desc has an [[Enumerable]] field and SameValue(Desc.[[Enumerable]], current.[[Enumerable]]) is false, return false.
if (property_descriptor.enumerable.has_value() && *property_descriptor.enumerable)
return false;
// c. If ! IsGenericDescriptor(Desc) is false and ! SameValue(IsAccessorDescriptor(Desc), IsAccessorDescriptor(current)) is false, return false.
// c. If IsGenericDescriptor(Desc) is false and SameValue(IsAccessorDescriptor(Desc), IsAccessorDescriptor(current)) is false, return false.
if (!property_descriptor.is_generic_descriptor() && property_descriptor.is_accessor_descriptor())
return false;
// NOTE: Step d. doesn't apply here.
@ -168,7 +168,7 @@ ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& p
// 2. Else if P is an array index, then
if (property_key.is_number()) {
// a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
// b. Assert: ! IsDataDescriptor(oldLenDesc) is true.
// b. Assert: IsDataDescriptor(oldLenDesc) is true.
// c. Assert: oldLenDesc.[[Configurable]] is false.
// d. Let oldLen be oldLenDesc.[[Value]].
// e. Assert: oldLen is a non-negative integral Number.
@ -187,14 +187,14 @@ ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& p
// j. If index ≥ oldLen, then
// i. Set oldLenDesc.[[Value]] to index + 1𝔽.
// ii. Set succeeded to OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
// ii. Set succeeded to ! OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
// iii. Assert: succeeded is true.
// k. Return true.
return true;
}
// 3. Return OrdinaryDefineOwnProperty(A, P, Desc).
// 3. Return ? OrdinaryDefineOwnProperty(A, P, Desc).
return Object::internal_define_own_property(property_key, property_descriptor);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
@ -98,7 +98,7 @@ ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(GlobalObject& global_objec
}
// 25.1.2.3 DetachArrayBuffer ( arrayBuffer [ , key ] ), https://tc39.es/ecma262/#sec-detacharraybuffer
ThrowCompletionOr<Value> detach_array_buffer(GlobalObject& global_object, ArrayBuffer& array_buffer, Optional<Value> key)
ThrowCompletionOr<void> detach_array_buffer(GlobalObject& global_object, ArrayBuffer& array_buffer, Optional<Value> key)
{
auto& vm = global_object.vm();
@ -118,7 +118,7 @@ ThrowCompletionOr<Value> detach_array_buffer(GlobalObject& global_object, ArrayB
array_buffer.detach_buffer();
// 6. Return unused.
return js_null();
return {};
}
// 25.1.2.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ), https://tc39.es/ecma262/#sec-clonearraybuffer

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -57,7 +57,7 @@ public:
template<typename type>
Value get_value(size_t byte_index, bool is_typed_array, Order, bool is_little_endian = true);
template<typename type>
Value set_value(size_t byte_index, Value value, bool is_typed_array, Order, bool is_little_endian = true);
void set_value(size_t byte_index, Value value, bool is_typed_array, Order, bool is_little_endian = true);
template<typename T>
Value get_modify_set_value(size_t byte_index, Value value, ReadWriteModifyFunction operation, bool is_little_endian = true);
@ -81,7 +81,7 @@ private:
};
ThrowCompletionOr<ArrayBuffer*> allocate_array_buffer(GlobalObject&, FunctionObject& constructor, size_t byte_length, Optional<size_t> max_byte_length = {});
ThrowCompletionOr<Value> detach_array_buffer(GlobalObject&, ArrayBuffer& array_buffer, Optional<Value> key = {});
ThrowCompletionOr<void> detach_array_buffer(GlobalObject&, ArrayBuffer& array_buffer, Optional<Value> key = {});
ThrowCompletionOr<ArrayBuffer*> clone_array_buffer(GlobalObject&, ArrayBuffer& source_buffer, size_t source_byte_offset, size_t source_length);
// 25.1.2.9 RawBytesToNumeric ( type, rawBytes, isLittleEndian ), https://tc39.es/ecma262/#sec-rawbytestonumeric
@ -201,14 +201,13 @@ static ByteBuffer numeric_to_raw_bytes(GlobalObject& global_object, Value value,
// 25.1.2.12 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-setvalueinbuffer
template<typename T>
Value ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian)
void ArrayBuffer::set_value(size_t byte_index, Value value, [[maybe_unused]] bool is_typed_array, Order, bool is_little_endian)
{
auto raw_bytes = numeric_to_raw_bytes<T>(global_object(), value, is_little_endian);
// FIXME: Check for shared buffer
raw_bytes.span().copy_to(buffer_impl().span().slice(byte_index));
return js_undefined();
}
// 25.1.2.13 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op [ , isLittleEndian ] ), https://tc39.es/ecma262/#sec-getmodifysetvalueinbuffer

View file

@ -179,7 +179,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
// i. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(k));
// ii. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
// ii. Let selected be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto selected = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
// iii. If selected is true, then
@ -1128,7 +1128,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find)
// b. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
// c. Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
// d. If testResult is true, return kValue.
@ -1167,7 +1167,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
// b. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
// c. Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
// d. If testResult is true, return 𝔽(k).
@ -1206,7 +1206,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last)
// b. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
// c. Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
// d. If testResult is true, return kValue.
@ -1245,7 +1245,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last_index)
// b. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
// c. Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
// d. If testResult is true, return 𝔽(k).
@ -1289,7 +1289,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
// i. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
// ii. Let testResult be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
// iii. If testResult is true, return true.
@ -1334,7 +1334,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
// i. Let kValue be ? Get(O, Pk).
auto k_value = TRY(object->get(property_key));
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
// ii. Let testResult be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto test_result = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
// iii. If testResult is false, return false.
@ -1567,7 +1567,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::flat_map)
// 2. Let sourceLen be ? LengthOfArrayLike(O).
auto source_length = TRY(length_of_array_like(global_object, *object));
// 3. If ! IsCallable(mapperFunction) is false, throw a TypeError exception.
// 3. If IsCallable(mapperFunction) is false, throw a TypeError exception.
if (!mapper_function.is_function())
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, mapper_function.to_string_without_side_effects());
@ -1672,7 +1672,7 @@ template<typename GroupsType, typename KeyType>
static void add_value_to_keyed_group(GlobalObject& global_object, GroupsType& groups, KeyType key, Value value)
{
// 1. For each Record { [[Key]], [[Elements]] } g of groups, do
// a. If ! SameValue(g.[[Key]], key) is true, then
// a. If SameValue(g.[[Key]], key) is true, then
// NOTE: This is performed in KeyedGroupTraits::equals for groupByToMap and Traits<JS::PropertyKey>::equals for groupBy.
auto existing_elements_iterator = groups.find(key);
if (existing_elements_iterator != groups.end()) {
@ -1682,7 +1682,7 @@ static void add_value_to_keyed_group(GlobalObject& global_object, GroupsType& gr
// ii. Append value as the last element of g.[[Elements]].
existing_elements_iterator->value.append(value);
// iii. Return.
// iii. Return unused.
return;
}
@ -1727,18 +1727,18 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::group_by)
auto property_key_value = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(index), this_object));
auto property_key = TRY(property_key_value.to_property_key(global_object));
// d. Perform ! AddValueToKeyedGroup(groups, propertyKey, kValue).
// d. Perform AddValueToKeyedGroup(groups, propertyKey, kValue).
add_value_to_keyed_group(global_object, groups, property_key, k_value);
// e. Set k to k + 1.
}
// 7. Let obj be ! OrdinaryObjectCreate(null).
// 7. Let obj be OrdinaryObjectCreate(null).
auto* object = Object::create(global_object, nullptr);
// 8. For each Record { [[Key]], [[Elements]] } g of groups, do
for (auto& group : groups) {
// a. Let elements be ! CreateArrayFromList(g.[[Elements]]).
// a. Let elements be CreateArrayFromList(g.[[Elements]]).
auto* elements = Array::create_from(global_object, group.value);
// b. Perform ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements).
@ -1797,7 +1797,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::group_by_to_map)
if (key.is_negative_zero())
key = Value(0);
// e. Perform ! AddValueToKeyedGroup(groups, key, kValue).
// e. Perform AddValueToKeyedGroup(groups, key, kValue).
add_value_to_keyed_group(global_object, groups, make_handle(key), k_value);
// f. Set k to k + 1.
@ -1808,7 +1808,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::group_by_to_map)
// 8. For each Record { [[Key]], [[Elements]] } g of groups, do
for (auto& group : groups) {
// a. Let elements be ! CreateArrayFromList(g.[[Elements]]).
// a. Let elements be CreateArrayFromList(g.[[Elements]]).
auto* elements = Array::create_from(global_object, group.value);
// b. Let entry be the Record { [[Key]]: g.[[Key]], [[Value]]: elements }.

View file

@ -31,36 +31,35 @@ void AsyncFromSyncIteratorPrototype::initialize(GlobalObject& global_object)
}
// 27.1.4.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability ), https://tc39.es/ecma262/#sec-asyncfromsynciteratorcontinuation
static ThrowCompletionOr<Object*> async_from_sync_iterator_continuation(GlobalObject& global_object, Object& result, PromiseCapability& promise_capability)
static Object* async_from_sync_iterator_continuation(GlobalObject& global_object, Object& result, PromiseCapability& promise_capability)
{
// 1. Let done be IteratorComplete(result).
// 2. IfAbruptRejectPromise(done, promiseCapability).
auto done = TRY_OR_REJECT(global_object, promise_capability, iterator_complete(global_object, result));
// 1. NOTE: Because promiseCapability is derived from the intrinsic %Promise%, the calls to promiseCapability.[[Reject]] entailed by the use IfAbruptRejectPromise below are guaranteed not to throw.
// 2. Let done be Completion(IteratorComplete(result)).
// 3. IfAbruptRejectPromise(done, promiseCapability).
auto done = TRY_OR_MUST_REJECT(global_object, promise_capability, iterator_complete(global_object, result));
// 3. Let value be IteratorValue(result).
// 4. IfAbruptRejectPromise(value, promiseCapability).
auto value = TRY_OR_REJECT(global_object, promise_capability, iterator_value(global_object, result));
// 4. Let value be Completion(IteratorValue(result)).
// 5. IfAbruptRejectPromise(value, promiseCapability).
auto value = TRY_OR_MUST_REJECT(global_object, promise_capability, iterator_value(global_object, result));
// 5. Let valueWrapper be PromiseResolve(%Promise%, value).
// 6. IfAbruptRejectPromise(valueWrapper, promiseCapability).
auto value_wrapper = TRY_OR_REJECT(global_object, promise_capability, promise_resolve(global_object, *global_object.promise_constructor(), value));
// 6. Let valueWrapper be PromiseResolve(%Promise%, value).
// 7. IfAbruptRejectPromise(valueWrapper, promiseCapability).
auto value_wrapper = TRY_OR_MUST_REJECT(global_object, promise_capability, promise_resolve(global_object, *global_object.promise_constructor(), value));
// 7. Let unwrap be a new Abstract Closure with parameters (value) that captures done and performs the following steps when called:
// 8. Let unwrap be a new Abstract Closure with parameters (value) that captures done and performs the following steps when called:
auto unwrap = [done](VM& vm, GlobalObject& global_object) -> ThrowCompletionOr<Value> {
// a. Return ! CreateIterResultObject(value, done).
// a. Return CreateIterResultObject(value, done).
return create_iterator_result_object(global_object, vm.argument(0), done);
};
// 8. Let onFulfilled be ! CreateBuiltinFunction(unwrap, 1, "", « »).
// 9. Let onFulfilled be CreateBuiltinFunction(unwrap, 1, "", « »).
// 10. NOTE: onFulfilled is used when processing the "value" property of an IteratorResult object in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" IteratorResult object.
auto* on_fulfilled = NativeFunction::create(global_object, move(unwrap), 1, "");
// 9. NOTE: onFulfilled is used when processing the "value" property of an IteratorResult object in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" IteratorResult object.
VERIFY(is<Promise>(value_wrapper));
auto* value_wrapper_promise = static_cast<Promise*>(value_wrapper);
// 10. Perform ! PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
value_wrapper_promise->perform_then(move(on_fulfilled), js_undefined(), promise_capability);
// 11. Perform PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
verify_cast<Promise>(value_wrapper)->perform_then(move(on_fulfilled), js_undefined(), promise_capability);
// 11. Return promiseCapability.[[Promise]].
// 12. Return promiseCapability.[[Promise]].
return promise_capability.promise;
}
@ -78,16 +77,16 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::next)
auto& sync_iterator_record = this_object->sync_iterator_record();
// 5. If value is present, then
// a. Let result be IteratorNext(syncIteratorRecord, value).
// a. Let result be Completion(IteratorNext(syncIteratorRecord, value)).
// 6. Else,
// a. Let result be IteratorNext(syncIteratorRecord).
// a. Let result be Completion(IteratorNext(syncIteratorRecord)).
// 7. IfAbruptRejectPromise(result, promiseCapability).
auto* result = TRY_OR_REJECT(global_object, promise_capability,
(vm.argument_count() > 0 ? iterator_next(global_object, sync_iterator_record, vm.argument(0))
: iterator_next(global_object, sync_iterator_record)));
// 8. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
return MUST(async_from_sync_iterator_continuation(global_object, *result, promise_capability));
// 8. Return AsyncFromSyncIteratorContinuation(result, promiseCapability).
return async_from_sync_iterator_continuation(global_object, *result, promise_capability);
}
// 27.1.4.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] ), https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.return
@ -103,13 +102,13 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
// 4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
auto* sync_iterator = this_object->sync_iterator_record().iterator;
// 5. Let return be GetMethod(syncIterator, "return").
// 5. Let return be Completion(GetMethod(syncIterator, "return")).
// 6. IfAbruptRejectPromise(return, promiseCapability).
auto* return_method = TRY_OR_REJECT(global_object, promise_capability, Value(sync_iterator).get_method(global_object, vm.names.return_));
// 7. If return is undefined, then
if (return_method == nullptr) {
// a. Let iterResult be ! CreateIterResultObject(value, true).
// a. Let iterResult be CreateIterResultObject(value, true).
auto* iter_result = create_iterator_result_object(global_object, vm.argument(0), true);
// b. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
@ -120,9 +119,9 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
}
// 8. If value is present, then
// a. Let result be Call(return, syncIterator, « value »).
// a. Let result be Completion(Call(return, syncIterator, « value »)).
// 9. Else,
// a. Let result be Call(return, syncIterator).
// a. Let result be Completion(Call(return, syncIterator)).
// 10. IfAbruptRejectPromise(result, promiseCapability).
auto result = TRY_OR_REJECT(global_object, promise_capability,
(vm.argument_count() > 0 ? call(global_object, return_method, sync_iterator, vm.argument(0))
@ -137,8 +136,8 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::return_)
return promise_capability.promise;
}
// 12. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
return MUST(async_from_sync_iterator_continuation(global_object, result.as_object(), promise_capability));
// 12. Return AsyncFromSyncIteratorContinuation(result, promiseCapability).
return async_from_sync_iterator_continuation(global_object, result.as_object(), promise_capability);
}
// 27.1.4.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] ), https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.throw
@ -154,7 +153,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
// 4. Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
auto* sync_iterator = this_object->sync_iterator_record().iterator;
// 5. Let throw be GetMethod(syncIterator, "throw").
// 5. Let throw be Completion(GetMethod(syncIterator, "throw")).
// 6. IfAbruptRejectPromise(throw, promiseCapability).
auto* throw_method = TRY_OR_REJECT(global_object, promise_capability, Value(sync_iterator).get_method(global_object, vm.names.throw_));
@ -166,9 +165,9 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
return promise_capability.promise;
}
// 8. If value is present, then
// a. Let result be Call(throw, syncIterator, « value »).
// a. Let result be Completion(Call(throw, syncIterator, « value »)).
// 9. Else,
// a. Let result be Call(throw, syncIterator).
// a. Let result be Completion(Call(throw, syncIterator)).
// 10. IfAbruptRejectPromise(result, promiseCapability).
auto result = TRY_OR_REJECT(global_object, promise_capability,
(vm.argument_count() > 0 ? call(global_object, throw_method, sync_iterator, vm.argument(0))
@ -184,16 +183,16 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncFromSyncIteratorPrototype::throw_)
return promise_capability.promise;
}
// 12. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
return MUST(async_from_sync_iterator_continuation(global_object, result.as_object(), promise_capability));
// 12. Return AsyncFromSyncIteratorContinuation(result, promiseCapability).
return async_from_sync_iterator_continuation(global_object, result.as_object(), promise_capability);
}
// 27.1.4.1 CreateAsyncFromSyncIterator ( syncIteratorRecord ), https://tc39.es/ecma262/#sec-createasyncfromsynciterator
ThrowCompletionOr<Iterator> create_async_from_sync_iterator(GlobalObject& global_object, Iterator sync_iterator_record)
Iterator create_async_from_sync_iterator(GlobalObject& global_object, Iterator sync_iterator_record)
{
auto& vm = global_object.vm();
// 1. Let asyncIterator be ! OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »).
// 1. Let asyncIterator be OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »).
// 2. Set asyncIterator.[[SyncIteratorRecord]] to syncIteratorRecord.
auto* async_iterator = AsyncFromSyncIterator::create(global_object, sync_iterator_record);

View file

@ -29,6 +29,6 @@ private:
JS_DECLARE_NATIVE_FUNCTION(throw_);
};
ThrowCompletionOr<Iterator> create_async_from_sync_iterator(GlobalObject&, Iterator sync_iterator);
Iterator create_async_from_sync_iterator(GlobalObject&, Iterator sync_iterator);
}

View file

@ -38,7 +38,7 @@ static ThrowCompletionOr<ArrayBuffer*> validate_integer_typed_array(GlobalObject
// 5. Else,
else {
// a. Let type be TypedArrayElementType(typedArray).
// b. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false, throw a TypeError exception.
// b. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
if (!typed_array.is_unclamped_integer_element_type() && !typed_array.is_bigint_element_type())
return vm.throw_completion<TypeError>(global_object, ErrorType::TypedArrayTypeIsNot, type_name, "an unclamped integer or BigInt"sv);
}

View file

@ -18,7 +18,7 @@ ThrowCompletionOr<BoundFunction*> BoundFunction::create(GlobalObject& global_obj
auto* prototype = TRY(target_function.internal_get_prototype_of());
// 2. Let internalSlotsList be the list-concatenation of « [[Prototype]], [[Extensible]] » and the internal slots listed in Table 34.
// 3. Let obj be ! MakeBasicObject(internalSlotsList).
// 3. Let obj be MakeBasicObject(internalSlotsList).
// 4. Set obj.[[Prototype]] to proto.
// 5. Set obj.[[Call]] as described in 10.4.1.1.
// 6. If IsConstructor(targetFunction) is true, then

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -62,7 +62,7 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
return js_undefined();
};
// 4. Let onFulfilled be ! CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
// 4. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
auto* on_fulfilled = NativeFunction::create(global_object, move(fulfilled_closure), 1, "");
// 5. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures asyncContext and performs the following steps when called:
@ -86,10 +86,10 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
return js_undefined();
};
// 6. Let onRejected be ! CreateBuiltinFunction(rejectedClosure, 1, "", « »).
// 6. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
auto* on_rejected = NativeFunction::create(global_object, move(rejected_closure), 1, "");
// 7. Perform ! PerformPromiseThen(promise, onFulfilled, onRejected).
// 7. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
auto* promise = verify_cast<Promise>(promise_object);
promise->perform_then(on_fulfilled, on_rejected, {});
@ -103,8 +103,8 @@ ThrowCompletionOr<Value> await(GlobalObject& global_object, Value value)
// 8. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
// NOTE: Since we don't push any EC, this step is not performed.
// 9. Set the code evaluation state of asyncContext such that when evaluation is resumed with a Completion completion, the following steps of the algorithm that invoked Await will be performed, with completion available.
// 10. Return.
// 9. Set the code evaluation state of asyncContext such that when evaluation is resumed with a Completion Record completion, the following steps of the algorithm that invoked Await will be performed, with completion available.
// 10. Return NormalCompletion(unused).
// 11. NOTE: This returns to the evaluation of the operation that had most previously resumed evaluation of asyncContext.
vm.run_queued_promise_jobs();

View file

@ -44,6 +44,11 @@ public:
{
}
ALWAYS_INLINE Completion(Optional<Value> value)
: Completion(Type::Normal, move(value), {})
{
}
ALWAYS_INLINE Completion()
: Completion(js_undefined())
{
@ -80,7 +85,7 @@ public:
if (m_type == Type::Return || m_type == Type::Throw)
VERIFY(m_value.has_value());
// 2. If completionRecord.[[Value]] is not empty, return Completion(completionRecord).
// 2. If completionRecord.[[Value]] is not empty, return ? completionRecord.
if (m_value.has_value())
return *this;

View file

@ -114,7 +114,9 @@ static ThrowCompletionOr<Value> set_view_value(GlobalObject& global_object, Valu
if (buffer_index.has_overflow() || end_index.has_overflow() || end_index.value() > view_size)
return vm.throw_completion<RangeError>(global_object, ErrorType::DataViewOutOfRangeByteOffset, get_index, view_size);
return buffer->set_value<T>(buffer_index.value(), number_value, false, ArrayBuffer::Order::Unordered, little_endian);
buffer->set_value<T>(buffer_index.value(), number_value, false, ArrayBuffer::Order::Unordered, little_endian);
return js_undefined();
}
// 25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] ), https://tc39.es/ecma262/#sec-dataview.prototype.getbigint64

View file

@ -58,6 +58,9 @@ 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(GlobalObject&, FlyString 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.
// 2. Create a mutable binding in envRec for N and record that it is uninitialized. If D is true, record that the newly created binding may be deleted by a subsequent DeleteBinding call.
m_bindings.append(Binding {
.name = name,
@ -68,16 +71,16 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(GlobalObj
.initialized = false,
});
// 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
// 3. Return NormalCompletion(empty).
// 3. Return unused.
return {};
}
// 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(GlobalObject&, FlyString 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.
// 2. Create an immutable binding in envRec for N and record that it is uninitialized. If S is true, record that the newly created binding is a strict binding.
m_bindings.append(Binding {
.name = name,
@ -88,10 +91,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(GlobalO
.initialized = false,
});
// 1. Assert: envRec does not already have a binding for N.
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
// 3. Return NormalCompletion(empty).
// 3. Return unused.
return {};
}
@ -117,7 +117,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding_direct(Global
// 3. Record that the binding for N in envRec has been initialized.
binding.initialized = true;
// 4. Return NormalCompletion(empty).
// 4. Return unused.
return {};
}
@ -131,20 +131,21 @@ ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(GlobalObject
if (strict)
return vm().throw_completion<ReferenceError>(global_object, ErrorType::UnknownIdentifier, name);
// FIXME: Should be `! envRec.CreateMutableBinding(N, true)` (see https://github.com/tc39/ecma262/pull/2764)
// b. Perform envRec.CreateMutableBinding(N, true).
MUST(create_mutable_binding(global_object, name, true));
// c. Perform envRec.InitializeBinding(N, V).
// c. Perform ! envRec.InitializeBinding(N, V).
MUST(initialize_binding(global_object, name, value));
// d. Return NormalCompletion(empty).
// d. Return unused.
return {};
}
// 2-5. (extracted into a non-standard function below)
TRY(set_mutable_binding_direct(global_object, *index, value, strict));
// 6. Return NormalCompletion(empty).
// 6. Return unused.
return {};
}

View file

@ -173,13 +173,13 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
// 5. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
ordinary_call_bind_this(callee_context, this_argument);
// 6. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
// 6. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
auto result = ordinary_call_evaluate_body();
// 7. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
vm.pop_execution_context();
// 8. If result.[[Type]] is return, return NormalCompletion(result.[[Value]]).
// 8. If result.[[Type]] is return, return result.[[Value]].
if (result.type() == Completion::Type::Return)
return result.value();
@ -189,7 +189,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
return result;
}
// 10. Return NormalCompletion(undefined).
// 10. Return undefined.
return js_undefined();
}
@ -232,7 +232,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
// a. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
ordinary_call_bind_this(callee_context, this_argument);
// b. Let initializeResult be InitializeInstanceElements(thisArgument, F).
// b. Let initializeResult be Completion(InitializeInstanceElements(thisArgument, F)).
auto initialize_result = vm.initialize_instance_elements(*this_argument, *this);
// c. If initializeResult is an abrupt completion, then
@ -240,7 +240,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
// i. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
vm.pop_execution_context();
// ii. Return Completion(initializeResult).
// ii. Return ? initializeResult.
return initialize_result.throw_completion();
}
}
@ -248,7 +248,7 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
// 7. Let constructorEnv be the LexicalEnvironment of calleeContext.
auto* constructor_env = callee_context.lexical_environment;
// 8. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
// 8. Let result be Completion(OrdinaryCallEvaluateBody(F, argumentsList)).
auto result = ordinary_call_evaluate_body();
// 9. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
@ -265,11 +265,11 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
}
// EOF (End of FIXME)
// a. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
// a. If Type(result.[[Value]]) is Object, return result.[[Value]].
if (result.value()->is_object())
return &result.value()->as_object();
// b. If kind is base, return NormalCompletion(thisArgument).
// b. If kind is base, return thisArgument.
if (kind == ConstructorKind::Base)
return this_argument;
@ -283,8 +283,13 @@ ThrowCompletionOr<Object*> ECMAScriptFunctionObject::internal_construct(MarkedVe
return result;
}
// 12. Return ? constructorEnv.GetThisBinding().
// 12. Let thisBinding be ? constructorEnv.GetThisBinding().
auto this_binding = TRY(constructor_env->get_this_binding(global_object));
// 13. Assert: Type(thisBinding) is Object.
VERIFY(this_binding.is_object());
// 14. Return thisBinding.
return &this_binding.as_object();
}
@ -308,7 +313,7 @@ void ECMAScriptFunctionObject::make_method(Object& home_object)
// 1. Set F.[[HomeObject]] to homeObject.
m_home_object = &home_object;
// 2. Return NormalCompletion(undefined).
// 2. Return unused.
}
// 10.2.11 FunctionDeclarationInstantiation ( func, argumentsList ), https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
@ -638,7 +643,7 @@ void ECMAScriptFunctionObject::ordinary_call_bind_this(ExecutionContext& callee_
// 1. Let thisMode be F.[[ThisMode]].
auto this_mode = m_this_mode;
// If thisMode is lexical, return NormalCompletion(undefined).
// If thisMode is lexical, return unused.
if (this_mode == ThisMode::Lexical)
return;
@ -685,8 +690,10 @@ void ECMAScriptFunctionObject::ordinary_call_bind_this(ExecutionContext& callee_
// 7. Assert: localEnv is a function Environment Record.
// 8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
// 9. Return localEnv.BindThisValue(thisValue).
// 9. Perform ! localEnv.BindThisValue(thisValue).
MUST(verify_cast<FunctionEnvironment>(local_env)->bind_this_value(global_object(), this_value));
// 10. Return unused.
}
// 27.7.5.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody ), https://tc39.es/ecma262/#sec-async-functions-abstract-operations-async-function-start
@ -702,8 +709,10 @@ void ECMAScriptFunctionObject::async_function_start(PromiseCapability const& pro
// 3. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context.
// 4. Perform ! AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
// 4. Perform AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
async_block_start(vm, m_ecmascript_code, promise_capability, async_context);
// 5. Return unused.
}
// 27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext ), https://tc39.es/ecma262/#sec-asyncblockstart
@ -743,7 +752,8 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
// ii. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
MUST(call(global_object, promise_capability.reject, js_undefined(), *result.value()));
}
// g. Return.
// g. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
return js_undefined();
});
@ -758,10 +768,10 @@ void async_block_start(VM& vm, NonnullRefPtr<Statement> const& async_body, Promi
// 6. Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
VERIFY(&vm.running_execution_context() == &running_context);
// 7. Assert: result is a normal completion with a value of undefined. The possible sources of completion values are Await or, if the async function doesn't await anything, step 3.g above.
// 7. Assert: result is a normal completion with a value of unused. The possible sources of completion values are Await or, if the async function doesn't await anything, step 3.g above.
VERIFY(result.has_value() && result.value().is_undefined());
// 8. Return.
// 8. Return unused.
}
// 10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList ), https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
@ -854,18 +864,18 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
// 1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
auto promise_capability = MUST(new_promise_capability(global_object(), global_object().promise_constructor()));
// 2. Let declResult be FunctionDeclarationInstantiation(functionObject, argumentsList).
// 2. Let declResult be Completion(FunctionDeclarationInstantiation(functionObject, argumentsList)).
auto declaration_result = function_declaration_instantiation(ast_interpreter);
// 3. If declResult is not an abrupt completion, then
if (!declaration_result.is_throw_completion()) {
// a. Perform ! AsyncFunctionStart(promiseCapability, FunctionBody).
async_function_start(promise_capability);
// 3. If declResult is an abrupt completion, then
if (declaration_result.is_throw_completion()) {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « declResult.[[Value]] »).
MUST(call(global_object(), promise_capability.reject, js_undefined(), *declaration_result.throw_completion().value()));
}
// 4. Else,
else {
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « declResult.[[Value]] »).
MUST(call(global_object(), promise_capability.reject, js_undefined(), *declaration_result.throw_completion().value()));
// a. Perform AsyncFunctionStart(promiseCapability, FunctionBody).
async_function_start(promise_capability);
}
// 5. Return Completion Record { [[Type]]: return, [[Value]]: promiseCapability.[[Promise]], [[Target]]: empty }.
@ -880,8 +890,7 @@ void ECMAScriptFunctionObject::set_name(FlyString const& name)
VERIFY(!name.is_null());
auto& vm = this->vm();
m_name = name;
auto success = MUST(define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name), .writable = false, .enumerable = false, .configurable = true }));
VERIFY(success);
MUST(define_property_or_throw(vm.names.name, { .value = js_string(vm, m_name), .writable = false, .enumerable = false, .configurable = true }));
}
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -44,11 +44,11 @@ ThrowCompletionOr<void> Error::install_error_cause(Value options)
// a. Let cause be ? Get(options, "cause").
auto cause = TRY(options.as_object().get(vm.names.cause));
// b. Perform ! CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
MUST(create_non_enumerable_data_property_or_throw(vm.names.cause, cause));
// b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
create_non_enumerable_data_property_or_throw(vm.names.cause, cause);
}
// 2. Return NormalCompletion(undefined).
// 2. Return unused.
return {};
}

View file

@ -51,8 +51,8 @@ ThrowCompletionOr<Object*> ErrorConstructor::construct(FunctionObject& new_targe
// a. Let msg be ? ToString(message).
auto msg = TRY(message.to_string(global_object));
// b. Perform ! CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, move(msg))));
// b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg).
error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, move(msg)));
}
// 4. Perform ? InstallErrorCause(O, options).
@ -79,7 +79,7 @@ ThrowCompletionOr<Object*> ErrorConstructor::construct(FunctionObject& new_targe
define_direct_property(vm.names.length, Value(1), Attribute::Configurable); \
} \
\
ConstructorName::~ConstructorName() { } \
ConstructorName::~ConstructorName() = default; \
\
/* 20.5.6.1.1 NativeError ( message [ , options ] ), https://tc39.es/ecma262/#sec-nativeerror */ \
ThrowCompletionOr<Value> ConstructorName::call() \
@ -105,8 +105,8 @@ ThrowCompletionOr<Object*> ErrorConstructor::construct(FunctionObject& new_targe
/* a. Let msg be ? ToString(message). */ \
auto msg = TRY(message.to_string(global_object)); \
\
/* b. Perform ! CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). */ \
MUST(error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, move(msg)))); \
/* b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "message", msg). */ \
error->create_non_enumerable_data_property_or_throw(vm.names.message, js_string(vm, move(msg))); \
} \
\
/* 4. Perform ? InstallErrorCause(O, options). */ \

View file

@ -76,7 +76,7 @@ ThrowCompletionOr<void> FinalizationRegistry::cleanup(Optional<JobCallback> call
TRY(vm.host_call_job_callback(global_object, cleanup_callback, js_undefined(), move(arguments)));
}
// 4. Return NormalCompletion(empty).
// 4. Return unused.
return {};
}

View file

@ -171,7 +171,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
auto body_string = String::formatted("\n{}\n", body_arg.has_value() ? TRY(body_arg->to_string(global_object)) : "");
// 17. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
// 18. Let sourceText be ! StringToCodePoints(sourceString).
// 18. Let sourceText be StringToCodePoints(sourceString).
auto source_text = String::formatted("{} anonymous({}\n) {{{}}}", prefix, parameters_string, body_string);
u8 parse_options = FunctionNodeParseOptions::CheckForFunctionAndName;
@ -180,7 +180,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
if (kind == FunctionKind::Generator || kind == FunctionKind::AsyncGenerator)
parse_options |= FunctionNodeParseOptions::IsGeneratorFunction;
// 19. Let parameters be ParseText(! StringToCodePoints(P), parameterSym).
// 19. Let parameters be ParseText(StringToCodePoints(P), parameterSym).
i32 function_length = 0;
auto parameters_parser = Parser { Lexer { parameters_string } };
auto parameters = parameters_parser.parse_formal_parameters(function_length, parse_options);
@ -191,7 +191,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
return vm.throw_completion<SyntaxError>(global_object, error.to_string());
}
// 21. Let body be ParseText(! StringToCodePoints(bodyString), bodySym).
// 21. Let body be ParseText(StringToCodePoints(bodyString), bodySym).
bool contains_direct_call_to_eval = false;
auto body_parser = Parser { Lexer { body_string } };
// Set up some parser state to accept things like return await, and yield in the plain function body.
@ -234,7 +234,7 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
// 30. Let privateEnv be null.
PrivateEnvironment* private_environment = nullptr;
// 31. Let F be ! OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
// 31. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv).
auto* function = ECMAScriptFunctionObject::create(global_object, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), environment, private_environment, expr->kind(), expr->is_strict_mode(), expr->might_need_arguments_object(), contains_direct_call_to_eval);
// FIXME: Remove the name argument from create() and do this instead.
@ -242,19 +242,19 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic
// 33. If kind is generator, then
if (kind == FunctionKind::Generator) {
// a. Let prototype be ! OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
// a. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%).
prototype = Object::create(global_object, global_object.generator_prototype());
// b. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
}
// 34. Else if kind is asyncGenerator, then
else if (kind == FunctionKind::AsyncGenerator) {
// FIXME: We only have %AsyncGeneratorFunction.prototype%, not %AsyncGeneratorFunction.prototype.prototype%!
// a. Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
// a. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
// prototype = Object::create(global_object, global_object.async_generator_prototype());
// b. Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
// b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
// function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable);
}
// 35. Else if kind is normal, perform MakeConstructor(F).

View file

@ -72,8 +72,10 @@ void FunctionObject::set_function_name(Variant<PropertyKey, PrivateName> const&
}
}
// 6. Return ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).
// 6. Perform ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).
MUST(define_property_or_throw(vm.names.name, PropertyDescriptor { .value = js_string(vm, move(name)), .writable = false, .enumerable = false, .configurable = true }));
// 7. Return unused.
}
// 10.2.10 SetFunctionLength ( F, length ), https://tc39.es/ecma262/#sec-setfunctionlength
@ -88,8 +90,10 @@ void FunctionObject::set_function_length(double length)
VERIFY(m_is_extensible);
VERIFY(!storage_has(vm.names.length));
// 2. Return ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).
// 2. Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).
MUST(define_property_or_throw(vm.names.length, PropertyDescriptor { .value = Value { length }, .writable = false, .enumerable = false, .configurable = true }));
// 3. Return unused.
}
}

View file

@ -144,9 +144,9 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string)
auto& function = function_value.as_function();
// 2. If Type(func) is Object and func has a [[SourceText]] internal slot and func.[[SourceText]] is a sequence of Unicode code points and ! HostHasSourceTextAvailable(func) is true, then
// 2. If Type(func) is Object and func has a [[SourceText]] internal slot and func.[[SourceText]] is a sequence of Unicode code points and HostHasSourceTextAvailable(func) is true, then
if (is<ECMAScriptFunctionObject>(function)) {
// a. Return ! CodePointsToString(func.[[SourceText]]).
// a. Return CodePointsToString(func.[[SourceText]]).
return js_string(vm, static_cast<ECMAScriptFunctionObject&>(function).source_text());
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -42,7 +42,7 @@ ThrowCompletionOr<Value> GlobalEnvironment::get_this_binding(GlobalObject&) cons
ThrowCompletionOr<bool> GlobalEnvironment::has_binding(FlyString const& name, Optional<size_t>*) const
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, return true.
// 2. If ! DclRec.HasBinding(N) is true, return true.
if (MUST(m_declarative_record->has_binding(name)))
return true;
@ -55,7 +55,7 @@ ThrowCompletionOr<bool> GlobalEnvironment::has_binding(FlyString const& name, Op
ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(GlobalObject& global_object, FlyString const& name, bool can_be_deleted)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, throw a TypeError exception.
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
if (MUST(m_declarative_record->has_binding(name)))
return vm().throw_completion<TypeError>(global_object, ErrorType::GlobalEnvironmentAlreadyHasBinding, name);
@ -67,7 +67,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_mutable_binding(GlobalObject&
ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(GlobalObject& global_object, FlyString const& name, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, throw a TypeError exception.
// 2. If ! DclRec.HasBinding(N) is true, throw a TypeError exception.
if (MUST(m_declarative_record->has_binding(name)))
return vm().throw_completion<TypeError>(global_object, ErrorType::GlobalEnvironmentAlreadyHasBinding, name);
@ -79,10 +79,10 @@ ThrowCompletionOr<void> GlobalEnvironment::create_immutable_binding(GlobalObject
ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, then
// 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) {
// a. Return DclRec.InitializeBinding(N, V).
return m_declarative_record->initialize_binding(global_object, name, value);
// a. Return ! DclRec.InitializeBinding(N, V).
return MUST(m_declarative_record->initialize_binding(global_object, name, value));
}
// 3. Assert: If the binding exists, it must be in the object Environment Record.
@ -95,9 +95,11 @@ ThrowCompletionOr<void> GlobalEnvironment::initialize_binding(GlobalObject& glob
ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, then
// 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) {
// a. Return DclRec.SetMutableBinding(N, V, S).
// a. Return ! DclRec.SetMutableBinding(N, V, S).
// FIXME: Using MUST here breaks 22 tests in test262 (spec issue).
// Example: `function f() { x = 1; } f(); let x;`
return m_declarative_record->set_mutable_binding(global_object, name, value, strict);
}
@ -110,8 +112,9 @@ ThrowCompletionOr<void> GlobalEnvironment::set_mutable_binding(GlobalObject& glo
ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, then
// 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) {
// FIXME: Should be `! DclRec.GetBindingValue(N, S)` (see https://github.com/tc39/ecma262/pull/2764)
// a. Return DclRec.GetBindingValue(N, S).
return m_declarative_record->get_binding_value(global_object, name, strict);
}
@ -125,10 +128,10 @@ ThrowCompletionOr<Value> GlobalEnvironment::get_binding_value(GlobalObject& glob
ThrowCompletionOr<bool> GlobalEnvironment::delete_binding(GlobalObject& global_object, FlyString const& name)
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. If DclRec.HasBinding(N) is true, then
// 2. If ! DclRec.HasBinding(N) is true, then
if (MUST(m_declarative_record->has_binding(name))) {
// a. Return DclRec.DeleteBinding(N).
return m_declarative_record->delete_binding(global_object, name);
// a. Return ! DclRec.DeleteBinding(N).
return MUST(m_declarative_record->delete_binding(global_object, name));
}
// 3. Let ObjRec be envRec.[[ObjectRecord]].
@ -170,7 +173,7 @@ bool GlobalEnvironment::has_var_declaration(FlyString const& name) const
bool GlobalEnvironment::has_lexical_declaration(FlyString const& name) const
{
// 1. Let DclRec be envRec.[[DeclarativeRecord]].
// 2. Return DclRec.HasBinding(N).
// 2. Return ! DclRec.HasBinding(N).
return MUST(m_declarative_record->has_binding(name));
}
@ -269,7 +272,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_global_var_binding(FlyString c
m_var_names.append(name);
}
// 8. Return NormalCompletion(empty).
// 8. Return unused.
return {};
}
@ -309,7 +312,7 @@ ThrowCompletionOr<void> GlobalEnvironment::create_global_function_binding(FlyStr
m_var_names.append(name);
}
// 10. Return NormalCompletion(empty).
// 10. Return unused.
return {};
}

View file

@ -521,7 +521,7 @@ static ThrowCompletionOr<String> encode(GlobalObject& global_object, String cons
}
// d. Else,
else {
// i. Let cp be ! CodePointAt(string, k).
// i. Let cp be CodePointAt(string, k).
auto code_point = code_point_at(utf16_string.view(), k);
// ii. If cp.[[IsUnpairedSurrogate]] is true, throw a URIError exception.
if (code_point.is_unpaired_surrogate)

View file

@ -154,10 +154,10 @@ bool is_well_formed_unit_identifier(StringView unit_identifier)
return true;
}
// 2. Let i be ! StringIndexOf(unitIdentifier, "-per-", 0).
// 2. Let i be StringIndexOf(unitIdentifier, "-per-", 0).
auto indices = unit_identifier.find_all("-per-"sv);
// 3. If i is -1 or ! StringIndexOf(unitIdentifier, "-per-", i + 1) is not -1, then
// 3. If i is -1 or StringIndexOf(unitIdentifier, "-per-", i + 1) is not -1, then
if (indices.size() != 1) {
// a. Return false.
return false;
@ -199,7 +199,7 @@ ThrowCompletionOr<Vector<String>> canonicalize_locale_list(GlobalObject& global_
Object* object = nullptr;
// 3. If Type(locales) is String or Type(locales) is Object and locales has an [[InitializedLocale]] internal slot, then
if (locales.is_string() || (locales.is_object() && is<Locale>(locales.as_object()))) {
// a. Let O be ! CreateArrayFromList(« locales »).
// a. Let O be CreateArrayFromList(« locales »).
object = Array::create_from(global_object, { locales });
}
// 4. Else,
@ -586,7 +586,7 @@ ThrowCompletionOr<Array*> supported_locales(GlobalObject& global_object, Vector<
supported_locales = lookup_supported_locales(requested_locales);
}
// 5. Return ! CreateArrayFromList(supportedLocales).
// 5. Return CreateArrayFromList(supportedLocales).
return Array::create_from<String>(global_object, supported_locales, [&vm](auto& locale) { return js_string(vm, locale); });
}
@ -595,7 +595,7 @@ ThrowCompletionOr<Object*> coerce_options_to_object(GlobalObject& global_object,
{
// 1. If options is undefined, then
if (options.is_undefined()) {
// a. Return ! OrdinaryObjectCreate(null).
// a. Return OrdinaryObjectCreate(null).
return Object::create(global_object, nullptr);
}
@ -626,7 +626,7 @@ ThrowCompletionOr<Value> get_option(GlobalObject& global_object, Object const& o
// 5. If type is "boolean", then
if (type == Value::Type::Boolean) {
// a. Set value to ! ToBoolean(value).
// a. Set value to ToBoolean(value).
value = Value(value.to_boolean());
}
// 6. If type is "string", then
@ -685,7 +685,7 @@ Vector<PatternPartition> partition_pattern(StringView pattern)
// 1. Let result be a new empty List.
Vector<PatternPartition> result;
// 2. Let beginIndex be ! StringIndexOf(pattern, "{", 0).
// 2. Let beginIndex be StringIndexOf(pattern, "{", 0).
auto begin_index = pattern.find('{', 0);
// 3. Let endIndex be 0.
@ -697,7 +697,7 @@ Vector<PatternPartition> partition_pattern(StringView pattern)
// 5. Let length be the number of code units in pattern.
// 6. Repeat, while beginIndex is an integer index into pattern,
while (begin_index.has_value()) {
// a. Set endIndex to ! StringIndexOf(pattern, "}", beginIndex).
// a. Set endIndex to StringIndexOf(pattern, "}", beginIndex).
end_index = pattern.find('}', *begin_index).value();
// b. Assert: endIndex is greater than beginIndex.
@ -721,7 +721,7 @@ Vector<PatternPartition> partition_pattern(StringView pattern)
// f. Set nextIndex to endIndex + 1.
next_index = end_index + 1;
// g. Set beginIndex to ! StringIndexOf(pattern, "{", nextIndex).
// g. Set beginIndex to StringIndexOf(pattern, "{", nextIndex).
begin_index = pattern.find('{', next_index);
}

View file

@ -89,7 +89,7 @@ static ThrowCompletionOr<Collator*> initialize_collator(GlobalObject& global_obj
// 24. If relevantExtensionKeys contains "kn", then
if (relevant_extension_keys.span().contains_slow("kn"sv) && result.kn.has_value()) {
// a. Set collator.[[Numeric]] to ! SameValue(r.[[kn]], "true").
// a. Set collator.[[Numeric]] to SameValue(r.[[kn]], "true").
collator.set_numeric(same_value(js_string(vm, result.kn.release_value()), js_string(vm, "true"sv)));
}

View file

@ -59,7 +59,7 @@ JS_DEFINE_NATIVE_FUNCTION(CollatorPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(collator, [[InitializedCollator]]).
auto* collator = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 3, except the header row, in table order, do

View file

@ -72,7 +72,7 @@ ThrowCompletionOr<Object*> to_date_time_options(GlobalObject& global_object, Val
if (!options_value.is_undefined())
options = TRY(options_value.to_object(global_object));
// 2. Let options be ! OrdinaryObjectCreate(options).
// 2. Let options be OrdinaryObjectCreate(options).
options = Object::create(global_object, options);
// 3. Let needDefaults be true.
@ -524,7 +524,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObjec
return static_cast<NumberFormat*>(number_format);
};
// 4. Let nfOptions be ! OrdinaryObjectCreate(null).
// 4. Let nfOptions be OrdinaryObjectCreate(null).
auto* number_format_options = Object::create(global_object, nullptr);
// 5. Perform ! CreateDataPropertyOrThrow(nfOptions, "useGrouping", false).
@ -533,7 +533,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObjec
// 6. Let nf be ? Construct(%NumberFormat%, « locale, nfOptions »).
auto* number_format = TRY(construct_number_format(number_format_options));
// 7. Let nf2Options be ! OrdinaryObjectCreate(null).
// 7. Let nf2Options be OrdinaryObjectCreate(null).
auto* number_format_options2 = Object::create(global_object, nullptr);
// 8. Perform ! CreateDataPropertyOrThrow(nf2Options, "minimumIntegerDigits", 2).
@ -553,7 +553,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(GlobalObjec
if (date_time_format.has_fractional_second_digits()) {
fractional_second_digits = date_time_format.fractional_second_digits();
// a. Let nf3Options be ! OrdinaryObjectCreate(null).
// a. Let nf3Options be OrdinaryObjectCreate(null).
auto* number_format_options3 = Object::create(global_object, nullptr);
// b. Perform ! CreateDataPropertyOrThrow(nf3Options, "minimumIntegerDigits", fractionalSecondDigits).
@ -835,7 +835,7 @@ ThrowCompletionOr<Array*> format_date_time_to_parts(GlobalObject& global_object,
// 4. For each Record { [[Type]], [[Value]] } part in parts, do
for (auto& part : parts) {
// a. Let O be ! OrdinaryObjectCreate(%Object.prototype%).
// a. Let O be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
@ -1155,7 +1155,7 @@ ThrowCompletionOr<Array*> format_date_time_range_to_parts(GlobalObject& global_o
// 4. For each Record { [[Type]], [[Value]], [[Source]] } part in parts, do
for (auto& part : parts) {
// a. Let O be ! OrdinaryObjectCreate(%ObjectPrototype%).
// a. Let O be OrdinaryObjectCreate(%ObjectPrototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).

View file

@ -146,7 +146,7 @@ JS_DEFINE_NATIVE_FUNCTION(DateTimeFormatPrototype::resolved_options)
// 3. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
auto* date_time_format = TRY(typed_this_object(global_object));
// 4. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 4. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 5. For each row of Table 5, except the header row, in table order, do

View file

@ -128,7 +128,7 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(displayNames, [[InitializedDisplayNames]]).
auto* display_names = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 8, except the header row, in table order, do

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -69,7 +69,7 @@ JS_DEFINE_NATIVE_FUNCTION(Intl::get_canonical_locales)
for (auto& locale : locale_list)
marked_locale_list.append(js_string(vm, move(locale)));
// 2. Return ! CreateArrayFromList(ll).
// 2. Return CreateArrayFromList(ll).
return Array::create_from(global_object, marked_locale_list);
}
@ -150,7 +150,7 @@ JS_DEFINE_NATIVE_FUNCTION(Intl::supported_values_of)
return vm.throw_completion<RangeError>(global_object, ErrorType::IntlInvalidKey, key);
}
// 9. Return ! CreateArrayFromList( list ).
// 9. Return CreateArrayFromList( list ).
return Array::create_from<StringView>(global_object, list, [&](auto value) { return js_string(vm, value); });
}

View file

@ -216,7 +216,7 @@ Array* format_list_to_parts(GlobalObject& global_object, ListFormat const& list_
// 4. For each Record { [[Type]], [[Value]] } part in parts, do
for (auto& part : parts) {
// a. Let O be ! OrdinaryObjectCreate(%Object.prototype%).
// a. Let O be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).

View file

@ -73,7 +73,7 @@ JS_DEFINE_NATIVE_FUNCTION(ListFormatPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(lf, [[InitializedListFormat]]).
auto* list_format = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 10, except the header row, in table order, do

View file

@ -349,7 +349,7 @@ ThrowCompletionOr<Object*> LocaleConstructor::construct(FunctionObject& new_targ
// 35. If relevantExtensionKeys contains "kn", then
if (relevant_extension_keys.span().contains_slow("kn"sv)) {
// a. If ! SameValue(r.[[kn]], "true") is true or r.[[kn]] is the empty String, then
// a. If SameValue(r.[[kn]], "true") is true or r.[[kn]] is the empty String, then
if (result.kn.has_value() && (same_value(js_string(vm, *result.kn), js_string(vm, "true")) || result.kn->is_empty())) {
// i. Set locale.[[Numeric]] to true.
locale->set_numeric(true);

View file

@ -641,7 +641,7 @@ Vector<PatternPartition> partition_notation_sub_pattern(GlobalObject& global_obj
// 2. Else use an implementation dependent algorithm to map n to the appropriate representation of n in the given numbering system.
formatted_string = Unicode::replace_digits_for_number_system(number_format.numbering_system(), formatted_string);
// 3. Let decimalSepIndex be ! StringIndexOf(n, ".", 0).
// 3. Let decimalSepIndex be StringIndexOf(n, ".", 0).
auto decimal_sep_index = formatted_string.find('.');
StringView integer;
@ -817,7 +817,7 @@ Array* format_numeric_to_parts(GlobalObject& global_object, NumberFormat& number
// 4. For each Record { [[Type]], [[Value]] } part in parts, do
for (auto& part : parts) {
// a. Let O be ! OrdinaryObjectCreate(%Object.prototype%).
// a. Let O be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).

View file

@ -84,7 +84,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberFormatPrototype::resolved_options)
// 3. Perform ? RequireInternalSlot(nf, [[InitializedNumberFormat]]).
auto* number_format = TRY(typed_this_object(global_object));
// 4. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 4. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 5. For each row of Table 11, except the header row, in table order, do

View file

@ -37,7 +37,7 @@ JS_DEFINE_NATIVE_FUNCTION(PluralRulesPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
auto* plural_rules = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 13, except the header row, in table order, do
@ -61,7 +61,7 @@ JS_DEFINE_NATIVE_FUNCTION(PluralRulesPrototype::resolved_options)
// FIXME: Implement this when the data is available in LibUnicode.
MarkedVector<Value> plural_categories { vm.heap() };
// 6. Perform ! CreateDataProperty(options, "pluralCategories", ! CreateArrayFromList(pluralCategories)).
// 6. Perform ! CreateDataProperty(options, "pluralCategories", CreateArrayFromList(pluralCategories)).
MUST(options->create_data_property_or_throw(vm.names.pluralCategories, Array::create_from(global_object, plural_categories)));
// 7. Return options.

View file

@ -257,7 +257,7 @@ ThrowCompletionOr<Array*> format_relative_time_to_parts(GlobalObject& global_obj
// 4. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
for (auto& part : parts) {
// a. Let O be ! OrdinaryObjectCreate(%Object.prototype%).
// a. Let O be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).

View file

@ -73,7 +73,7 @@ JS_DEFINE_NATIVE_FUNCTION(RelativeTimeFormatPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
auto* relative_time_format = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 15, except the header row, in table order, do

View file

@ -14,7 +14,7 @@ namespace JS::Intl {
SegmentIterator* SegmentIterator::create(GlobalObject& global_object, Segmenter& segmenter, Utf16View const& string, Segments const& segments)
{
// 1. Let internalSlotsList be « [[IteratingSegmenter]], [[IteratedString]], [[IteratedStringNextSegmentCodeUnitIndex]] ».
// 2. Let iterator be ! OrdinaryObjectCreate(%SegmentIteratorPrototype%, internalSlotsList).
// 2. Let iterator be OrdinaryObjectCreate(%SegmentIteratorPrototype%, internalSlotsList).
// 3. Set iterator.[[IteratingSegmenter]] to segmenter.
// 4. Set iterator.[[IteratedString]] to string.
// 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0.

View file

@ -52,7 +52,7 @@ JS_DEFINE_NATIVE_FUNCTION(SegmentIteratorPrototype::next)
// 7. If endIndex is not finite, then
if (!Value(end_index).is_finite_number()) {
// a. Return ! CreateIterResultObject(undefined, true).
// a. Return CreateIterResultObject(undefined, true).
return create_iterator_result_object(global_object, js_undefined(), true);
}
@ -62,7 +62,7 @@ JS_DEFINE_NATIVE_FUNCTION(SegmentIteratorPrototype::next)
// 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string, startIndex, endIndex).
auto* segment_data = create_segment_data_object(global_object, segmenter, string, start_index, end_index);
// 10. Return ! CreateIterResultObject(segmentData, false).
// 10. Return CreateIterResultObject(segmentData, false).
return create_iterator_result_object(global_object, segment_data, false);
}

View file

@ -61,7 +61,7 @@ Object* create_segment_data_object(GlobalObject& global_object, Segmenter const&
// 4. Assert: startIndex < endIndex.
VERIFY(start_index < end_index);
// 5. Let result be ! OrdinaryObjectCreate(%Object.prototype%).
// 5. Let result be OrdinaryObjectCreate(%Object.prototype%).
auto* result = Object::create(global_object, global_object.object_prototype());
// 6. Let segment be the substring of string from startIndex to endIndex.

View file

@ -38,7 +38,7 @@ JS_DEFINE_NATIVE_FUNCTION(SegmenterPrototype::resolved_options)
// 2. Perform ? RequireInternalSlot(segmenter, [[InitializedSegmenter]]).
auto* segmenter = TRY(typed_this_object(global_object));
// 3. Let options be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto* options = Object::create(global_object, global_object.object_prototype());
// 4. For each row of Table 16, except the header row, in table order, do

View file

@ -14,7 +14,7 @@ namespace JS::Intl {
Segments* Segments::create(GlobalObject& global_object, Segmenter& segmenter, Utf16String string)
{
// 1. Let internalSlotsList be « [[SegmentsSegmenter]], [[SegmentsString]] ».
// 2. Let segments be ! OrdinaryObjectCreate(%SegmentsPrototype%, internalSlotsList).
// 2. Let segments be OrdinaryObjectCreate(%SegmentsPrototype%, internalSlotsList).
// 3. Set segments.[[SegmentsSegmenter]] to segmenter.
// 4. Set segments.[[SegmentsString]] to string.
// 5. Return segments.

View file

@ -36,8 +36,8 @@ ThrowCompletionOr<Iterator> get_iterator(GlobalObject& global_object, Value valu
// 2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod).
auto sync_iterator_record = TRY(get_iterator(global_object, value, IteratorHint::Sync, sync_method));
// 3. Return ! CreateAsyncFromSyncIterator(syncIteratorRecord).
return MUST(create_async_from_sync_iterator(global_object, sync_iterator_record));
// 3. Return CreateAsyncFromSyncIterator(syncIteratorRecord).
return create_async_from_sync_iterator(global_object, sync_iterator_record);
}
method = Value(async_method);
@ -98,7 +98,7 @@ ThrowCompletionOr<bool> iterator_complete(GlobalObject& global_object, Object& i
{
auto& vm = global_object.vm();
// 1. Return ! ToBoolean(? Get(iterResult, "done")).
// 1. Return ToBoolean(? Get(iterResult, "done")).
return TRY(iterator_result.get(vm.names.done)).to_boolean();
}
@ -140,7 +140,7 @@ static Completion iterator_close_impl(GlobalObject& global_object, Iterator cons
// 2. Let iterator be iteratorRecord.[[Iterator]].
auto* iterator = iterator_record.iterator;
// 3. Let innerResult be GetMethod(iterator, "return").
// 3. Let innerResult be Completion(GetMethod(iterator, "return")).
auto inner_result = ThrowCompletionOr<Value> { js_undefined() };
auto get_method_result = Value(iterator).get_method(global_object, vm.names.return_);
if (get_method_result.is_error())
@ -151,25 +151,25 @@ static Completion iterator_close_impl(GlobalObject& global_object, Iterator cons
// a. Let return be innerResult.[[Value]].
auto* return_method = get_method_result.value();
// b. If return is undefined, return Completion(completion).
// b. If return is undefined, return ? completion.
if (!return_method)
return completion;
// c. Set innerResult to Call(return, iterator).
// c. Set innerResult to Completion(Call(return, iterator)).
inner_result = call(global_object, return_method, iterator);
// Note: If this is AsyncIteratorClose perform one extra step.
if (iterator_hint == IteratorHint::Async && !inner_result.is_error()) {
// d. If innerResult.[[Type]] is normal, set innerResult to Await(innerResult.[[Value]]).
// d. If innerResult.[[Type]] is normal, set innerResult to Completion(Await(innerResult.[[Value]])).
inner_result = await(global_object, inner_result.value());
}
}
// 5. If completion.[[Type]] is throw, return Completion(completion).
// 5. If completion.[[Type]] is throw, return ? completion.
if (completion.is_error())
return completion;
// 6. If innerResult.[[Type]] is throw, return Completion(innerResult).
// 6. If innerResult.[[Type]] is throw, return ? innerResult.
if (inner_result.is_throw_completion())
return inner_result;
@ -177,7 +177,7 @@ static Completion iterator_close_impl(GlobalObject& global_object, Iterator cons
if (!inner_result.value().is_object())
return vm.throw_completion<TypeError>(global_object, ErrorType::IterableReturnBadReturn);
// 8. Return Completion(completion).
// 8. Return ? completion.
return completion;
}
@ -198,7 +198,7 @@ Object* create_iterator_result_object(GlobalObject& global_object, Value value,
{
auto& vm = global_object.vm();
// 1. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
// 1. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// 2. Perform ! CreateDataPropertyOrThrow(obj, "value", value).

View file

@ -87,7 +87,7 @@ ThrowCompletionOr<void> ModuleEnvironment::create_import_binding(FlyString name,
module,
move(binding_name) });
// 4. Return NormalCompletion(empty).
// 4. Return unused.
return {};
}

View file

@ -40,8 +40,8 @@ ThrowCompletionOr<Object*> ModuleNamespaceObject::internal_get_prototype_of() co
// 10.4.6.2 [[SetPrototypeOf]] ( V ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-setprototypeof-v
ThrowCompletionOr<bool> ModuleNamespaceObject::internal_set_prototype_of(Object* prototype)
{
// 1. Return ? SetImmutablePrototype(O, V).
return set_immutable_prototype(prototype);
// 1. Return ! SetImmutablePrototype(O, V).
return MUST(set_immutable_prototype(prototype));
}
// 10.4.6.3 [[IsExtensible]] ( ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-isextensible
@ -81,9 +81,9 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ModuleNamespaceObject::internal_
// 10.4.6.6 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-defineownproperty-p-desc
ThrowCompletionOr<bool> ModuleNamespaceObject::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& descriptor)
{
// 1. If Type(P) is Symbol, return OrdinaryDefineOwnProperty(O, P, Desc).
// 1. If Type(P) is Symbol, return ! OrdinaryDefineOwnProperty(O, P, Desc).
if (property_key.is_symbol())
return Object::internal_define_own_property(property_key, descriptor);
return MUST(Object::internal_define_own_property(property_key, descriptor));
// 2. Let current be ? O.[[GetOwnProperty]](P).
auto current = TRY(internal_get_own_property(property_key));
@ -100,7 +100,7 @@ ThrowCompletionOr<bool> ModuleNamespaceObject::internal_define_own_property(Prop
if (descriptor.enumerable.has_value() && !descriptor.enumerable.value())
return false;
// 6. If ! IsAccessorDescriptor(Desc) is true, return false.
// 6. If IsAccessorDescriptor(Desc) is true, return false.
if (descriptor.is_accessor_descriptor())
return false;
@ -119,9 +119,9 @@ ThrowCompletionOr<bool> ModuleNamespaceObject::internal_define_own_property(Prop
// 10.4.6.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-module-namespace-exotic-objects-hasproperty-p
ThrowCompletionOr<bool> ModuleNamespaceObject::internal_has_property(PropertyKey const& property_key) const
{
// 1. If Type(P) is Symbol, return OrdinaryHasProperty(O, P).
// 1. If Type(P) is Symbol, return ! OrdinaryHasProperty(O, P).
if (property_key.is_symbol())
return Object::internal_has_property(property_key);
return MUST(Object::internal_has_property(property_key));
// 2. Let exports be O.[[Exports]].
// 3. If P is an element of exports, return true.
@ -138,8 +138,8 @@ ThrowCompletionOr<Value> ModuleNamespaceObject::internal_get(PropertyKey const&
{
// 1. If Type(P) is Symbol, then
if (property_key.is_symbol()) {
// a. Return ? OrdinaryGet(O, P, Receiver).
return Object::internal_get(property_key, receiver);
// a. Return ! OrdinaryGet(O, P, Receiver).
return MUST(Object::internal_get(property_key, receiver));
}
// 2. Let exports be O.[[Exports]].
@ -190,8 +190,8 @@ ThrowCompletionOr<bool> ModuleNamespaceObject::internal_delete(PropertyKey const
{
// 1. If Type(P) is Symbol, then
if (property_key.is_symbol()) {
// a. Return ? OrdinaryDelete(O, P).
return Object::internal_delete(property_key);
// a. Return ! OrdinaryDelete(O, P).
return MUST(Object::internal_delete(property_key));
}
// 2. Let exports be O.[[Exports]].
@ -209,7 +209,7 @@ ThrowCompletionOr<MarkedVector<Value>> ModuleNamespaceObject::internal_own_prope
{
// 1. Let exports be O.[[Exports]].
// 2. Let symbolKeys be ! OrdinaryOwnPropertyKeys(O).
// 2. Let symbolKeys be OrdinaryOwnPropertyKeys(O).
auto symbol_keys = MUST(Object::internal_own_property_keys());
// 3. Return the list-concatenation of exports and symbolKeys.

View file

@ -38,13 +38,13 @@ NativeFunction* NativeFunction::create(GlobalObject& global_object, Function<Thr
// 9. Set func.[[InitialName]] to null.
auto* function = global_object.heap().allocate<NativeFunction>(global_object, global_object, move(behaviour), prototype.value(), *realm.value());
// 10. Perform ! SetFunctionLength(func, length).
// 10. Perform SetFunctionLength(func, length).
function->set_function_length(length);
// 11. If prefix is not present, then
// a. Perform ! SetFunctionName(func, name).
// a. Perform SetFunctionName(func, name).
// 12. Else,
// a. Perform ! SetFunctionName(func, name, prefix).
// a. Perform SetFunctionName(func, name, prefix).
function->set_function_name(name, prefix);
// 13. Return func.
@ -156,7 +156,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
// 11. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
vm.pop_execution_context();
// 12. Return result.
// 12. Return ? result.
return result;
}
@ -220,7 +220,7 @@ ThrowCompletionOr<Object*> NativeFunction::internal_construct(MarkedVector<Value
// 11. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
vm.pop_execution_context();
// 12. Return result.
// 12. Return ? result.
return result;
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
@ -136,7 +136,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_exponential)
// 3. Assert: If fractionDigits is undefined, then f is 0.
VERIFY(!fraction_digits_value.is_undefined() || (fraction_digits == 0));
// 4. If x is not finite, return ! Number::toString(x).
// 4. If x is not finite, return Number::toString(x).
if (!number_value.is_finite_number())
return js_string(vm, MUST(number_value.to_string(global_object)));
@ -261,7 +261,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_fixed)
if (fraction_digits < 0 || fraction_digits > 100)
return vm.throw_completion<RangeError>(global_object, ErrorType::InvalidFractionDigits);
// 6. If x is not finite, return ! Number::toString(x).
// 6. If x is not finite, return Number::toString(x).
if (!number_value.is_finite_number())
return js_string(vm, TRY(number_value.to_string(global_object)));
@ -350,7 +350,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_precision)
// 3. Let p be ? ToIntegerOrInfinity(precision).
auto precision = TRY(precision_value.to_integer_or_infinity(global_object));
// 4. If x is not finite, return ! Number::toString(x).
// 4. If x is not finite, return Number::toString(x).
if (!number_value.is_finite_number())
return js_string(vm, MUST(number_value.to_string(global_object)));

View file

@ -91,7 +91,7 @@ ThrowCompletionOr<Value> Object::get(PropertyKey const& property_key) const
// NOTE: 7.3.3 GetV ( V, P ) is implemented as Value::get().
// 7.3.4 Set ( O, P, V, Throw ), https://tc39.es/ecma262/#sec-set-o-p-v-throw
ThrowCompletionOr<bool> Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions)
ThrowCompletionOr<void> Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions)
{
auto& vm = this->vm();
@ -107,8 +107,8 @@ ThrowCompletionOr<bool> Object::set(PropertyKey const& property_key, Value value
return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectSetReturnedFalse);
}
// 3. Return success.
return success;
// 3. Return unused.
return {};
}
// 7.3.5 CreateDataProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createdataproperty
@ -129,12 +129,14 @@ ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property
}
// 7.3.6 CreateMethodProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createmethodproperty
ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& property_key, Value value)
ThrowCompletionOr<void> Object::create_method_property(PropertyKey const& property_key, Value value)
{
VERIFY(property_key.is_valid());
VERIFY(!value.is_empty());
// 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
// 1. Assert: O is an ordinary, extensible object with no non-configurable properties.
// 2. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
auto new_descriptor = PropertyDescriptor {
.value = value,
.writable = true,
@ -142,8 +144,11 @@ ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& proper
.configurable = true,
};
// 2. Return ? O.[[DefineOwnProperty]](P, newDesc).
return internal_define_own_property(property_key, new_descriptor);
// 3. Perform ! O.[[DefineOwnProperty]](P, newDesc).
MUST(internal_define_own_property(property_key, new_descriptor));
// 4. Return unused.
return {};
}
// 7.3.7 CreateDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createdatapropertyorthrow
@ -168,20 +173,24 @@ ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const&
}
// 7.3.8 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow
ThrowCompletionOr<bool> Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value)
void Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value)
{
VERIFY(property_key.is_valid());
VERIFY(!value.is_empty());
// 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
// 1. Assert: O is an ordinary, extensible object with no non-configurable properties.
// 2. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true };
// 2. Return ? DefinePropertyOrThrow(O, P, newDesc).
return define_property_or_throw(property_key, new_description);
// 3. Perform ! DefinePropertyOrThrow(O, P, newDesc).
MUST(define_property_or_throw(property_key, new_description));
// 4. Return unused.
}
// 7.3.9 DefinePropertyOrThrow ( O, P, desc ), https://tc39.es/ecma262/#sec-definepropertyorthrow
ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
ThrowCompletionOr<void> Object::define_property_or_throw(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
{
auto& vm = this->vm();
@ -196,12 +205,12 @@ ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& prop
return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDefineOwnPropertyReturnedFalse);
}
// 3. Return success.
return success;
// 3. Return unused.
return {};
}
// 7.3.10 DeletePropertyOrThrow ( O, P ), https://tc39.es/ecma262/#sec-deletepropertyorthrow
ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& property_key)
ThrowCompletionOr<void> Object::delete_property_or_throw(PropertyKey const& property_key)
{
auto& vm = this->vm();
@ -216,8 +225,8 @@ ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& prop
return vm.throw_completion<TypeError>(global_object(), ErrorType::ObjectDeleteReturnedFalse);
}
// 3. Return success.
return success;
// 3. Return unused.
return {};
}
// 7.3.12 HasProperty ( O, P ), https://tc39.es/ecma262/#sec-hasproperty
@ -393,7 +402,7 @@ ThrowCompletionOr<MarkedVector<Value>> Object::enumerable_own_property_names(Pro
// i. Assert: kind is key+value.
VERIFY(kind == PropertyKind::KeyAndValue);
// ii. Let entry be ! CreateArrayFromList(« key, value »).
// ii. Let entry be CreateArrayFromList(« key, value »).
auto entry = Array::create_from(global_object, { key, value });
// iii. Append entry to properties.
@ -406,10 +415,10 @@ ThrowCompletionOr<MarkedVector<Value>> Object::enumerable_own_property_names(Pro
}
// 7.3.26 CopyDataProperties ( target, source, excludedItems ), https://tc39.es/ecma262/#sec-copydataproperties
ThrowCompletionOr<Object*> Object::copy_data_properties(Value source, HashTable<PropertyKey> const& seen_names, GlobalObject& global_object)
ThrowCompletionOr<void> Object::copy_data_properties(Value source, HashTable<PropertyKey> const& seen_names, GlobalObject& global_object)
{
if (source.is_nullish())
return this;
return {};
auto* from_object = MUST(source.to_object(global_object));
@ -425,7 +434,7 @@ ThrowCompletionOr<Object*> Object::copy_data_properties(Value source, HashTable<
TRY(create_data_property_or_throw(next_key, prop_value));
}
}
return this;
return {};
}
// 7.3.27 PrivateElementFind ( O, P ), https://tc39.es/ecma262/#sec-privateelementfind
@ -753,7 +762,7 @@ ThrowCompletionOr<bool> Object::internal_set(PropertyKey const& property_key, Va
// 2. Let ownDesc be ? O.[[GetOwnProperty]](P).
auto own_descriptor = TRY(internal_get_own_property(property_key));
// 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
// 3. Return ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
return ordinary_set_with_own_descriptor(property_key, value, receiver, own_descriptor);
}

View file

@ -25,10 +25,13 @@
namespace JS {
#define JS_OBJECT(class_, base_class) \
public: \
using Base = base_class; \
virtual StringView class_name() const override { return #class_; }
#define JS_OBJECT(class_, base_class) \
public: \
using Base = base_class; \
virtual StringView class_name() const override \
{ \
return #class_; \
}
struct PrivateElement {
enum class Kind {
@ -91,19 +94,19 @@ public:
// 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
ThrowCompletionOr<Value> get(PropertyKey const&) const;
ThrowCompletionOr<bool> set(PropertyKey const&, Value, ShouldThrowExceptions);
ThrowCompletionOr<void> set(PropertyKey const&, Value, ShouldThrowExceptions);
ThrowCompletionOr<bool> create_data_property(PropertyKey const&, Value);
ThrowCompletionOr<bool> create_method_property(PropertyKey const&, Value);
ThrowCompletionOr<void> create_method_property(PropertyKey const&, Value);
ThrowCompletionOr<bool> create_data_property_or_throw(PropertyKey const&, Value);
ThrowCompletionOr<bool> create_non_enumerable_data_property_or_throw(PropertyKey const&, Value);
ThrowCompletionOr<bool> define_property_or_throw(PropertyKey const&, PropertyDescriptor const&);
ThrowCompletionOr<bool> delete_property_or_throw(PropertyKey const&);
void create_non_enumerable_data_property_or_throw(PropertyKey const&, Value);
ThrowCompletionOr<void> define_property_or_throw(PropertyKey const&, PropertyDescriptor const&);
ThrowCompletionOr<void> delete_property_or_throw(PropertyKey const&);
ThrowCompletionOr<bool> has_property(PropertyKey const&) const;
ThrowCompletionOr<bool> has_own_property(PropertyKey const&) const;
ThrowCompletionOr<bool> set_integrity_level(IntegrityLevel);
ThrowCompletionOr<bool> test_integrity_level(IntegrityLevel) const;
ThrowCompletionOr<MarkedVector<Value>> enumerable_own_property_names(PropertyKind kind) const;
ThrowCompletionOr<Object*> copy_data_properties(Value source, HashTable<PropertyKey> const& seen_names, GlobalObject& global_object);
ThrowCompletionOr<void> copy_data_properties(Value source, HashTable<PropertyKey> const& seen_names, GlobalObject& global_object);
PrivateElement* private_element_find(PrivateName const& name);
ThrowCompletionOr<void> private_field_add(PrivateName const& name, Value value);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -83,7 +83,7 @@ enum class GetOwnPropertyKeysType {
};
// 20.1.2.11.1 GetOwnPropertyKeys ( O, type ), https://tc39.es/ecma262/#sec-getownpropertykeys
static ThrowCompletionOr<Array*> get_own_property_keys(GlobalObject& global_object, Value value, GetOwnPropertyKeysType type)
static ThrowCompletionOr<MarkedVector<Value>> get_own_property_keys(GlobalObject& global_object, Value value, GetOwnPropertyKeysType type)
{
auto& vm = global_object.vm();
@ -105,22 +105,22 @@ static ThrowCompletionOr<Array*> get_own_property_keys(GlobalObject& global_obje
}
}
// 5. Return CreateArrayFromList(nameList).
return Array::create_from(global_object, name_list);
// 5. Return nameList.
return { move(name_list) };
}
// 20.1.2.10 Object.getOwnPropertyNames ( O ), https://tc39.es/ecma262/#sec-object.getownpropertynames
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
{
// 1. Return ? GetOwnPropertyKeys(O, string).
return TRY(get_own_property_keys(global_object, vm.argument(0), GetOwnPropertyKeysType::String));
// 1. Return CreateArrayFromList(? GetOwnPropertyKeys(O, string)).
return Array::create_from(global_object, TRY(get_own_property_keys(global_object, vm.argument(0), GetOwnPropertyKeysType::String)));
}
// 20.1.2.11 Object.getOwnPropertySymbols ( O ), https://tc39.es/ecma262/#sec-object.getownpropertysymbols
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_symbols)
{
// 1. Return ? GetOwnPropertyKeys(O, symbol).
return TRY(get_own_property_keys(global_object, vm.argument(0), GetOwnPropertyKeysType::Symbol));
// 1. Return CreateArrayFromList(? GetOwnPropertyKeys(O, symbol)).
return Array::create_from(global_object, TRY(get_own_property_keys(global_object, vm.argument(0), GetOwnPropertyKeysType::Symbol)));
}
// 20.1.2.12 Object.getPrototypeOf ( O ), https://tc39.es/ecma262/#sec-object.getprototypeof
@ -268,7 +268,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptors)
// 2. Let ownKeys be ? obj.[[OwnPropertyKeys]]().
auto own_keys = TRY(object->internal_own_property_keys());
// 3. Let descriptors be ! OrdinaryObjectCreate(%Object.prototype%).
// 3. Let descriptors be OrdinaryObjectCreate(%Object.prototype%).
auto* descriptors = Object::create(global_object, global_object.object_prototype());
// 4. For each element key of ownKeys, do
@ -278,7 +278,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptors)
// a. Let desc be ? obj.[[GetOwnProperty]](key).
auto desc = TRY(object->internal_get_own_property(property_key));
// b. Let descriptor be ! FromPropertyDescriptor(desc).
// b. Let descriptor be FromPropertyDescriptor(desc).
auto descriptor = from_property_descriptor(global_object, desc);
// c. If descriptor is not undefined, perform ! CreateDataPropertyOrThrow(descriptors, key, descriptor).
@ -355,7 +355,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::create)
if (!proto.is_object() && !proto.is_null())
return vm.throw_completion<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
// 2. Let obj be ! OrdinaryObjectCreate(O).
// 2. Let obj be OrdinaryObjectCreate(O).
auto* object = Object::create(global_object, proto.is_null() ? nullptr : &proto.as_object());
// 3. If Properties is not undefined, then

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -47,7 +47,7 @@ ThrowCompletionOr<bool> ObjectEnvironment::has_binding(FlyString const& name, Op
// 6. If Type(unscopables) is Object, then
if (unscopables.is_object()) {
// a. Let blocked be ! ToBoolean(? Get(unscopables, N)).
// a. Let blocked be ToBoolean(? Get(unscopables, N)).
auto blocked = TRY(unscopables.as_object().get(name)).to_boolean();
// b. If blocked is true, return false.
@ -63,8 +63,10 @@ ThrowCompletionOr<bool> ObjectEnvironment::has_binding(FlyString const& name, Op
ThrowCompletionOr<void> ObjectEnvironment::create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted)
{
// 1. Let bindingObject be envRec.[[BindingObject]].
// 2. Return ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
// 2. Perform ? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }).
TRY(m_binding_object.define_property_or_throw(name, { .value = js_undefined(), .writable = true, .enumerable = true, .configurable = can_be_deleted }));
// 3. Return unused.
return {};
}
@ -78,8 +80,11 @@ ThrowCompletionOr<void> ObjectEnvironment::create_immutable_binding(GlobalObject
// 9.1.1.2.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v
ThrowCompletionOr<void> ObjectEnvironment::initialize_binding(GlobalObject& global_object, FlyString const& name, Value value)
{
// 1. Return ? envRec.SetMutableBinding(N, V, false).
return set_mutable_binding(global_object, name, value, false);
// 1. Perform ? envRec.SetMutableBinding(N, V, false).
TRY(set_mutable_binding(global_object, name, value, false));
// 2. Return unused.
return {};
}
// 9.1.1.2.5 SetMutableBinding ( N, V, S ), https://tc39.es/ecma262/#sec-object-environment-records-setmutablebinding-n-v-s
@ -95,7 +100,7 @@ ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(GlobalObject& glo
if (!still_exists && strict)
return vm.throw_completion<ReferenceError>(global_object, ErrorType::UnknownIdentifier, name);
// 4. Return ? Set(bindingObject, N, V, S).
// 4. Perform ? Set(bindingObject, N, V, S).
auto result_or_error = m_binding_object.set(name, value, strict ? Object::ShouldThrowExceptions::Yes : Object::ShouldThrowExceptions::No);
// Note: Nothing like this in the spec, this is here to produce nicer errors instead of the generic one thrown by Object::set().
@ -112,6 +117,8 @@ ThrowCompletionOr<void> ObjectEnvironment::set_mutable_binding(GlobalObject& glo
if (result_or_error.is_error())
return result_or_error.release_error();
// 5. Return unused.
return {};
}
@ -126,7 +133,7 @@ ThrowCompletionOr<Value> ObjectEnvironment::get_binding_value(GlobalObject& glob
// 3. If value is false, then
if (!value) {
// a. If S is false, return the value undefined; otherwise throw a ReferenceError exception.
// a. If S is false, return undefined; otherwise throw a ReferenceError exception.
if (!strict)
return js_undefined();
return vm.throw_completion<ReferenceError>(global_object, ErrorType::UnknownIdentifier, name);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -65,7 +65,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
// 2. Let stepsResolve be the algorithm steps defined in Promise Resolve Functions.
// 3. Let lengthResolve be the number of non-optional parameters of the function definition in Promise Resolve Functions.
// 4. Let resolve be ! CreateBuiltinFunction(stepsResolve, lengthResolve, "", « [[Promise]], [[AlreadyResolved]] »).
// 4. Let resolve be CreateBuiltinFunction(stepsResolve, lengthResolve, "", « [[Promise]], [[AlreadyResolved]] »).
// 5. Set resolve.[[Promise]] to promise.
// 6. Set resolve.[[AlreadyResolved]] to alreadyResolved.
@ -96,25 +96,34 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
// a. Let selfResolutionError be a newly created TypeError object.
auto* self_resolution_error = TypeError::create(global_object, "Cannot resolve promise with itself");
// b. Return RejectPromise(promise, selfResolutionError).
return promise.reject(self_resolution_error);
// b. Perform RejectPromise(promise, selfResolutionError).
promise.reject(self_resolution_error);
// c. Return undefined.
return js_undefined();
}
// 8. If Type(resolution) is not Object, then
if (!resolution.is_object()) {
// a. Return FulfillPromise(promise, resolution).
// a. Perform FulfillPromise(promise, resolution).
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Resolution is not an object, fulfilling with {}", &promise, resolution);
return promise.fulfill(resolution);
promise.fulfill(resolution);
// b. Return undefined.
return js_undefined();
}
// 9. Let then be Get(resolution, "then").
// 9. Let then be Completion(Get(resolution, "then")).
auto then = resolution.as_object().get(vm.names.then);
// 10. If then is an abrupt completion, then
if (then.is_throw_completion()) {
// a. Return RejectPromise(promise, then.[[Value]]).
// a. Perform RejectPromise(promise, then.[[Value]]).
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Exception while getting 'then' property, rejecting with error", &promise);
return promise.reject(*then.throw_completion().value());
promise.reject(*then.throw_completion().value());
// b. Return undefined.
return js_undefined();
}
// 11. Let thenAction be then.[[Value]].
@ -122,9 +131,12 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
// 12. If IsCallable(thenAction) is false, then
if (!then_action.is_function()) {
// a. Return FulfillPromise(promise, resolution).
// a. Perform FulfillPromise(promise, resolution).
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / PromiseResolvingFunction]: Then action is not a function, fulfilling with {}", &promise, resolution);
return promise.fulfill(resolution);
promise.fulfill(resolution);
// b. Return undefined.
return js_undefined();
}
// 13. Let thenJobCallback be HostMakeJobCallback(thenAction).
@ -146,7 +158,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
// 7. Let stepsReject be the algorithm steps defined in Promise Reject Functions.
// 8. Let lengthReject be the number of non-optional parameters of the function definition in Promise Reject Functions.
// 9. Let reject be ! CreateBuiltinFunction(stepsReject, lengthReject, "", « [[Promise]], [[AlreadyResolved]] »).
// 9. Let reject be CreateBuiltinFunction(stepsReject, lengthReject, "", « [[Promise]], [[AlreadyResolved]] »).
// 10. Set reject.[[Promise]] to promise.
// 11. Set reject.[[AlreadyResolved]] to alreadyResolved.
@ -168,8 +180,11 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
// 6. Set alreadyResolved.[[Value]] to true.
already_resolved.value = true;
// 7. Return RejectPromise(promise, reason).
return promise.reject(reason);
// 7. Perform RejectPromise(promise, reason).
promise.reject(reason);
// 8. Return undefined.
return js_undefined();
});
reject_function->define_direct_property(vm.names.name, js_string(vm, String::empty()), Attribute::Configurable);
@ -178,7 +193,7 @@ Promise::ResolvingFunctions Promise::create_resolving_functions()
}
// 27.2.1.4 FulfillPromise ( promise, value ), https://tc39.es/ecma262/#sec-fulfillpromise
Value Promise::fulfill(Value value)
void Promise::fulfill(Value value)
{
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / fulfill()]: Fulfilling promise with value {}", this, value);
@ -198,15 +213,16 @@ Value Promise::fulfill(Value value)
// 6. Set promise.[[PromiseState]] to fulfilled.
m_state = State::Fulfilled;
// 7. Return TriggerPromiseReactions(reactions, value).
// 7. Perform TriggerPromiseReactions(reactions, value).
trigger_reactions();
m_fulfill_reactions.clear();
m_reject_reactions.clear();
return js_undefined();
// 8. Return unused.
}
// 27.2.1.7 RejectPromise ( promise, reason ), https://tc39.es/ecma262/#sec-rejectpromise
Value Promise::reject(Value reason)
void Promise::reject(Value reason)
{
dbgln_if(PROMISE_DEBUG, "[Promise @ {} / reject()]: Rejecting promise with reason {}", this, reason);
@ -232,11 +248,12 @@ Value Promise::reject(Value reason)
if (!m_is_handled)
vm.host_promise_rejection_tracker(*this, RejectionOperation::Reject);
// 8. Return TriggerPromiseReactions(reactions, reason).
// 8. Perform TriggerPromiseReactions(reactions, reason).
trigger_reactions();
m_fulfill_reactions.clear();
m_reject_reactions.clear();
return js_undefined();
// 9. Return unused.
}
// 27.2.1.8 TriggerPromiseReactions ( reactions, argument ), https://tc39.es/ecma262/#sec-triggerpromisereactions
@ -264,7 +281,7 @@ void Promise::trigger_reactions() const
dbgln("[Promise @ {} / trigger_reactions()]: No reactions!", this);
}
// 2. Return undefined.
// 2. Return unused.
}
// 27.2.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] ), https://tc39.es/ecma262/#sec-performpromisethen

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -41,8 +41,8 @@ public:
};
ResolvingFunctions create_resolving_functions();
Value fulfill(Value value);
Value reject(Value reason);
void fulfill(Value value);
void reject(Value reason);
Value perform_then(Value on_fulfilled, Value on_rejected, Optional<PromiseCapability> result_capability);
bool is_handled() const { return m_is_handled; }

View file

@ -58,7 +58,7 @@ static ThrowCompletionOr<Value> perform_promise_common(GlobalObject& global_obje
// 4. Repeat,
while (true) {
// a. Let next be IteratorStep(iteratorRecord).
// a. Let next be Completion(IteratorStep(iteratorRecord)).
auto next_or_error = iterator_step(global_object, iterator_record);
// b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -85,7 +85,7 @@ static ThrowCompletionOr<Value> perform_promise_common(GlobalObject& global_obje
return result_capability.promise;
}
// e. Let nextValue be IteratorValue(next).
// e. Let nextValue be Completion(IteratorValue(next)).
auto next_value_or_error = iterator_value(global_object, *next);
// f. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -123,7 +123,7 @@ static ThrowCompletionOr<Value> perform_promise_all(GlobalObject& global_object,
return perform_promise_common(
global_object, iterator_record, constructor, result_capability, promise_resolve,
[&](PromiseValueList& values) -> ThrowCompletionOr<Value> {
// 1. Let valuesArray be ! CreateArrayFromList(values).
// 1. Let valuesArray be CreateArrayFromList(values).
auto* values_array = Array::create_from(global_object, values.values());
// 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
@ -135,7 +135,7 @@ static ThrowCompletionOr<Value> perform_promise_all(GlobalObject& global_object,
[&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
// j. Let steps be the algorithm steps defined in Promise.all Resolve Element Functions.
// k. Let length be the number of non-optional parameters of the function definition in Promise.all Resolve Element Functions.
// l. Let onFulfilled be ! CreateBuiltinFunction(steps, length, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// l. Let onFulfilled be CreateBuiltinFunction(steps, length, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// m. Set onFulfilled.[[AlreadyCalled]] to false.
// n. Set onFulfilled.[[Index]] to index.
// o. Set onFulfilled.[[Values]] to values.
@ -166,7 +166,7 @@ static ThrowCompletionOr<Value> perform_promise_all_settled(GlobalObject& global
[&](PromiseValueList& values, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
// j. Let stepsFulfilled be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
// k. Let lengthFulfilled be the number of non-optional parameters of the function definition in Promise.allSettled Resolve Element Functions.
// l. Let onFulfilled be ! CreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// l. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// m. Let alreadyCalled be the Record { [[Value]]: false }.
// n. Set onFulfilled.[[AlreadyCalled]] to alreadyCalled.
// o. Set onFulfilled.[[Index]] to index.
@ -178,7 +178,7 @@ static ThrowCompletionOr<Value> perform_promise_all_settled(GlobalObject& global
// s. Let stepsRejected be the algorithm steps defined in Promise.allSettled Reject Element Functions.
// t. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.allSettled Reject Element Functions.
// u. Let onRejected be ! CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// u. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
// v. Set onRejected.[[AlreadyCalled]] to alreadyCalled.
// w. Set onRejected.[[Index]] to index.
// x. Set onRejected.[[Values]] to values.
@ -203,7 +203,7 @@ static ThrowCompletionOr<Value> perform_promise_any(GlobalObject& global_object,
// 1. Let error be a newly created AggregateError object.
auto* error = AggregateError::create(global_object);
// 2. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
// 2. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
auto* errors_array = Array::create_from(global_object, errors.values());
MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));
@ -213,7 +213,7 @@ static ThrowCompletionOr<Value> perform_promise_any(GlobalObject& global_object,
[&](PromiseValueList& errors, RemainingElements& remaining_elements_count, Value next_promise, size_t index) {
// j. Let stepsRejected be the algorithm steps defined in Promise.any Reject Element Functions.
// k. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.any Reject Element Functions.
// l. Let onRejected be ! CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
// l. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
// m. Set onRejected.[[AlreadyCalled]] to false.
// n. Set onRejected.[[Index]] to index.
// o. Set onRejected.[[Errors]] to errors.
@ -301,7 +301,7 @@ ThrowCompletionOr<Object*> PromiseConstructor::construct(FunctionObject& new_tar
// 8. Let resolvingFunctions be CreateResolvingFunctions(promise).
auto [resolve_function, reject_function] = promise->create_resolving_functions();
// 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »).
// 9. Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
auto completion = JS::call(global_object, executor.as_function(), js_undefined(), &resolve_function, &reject_function);
// 10. If completion is an abrupt completion, then
@ -323,20 +323,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all)
// 2. Let promiseCapability be ? NewPromiseCapability(C).
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
// 3. Let promiseResolve be GetPromiseResolve(C).
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
// 5. Let iteratorRecord be GetIterator(iterable).
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(global_object, vm.argument(0)));
// 7. Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve).
// 7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
auto result = perform_promise_all(global_object, iterator_record, constructor, promise_capability, promise_resolve);
// 8. If result is an abrupt completion, then
if (result.is_error()) {
// a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
if (!iterator_record.done)
result = iterator_close(global_object, iterator_record, result.release_error());
@ -344,8 +344,8 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all)
TRY_OR_REJECT(global_object, promise_capability, result);
}
// 9. Return Completion(result).
return result.release_value();
// 9. Return ? result.
return result;
}
// 27.2.4.2 Promise.allSettled ( iterable ), https://tc39.es/ecma262/#sec-promise.allsettled
@ -357,20 +357,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all_settled)
// 2. Let promiseCapability be ? NewPromiseCapability(C).
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
// 3. Let promiseResolve be GetPromiseResolve(C).
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
// 5. Let iteratorRecord be GetIterator(iterable).
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(global_object, vm.argument(0)));
// 7. Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve).
// 7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
auto result = perform_promise_all_settled(global_object, iterator_record, constructor, promise_capability, promise_resolve);
// 8. If result is an abrupt completion, then
if (result.is_error()) {
// a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
if (!iterator_record.done)
result = iterator_close(global_object, iterator_record, result.release_error());
@ -378,8 +378,8 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::all_settled)
TRY_OR_REJECT(global_object, promise_capability, result);
}
// 9. Return Completion(result).
return result.release_value();
// 9. Return ? result.
return result;
}
// 27.2.4.3 Promise.any ( iterable ), https://tc39.es/ecma262/#sec-promise.any
@ -391,20 +391,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::any)
// 2. Let promiseCapability be ? NewPromiseCapability(C).
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
// 3. Let promiseResolve be GetPromiseResolve(C).
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
// 5. Let iteratorRecord be GetIterator(iterable).
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(global_object, vm.argument(0)));
// 7. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve).
// 7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
auto result = perform_promise_any(global_object, iterator_record, constructor, promise_capability, promise_resolve);
// 8. If result is an abrupt completion, then
if (result.is_error()) {
// a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
if (!iterator_record.done)
result = iterator_close(global_object, iterator_record, result.release_error());
@ -412,8 +412,8 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::any)
TRY_OR_REJECT(global_object, promise_capability, result);
}
// 9. Return Completion(result).
return result.release_value();
// 9. Return ? result.
return result;
}
// 27.2.4.5 Promise.race ( iterable ), https://tc39.es/ecma262/#sec-promise.race
@ -425,20 +425,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::race)
// 2. Let promiseCapability be ? NewPromiseCapability(C).
auto promise_capability = TRY(new_promise_capability(global_object, constructor));
// 3. Let promiseResolve be GetPromiseResolve(C).
// 3. Let promiseResolve be Completion(GetPromiseResolve(C)).
// 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
auto promise_resolve = TRY_OR_REJECT(global_object, promise_capability, get_promise_resolve(global_object, constructor));
// 5. Let iteratorRecord be GetIterator(iterable).
// 5. Let iteratorRecord be Completion(GetIterator(iterable)).
// 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
auto iterator_record = TRY_OR_REJECT(global_object, promise_capability, get_iterator(global_object, vm.argument(0)));
// 7. Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve).
// 7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
auto result = perform_promise_race(global_object, iterator_record, constructor, promise_capability, promise_resolve);
// 8. If result is an abrupt completion, then
if (result.is_error()) {
// a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
// a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
if (!iterator_record.done)
result = iterator_close(global_object, iterator_record, result.release_error());
@ -446,8 +446,8 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::race)
TRY_OR_REJECT(global_object, promise_capability, result);
}
// 9. Return Completion(result).
return result.release_value();
// 9. Return ? result.
return result;
}
// 27.2.4.6 Promise.reject ( r ), https://tc39.es/ecma262/#sec-promise.reject

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -50,7 +50,7 @@ static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, Pr
handler_result = throw_completion(argument);
}
}
// e. Else, let handlerResult be HostCallJobCallback(handler, undefined, « argument »).
// e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
else {
dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling handler callback {} @ {} with argument {}", handler.value().callback.cell()->class_name(), handler.value().callback.cell(), argument);
MarkedVector<Value> arguments(vm.heap());
@ -63,7 +63,7 @@ static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, Pr
// i. Assert: handlerResult is not an abrupt completion.
VERIFY(!handler_result.is_abrupt());
// ii. Return NormalCompletion(empty).
// ii. Return empty.
dbgln_if(PROMISE_DEBUG, "run_reaction_job: Reaction has no PromiseCapability, returning empty value");
// TODO: This can't return an empty value at the moment, because the implicit conversion to Completion would fail.
// Change it back when this is using completions (`return normal_completion({})`)
@ -74,20 +74,18 @@ static ThrowCompletionOr<Value> run_reaction_job(GlobalObject& global_object, Pr
// h. If handlerResult is an abrupt completion, then
if (handler_result.is_abrupt()) {
// i. Let status be Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
// i. Return ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
auto* reject_function = promise_capability.value().reject;
dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling PromiseCapability's reject function @ {}", reject_function);
return call(global_object, *reject_function, js_undefined(), *handler_result.value());
}
// i. Else,
else {
// i. Let status be Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »).
// i. Return ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »).
auto* resolve_function = promise_capability.value().resolve;
dbgln_if(PROMISE_DEBUG, "[PromiseReactionJob]: Calling PromiseCapability's resolve function @ {}", resolve_function);
return call(global_object, *resolve_function, js_undefined(), *handler_result.value());
}
// j. Return Completion(status).
}
// 27.2.2.1 NewPromiseReactionJob ( reaction, argument ), https://tc39.es/ecma262/#sec-newpromisereactionjob
@ -105,7 +103,7 @@ PromiseJob create_promise_reaction_job(GlobalObject& global_object, PromiseReact
// 3. If reaction.[[Handler]] is not empty, then
auto& handler = reaction.handler();
if (handler.has_value()) {
// a. Let getHandlerRealmResult be GetFunctionRealm(reaction.[[Handler]].[[Callback]]).
// a. Let getHandlerRealmResult be Completion(GetFunctionRealm(reaction.[[Handler]].[[Callback]])).
auto get_handler_realm_result = get_function_realm(global_object, *handler->callback.cell());
// b. If getHandlerRealmResult is a normal completion, set handlerRealm to getHandlerRealmResult.[[Value]].
@ -131,7 +129,7 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_ob
// a. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve).
auto [resolve_function, reject_function] = promise_to_resolve.create_resolving_functions();
// b. Let thenCallResult be HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »).
// b. Let thenCallResult be Completion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: Calling then job callback for thenable {}", &thenable);
MarkedVector<Value> arguments(vm.heap());
arguments.append(Value(&resolve_function));
@ -140,15 +138,12 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_ob
// c. If thenCallResult is an abrupt completion, then
if (then_call_result.is_error()) {
// i. Let status be Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »).
// i. Return ? Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »).
dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: then_call_result is an abrupt completion, calling reject function with value {}", *then_call_result.throw_completion().value());
auto status = call(global_object, &reject_function, js_undefined(), *then_call_result.throw_completion().value());
// ii. Return Completion(status).
return status;
return call(global_object, &reject_function, js_undefined(), *then_call_result.throw_completion().value());
}
// d. Return Completion(thenCallResult).
// d. Return ? thenCallResult.
dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: Returning then call result {}", then_call_result.value());
return then_call_result;
}
@ -156,10 +151,11 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(GlobalObject& global_ob
// 27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then ), https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob
PromiseJob create_promise_resolve_thenable_job(GlobalObject& global_object, Promise& promise_to_resolve, Value thenable, JobCallback then)
{
// 2. Let getThenRealmResult be GetFunctionRealm(then.[[Callback]]).
Realm* then_realm { nullptr };
// 2. Let getThenRealmResult be Completion(GetFunctionRealm(then.[[Callback]])).
auto get_then_realm_result = get_function_realm(global_object, *then.callback.cell());
Realm* then_realm;
// 3. If getThenRealmResult is a normal completion, let thenRealm be getThenRealmResult.[[Value]].
if (!get_then_realm_result.is_throw_completion()) {
then_realm = get_then_realm_result.release_value();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -116,14 +116,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
return value_handle.value();
};
// iv. Let valueThunk be ! CreateBuiltinFunction(returnValue, 0, "", « »).
// iv. Let valueThunk be CreateBuiltinFunction(returnValue, 0, "", « »).
auto* value_thunk = NativeFunction::create(global_object, move(return_value), 0, "");
// v. Return ? Invoke(promise, "then", « valueThunk »).
return TRY(Value(promise).invoke(global_object, vm.names.then, value_thunk));
};
// b. Let thenFinally be ! CreateBuiltinFunction(thenFinallyClosure, 1, "", « »).
// b. Let thenFinally be CreateBuiltinFunction(thenFinallyClosure, 1, "", « »).
then_finally = NativeFunction::create(global_object, move(then_finally_closure), 1, "");
// c. Let catchFinallyClosure be a new Abstract Closure with parameters (reason) that captures onFinally and C and performs the following steps when called:
@ -144,14 +144,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
return throw_completion(reason_handle.value());
};
// iv. Let thrower be ! CreateBuiltinFunction(throwReason, 0, "", « »).
// iv. Let thrower be CreateBuiltinFunction(throwReason, 0, "", « »).
auto* thrower = NativeFunction::create(global_object, move(throw_reason), 0, "");
// v. Return ? Invoke(promise, "then", « thrower »).
return TRY(Value(promise).invoke(global_object, vm.names.then, thrower));
};
// d. Let catchFinally be ! CreateBuiltinFunction(catchFinallyClosure, 1, "", « »).
// d. Let catchFinally be CreateBuiltinFunction(catchFinallyClosure, 1, "", « »).
catch_finally = NativeFunction::create(global_object, move(catch_finally_closure), 1, "");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -54,7 +54,7 @@ ThrowCompletionOr<PromiseCapability> new_promise_capability(GlobalObject& global
return js_undefined();
};
// 5. Let executor be ! CreateBuiltinFunction(executorClosure, 2, "", « »).
// 5. Let executor be CreateBuiltinFunction(executorClosure, 2, "", « »).
auto* executor = NativeFunction::create(global_object, move(executor_closure), 2, "");
// 6. Let promise be ? Construct(C, « executor »).

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -21,22 +21,28 @@ struct PromiseCapability {
};
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
#define TRY_OR_REJECT(global_object, capability, expression) \
({ \
auto _temporary_try_or_reject_result = (expression); \
/* 1. If value is an abrupt completion, then */ \
if (_temporary_try_or_reject_result.is_error()) { \
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
TRY(JS::call(global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
\
/* b. Return capability.[[Promise]]. */ \
return capability.promise; \
} \
\
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
_temporary_try_or_reject_result.release_value(); \
#define __TRY_OR_REJECT(global_object, capability, expression, CALL_CHECK) \
({ \
auto _temporary_try_or_reject_result = (expression); \
/* 1. If value is an abrupt completion, then */ \
if (_temporary_try_or_reject_result.is_error()) { \
/* a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »). */ \
CALL_CHECK(JS::call(global_object, *capability.reject, js_undefined(), *_temporary_try_or_reject_result.release_error().value())); \
\
/* b. Return capability.[[Promise]]. */ \
return capability.promise; \
} \
\
/* 2. Else if value is a Completion Record, set value to value.[[Value]]. */ \
_temporary_try_or_reject_result.release_value(); \
})
#define TRY_OR_REJECT(global_object, capability, expression) \
__TRY_OR_REJECT(global_object, capability, expression, TRY)
#define TRY_OR_MUST_REJECT(global_object, capability, expression) \
__TRY_OR_REJECT(global_object, capability, expression, MUST)
// 27.2.1.1.1 IfAbruptRejectPromise ( value, capability ), https://tc39.es/ecma262/#sec-ifabruptrejectpromise
#define TRY_OR_REJECT_WITH_VALUE(global_object, capability, expression) \
({ \

View file

@ -76,7 +76,7 @@ ThrowCompletionOr<Value> PromiseAllResolveElementFunction::resolve_element()
// 9. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
// 10. If remainingElementsCount.[[Value]] is 0, then
if (--m_remaining_elements.value == 0) {
// a. Let valuesArray be ! CreateArrayFromList(values).
// a. Let valuesArray be CreateArrayFromList(values).
auto* values_array = Array::create_from(global_object, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
@ -102,7 +102,7 @@ ThrowCompletionOr<Value> PromiseAllSettledResolveElementFunction::resolve_elemen
auto& vm = this->vm();
auto& global_object = this->global_object();
// 9. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
// 9. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "fulfilled").
@ -117,7 +117,7 @@ ThrowCompletionOr<Value> PromiseAllSettledResolveElementFunction::resolve_elemen
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
// 14. If remainingElementsCount.[[Value]] is 0, then
if (--m_remaining_elements.value == 0) {
// a. Let valuesArray be ! CreateArrayFromList(values).
// a. Let valuesArray be CreateArrayFromList(values).
auto* values_array = Array::create_from(global_object, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
@ -143,7 +143,7 @@ ThrowCompletionOr<Value> PromiseAllSettledRejectElementFunction::resolve_element
auto& vm = this->vm();
auto& global_object = this->global_object();
// 9. Let obj be ! OrdinaryObjectCreate(%Object.prototype%).
// 9. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto* object = Object::create(global_object, global_object.object_prototype());
// 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "rejected").
@ -158,7 +158,7 @@ ThrowCompletionOr<Value> PromiseAllSettledRejectElementFunction::resolve_element
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
// 14. If remainingElementsCount.[[Value]] is 0, then
if (--m_remaining_elements.value == 0) {
// a. Let valuesArray be ! CreateArrayFromList(values).
// a. Let valuesArray be CreateArrayFromList(values).
auto* values_array = Array::create_from(global_object, m_values.values());
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
@ -193,7 +193,7 @@ ThrowCompletionOr<Value> PromiseAnyRejectElementFunction::resolve_element()
// a. Let error be a newly created AggregateError object.
auto* error = AggregateError::create(global_object);
// b. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
// b. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
auto* errors_array = Array::create_from(global_object, m_values.values());
MUST(error->define_property_or_throw(vm.names.errors, { .value = errors_array, .writable = true, .enumerable = false, .configurable = true }));

View file

@ -105,7 +105,7 @@ ThrowCompletionOr<PropertyDescriptor> to_property_descriptor(GlobalObject& globa
// 4. If hasEnumerable is true, then
if (has_enumerable) {
// a. Let enumerable be ! ToBoolean(? Get(Obj, "enumerable")).
// a. Let enumerable be ToBoolean(? Get(Obj, "enumerable")).
auto enumerable = TRY(object.get(vm.names.enumerable)).to_boolean();
// b. Set desc.[[Enumerable]] to enumerable.
@ -117,7 +117,7 @@ ThrowCompletionOr<PropertyDescriptor> to_property_descriptor(GlobalObject& globa
// 6. If hasConfigurable is true, then
if (has_configurable) {
// a. Let configurable be ! ToBoolean(? Get(Obj, "configurable")).
// a. Let configurable be ToBoolean(? Get(Obj, "configurable")).
auto configurable = TRY(object.get(vm.names.configurable)).to_boolean();
// b. Set desc.[[Configurable]] to configurable.
@ -141,7 +141,7 @@ ThrowCompletionOr<PropertyDescriptor> to_property_descriptor(GlobalObject& globa
// 10. If hasWritable is true, then
if (has_writable) {
// a. Let writable be ! ToBoolean(? Get(Obj, "writable")).
// a. Let writable be ToBoolean(? Get(Obj, "writable")).
auto writable = TRY(object.get(vm.names.writable)).to_boolean();
// b. Set desc.[[Writable]] to writable.

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -80,11 +80,11 @@ JS_DEFINE_NATIVE_FUNCTION(ProxyConstructor::revocable)
return js_undefined();
};
// 3. Let revoker be ! CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
// 3. Let revoker be CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
// 4. Set revoker.[[RevocableProxy]] to p.
auto* revoker = NativeFunction::create(global_object, move(revoker_closure), 0, "");
// 5. Let result be ! OrdinaryObjectCreate(%Object.prototype%).
// 5. Let result be OrdinaryObjectCreate(%Object.prototype%).
auto* result = Object::create(global_object, global_object.object_prototype());
// 6. Perform ! CreateDataPropertyOrThrow(result, "proxy", p).

View file

@ -113,7 +113,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_set_prototype_of(Object* prototype
return m_target.internal_set_prototype_of(prototype);
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, V »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, prototype)).to_boolean();
// 8. If booleanTrapResult is false, return false.
@ -162,7 +162,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_is_extensible() const
return m_target.is_extensible();
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target)).to_boolean();
// 8. Let targetResult be ? IsExtensible(target).
@ -200,7 +200,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_prevent_extensions()
return m_target.internal_prevent_extensions();
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target)).to_boolean();
// 8. If booleanTrapResult is true, then
@ -280,7 +280,7 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ProxyObject::internal_get_own_pr
// 12. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
auto result_desc = TRY(to_property_descriptor(global_object, trap_result));
// 13. Call CompletePropertyDescriptor(resultDesc).
// 13. Perform CompletePropertyDescriptor(resultDesc).
result_desc.complete();
// 14. Let valid be IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc).
@ -338,7 +338,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_define_own_property(PropertyKey co
// 7. Let descObj be FromPropertyDescriptor(Desc).
auto descriptor_object = from_property_descriptor(global_object, property_descriptor);
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P, descObj »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), descriptor_object)).to_boolean();
// 9. If booleanTrapResult is false, return false.
@ -418,7 +418,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_has_property(PropertyKey const& pr
return m_target.internal_has_property(property_key);
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean();
// 8. If booleanTrapResult is false, then
@ -544,7 +544,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_ke
return m_target.internal_set(property_key, value, receiver);
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), value, receiver)).to_boolean();
// 8. If booleanTrapResult is false, return false.
@ -600,7 +600,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_delete(PropertyKey const& property
return m_target.internal_delete(property_key);
}
// 7. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
// 7. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, P »)).
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean();
// 8. If booleanTrapResult is false, return false.
@ -782,7 +782,7 @@ ThrowCompletionOr<Value> ProxyObject::internal_call(Value this_argument, MarkedV
return call(global_object, &m_target, this_argument, move(arguments_list));
}
// 7. Let argArray be ! CreateArrayFromList(argumentsList).
// 7. Let argArray be CreateArrayFromList(argumentsList).
auto* arguments_array = Array::create_from(global_object, arguments_list);
// 8. Return ? Call(trap, handler, « target, thisArgument, argArray »).
@ -830,7 +830,7 @@ ThrowCompletionOr<Object*> ProxyObject::internal_construct(MarkedVector<Value> a
return construct(global_object, static_cast<FunctionObject&>(m_target), move(arguments_list), &new_target);
}
// 8. Let argArray be ! CreateArrayFromList(argumentsList).
// 8. Let argArray be CreateArrayFromList(argumentsList).
auto* arguments_array = Array::create_from(global_object, arguments_list);
// 9. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -37,7 +37,7 @@ void Realm::set_global_object(GlobalObject& global_object, Object* this_value)
// 6. Set realmRec.[[GlobalEnv]] to newGlobalEnv.
m_global_environment = global_object.heap().allocate_without_global_object<GlobalEnvironment>(global_object, *this_value);
// 7. Return realmRec.
// 7. Return unused.
}
void Realm::visit_edges(Visitor& visitor)

View file

@ -31,8 +31,10 @@ ThrowCompletionOr<void> Reference::put_value(GlobalObject& global_object, Value
return throw_reference_error(global_object);
// b. Let globalObj be GetGlobalObject().
// c. Return ? Set(globalObj, V.[[ReferencedName]], W, false).
// c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false).
TRY(global_object.set(m_name, value, Object::ShouldThrowExceptions::No));
// Return unused.
return {};
}
@ -54,7 +56,7 @@ ThrowCompletionOr<void> Reference::put_value(GlobalObject& global_object, Value
if (!succeeded && m_strict)
return vm.throw_completion<TypeError>(global_object, ErrorType::ReferenceNullishSetProperty, m_name, m_base_value.to_string_without_side_effects());
// e. Return.
// e. Return unused.
return {};
}
@ -163,7 +165,7 @@ ThrowCompletionOr<bool> Reference::delete_(GlobalObject& global_object)
// 5. If IsPropertyReference(ref) is true, then
if (is_property_reference()) {
// a. Assert: ! IsPrivateReference(ref) is false.
// a. Assert: IsPrivateReference(ref) is false.
VERIFY(!is_private_reference());
// b. If IsSuperReference(ref) is true, throw a ReferenceError exception.
@ -239,7 +241,7 @@ Reference make_private_reference(VM& vm, Value base_value, FlyString const& priv
// 2. Assert: privEnv is not null.
VERIFY(private_environment);
// 3. Let privateName be ! ResolvePrivateIdentifier(privEnv, privateIdentifier).
// 3. Let privateName be ResolvePrivateIdentifier(privEnv, privateIdentifier).
auto private_name = private_environment->resolve_private_identifier(private_identifier);
// 4. Return the Reference Record { [[Base]]: baseValue, [[ReferencedName]]: privateName, [[Strict]]: true, [[ThisValue]]: empty }.

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -274,7 +274,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(GlobalObject& global_object,
MUST(array->create_data_property_or_throw(0, js_string(vm, match.view.u16_view())));
// 29. If R contains any GroupName, then
// a. Let groups be ! OrdinaryObjectCreate(null).
// a. Let groups be OrdinaryObjectCreate(null).
// b. Let hasGroups be true.
// 30. Else,
// a. Let groups be undefined.
@ -395,7 +395,7 @@ size_t advance_string_index(Utf16View const& string, size_t index, bool unicode)
if (index + 1 >= string.length_in_code_units())
return index + 1;
// 5. Let cp be ! CodePointAt(S, index).
// 5. Let cp be CodePointAt(S, index).
auto code_point = code_point_at(string, index);
// 6. Return index + cp.[[CodeUnitCount]].
@ -458,17 +458,17 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flags)
// 4. Let hasIndices be ToBoolean(? Get(R, "hasIndices")).
// 5. If hasIndices is true, append the code unit 0x0064 (LATIN SMALL LETTER D) as the last code unit of result.
// 6. Let global be ! ToBoolean(? Get(R, "global")).
// 6. Let global be ToBoolean(? Get(R, "global")).
// 7. If global is true, append the code unit 0x0067 (LATIN SMALL LETTER G) as the last code unit of result.
// 8. Let ignoreCase be ! ToBoolean(? Get(R, "ignoreCase")).
// 8. Let ignoreCase be ToBoolean(? Get(R, "ignoreCase")).
// 9. If ignoreCase is true, append the code unit 0x0069 (LATIN SMALL LETTER I) as the last code unit of result.
// 10. Let multiline be ! ToBoolean(? Get(R, "multiline")).
// 10. Let multiline be ToBoolean(? Get(R, "multiline")).
// 11. If multiline is true, append the code unit 0x006D (LATIN SMALL LETTER M) as the last code unit of result.
// 12. Let dotAll be ! ToBoolean(? Get(R, "dotAll")).
// 12. Let dotAll be ToBoolean(? Get(R, "dotAll")).
// 13. If dotAll is true, append the code unit 0x0073 (LATIN SMALL LETTER S) as the last code unit of result.
// 14. Let unicode be ! ToBoolean(? Get(R, "unicode")).
// 14. Let unicode be ToBoolean(? Get(R, "unicode")).
// 15. If unicode is true, append the code unit 0x0075 (LATIN SMALL LETTER U) as the last code unit of result.
// 16. Let sticky be ! ToBoolean(? Get(R, "sticky")).
// 16. Let sticky be ToBoolean(? Get(R, "sticky")).
// 17. If sticky is true, append the code unit 0x0079 (LATIN SMALL LETTER Y) as the last code unit of result.
#define __JS_ENUMERATE(flagName, flag_name, flag_char) \
auto flag_##flag_name = TRY(regexp_object->get(vm.names.flagName)); \
@ -491,7 +491,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
// 3. Let S be ? ToString(string).
auto string = TRY(vm.argument(0).to_utf16_string(global_object));
// 4. Let global be ! ToBoolean(? Get(rx, "global")).
// 4. Let global be ToBoolean(? Get(rx, "global")).
bool global = TRY(regexp_object->get(vm.names.global)).to_boolean();
// 5. If global is false, then
@ -503,7 +503,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
// 6. Else,
// a. Assert: global is true.
// b. Let fullUnicode be ! ToBoolean(? Get(rx, "unicode")).
// b. Let fullUnicode be ToBoolean(? Get(rx, "unicode")).
bool full_unicode = TRY(regexp_object->get(vm.names.unicode)).to_boolean();
// c. Perform ? Set(rx, "lastIndex", +0𝔽, true).
@ -587,7 +587,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match_all)
// 8. Perform ? Set(matcher, "lastIndex", lastIndex, true).
TRY(matcher->set(vm.names.lastIndex, Value(last_index), Object::ShouldThrowExceptions::Yes));
// 13. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode).
// 13. Return CreateRegExpStringIterator(matcher, S, global, fullUnicode).
return RegExpStringIterator::create(global_object, *matcher, move(string), global, full_unicode);
}
@ -614,13 +614,13 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
replace_value = js_string(vm, move(replace_string));
}
// 7. Let global be ! ToBoolean(? Get(rx, "global")).
// 7. Let global be ToBoolean(? Get(rx, "global")).
bool global = TRY(regexp_object->get(vm.names.global)).to_boolean();
bool full_unicode = false;
// 8. If global is true, then
if (global) {
// a. Let fullUnicode be ! ToBoolean(? Get(rx, "unicode")).
// a. Let fullUnicode be ToBoolean(? Get(rx, "unicode")).
full_unicode = TRY(regexp_object->get(vm.names.unicode)).to_boolean();
// b. Perform ? Set(rx, "lastIndex", +0𝔽, true).

View file

@ -76,7 +76,7 @@ ThrowCompletionOr<void> copy_name_and_length(GlobalObject& global_object, Functi
}
}
// 5. Perform ! SetFunctionLength(F, L).
// 5. Perform SetFunctionLength(F, L).
function.set_function_length(length);
// 6. Let targetName be ? Get(Target, "name").
@ -86,7 +86,7 @@ ThrowCompletionOr<void> copy_name_and_length(GlobalObject& global_object, Functi
if (!target_name.is_string())
target_name = js_string(vm, String::empty());
// 8. Perform ! SetFunctionName(F, targetName, prefix).
// 8. Perform SetFunctionName(F, targetName, prefix).
function.set_function_name({ target_name.as_string().string() }, move(prefix));
return {};
@ -102,7 +102,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
// 2. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
// a. Let script be ParseText(! StringToCodePoints(sourceText), Script).
// a. Let script be ParseText(StringToCodePoints(sourceText), Script).
auto parser = Parser(Lexer(source_text));
auto program = parser.parse_program();
@ -165,7 +165,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
// 15. Push evalContext onto the execution context stack; evalContext is now the running execution context.
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
// 16. Let result be EvalDeclarationInstantiation(body, varEnv, lexEnv, null, strictEval).
// 16. Let result be Completion(EvalDeclarationInstantiation(body, varEnv, lexEnv, null, strictEval)).
auto eval_result = eval_declaration_instantiation(vm, eval_realm.global_object(), program, variable_environment, lexical_environment, nullptr, strict_eval);
Completion result;
@ -217,7 +217,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
// 5. Push evalContext onto the execution context stack; evalContext is now the running execution context.
TRY(vm.push_execution_context(eval_context, eval_realm.global_object()));
// 6. Perform ! HostImportModuleDynamically(null, specifierString, innerCapability).
// 6. Perform HostImportModuleDynamically(null, specifierString, innerCapability).
vm.host_import_module_dynamically(Empty {}, ModuleRequest { move(specifier_string) }, inner_capability);
// 7. Suspend evalContext and remove it from the execution context stack.
@ -258,7 +258,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
return get_wrapped_value(global_object, *realm, value);
};
// 10. Let onFulfilled be ! CreateBuiltinFunction(steps, 1, "", « [[ExportNameString]] », callerRealm).
// 10. Let onFulfilled be CreateBuiltinFunction(steps, 1, "", « [[ExportNameString]] », callerRealm).
// 11. Set onFulfilled.[[ExportNameString]] to exportNameString.
auto* on_fulfilled = NativeFunction::create(global_object, move(steps), 1, "", &caller_realm);
@ -271,7 +271,7 @@ ThrowCompletionOr<Value> shadow_realm_import_value(GlobalObject& global_object,
return vm.template throw_completion<TypeError>(global_object, vm.argument(0).as_object().get_without_side_effects(vm.names.message).as_string().string());
});
// 13. Return ! PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability).
// 13. Return PerformPromiseThen(innerCapability.[[Promise]], onFulfilled, callerRealm.[[Intrinsics]].[[%ThrowTypeError%]], promiseCapability).
return verify_cast<Promise>(inner_capability.promise)->perform_then(on_fulfilled, throw_type_error, promise_capability);
}

View file

@ -50,7 +50,7 @@ static Optional<PropertyDescriptor> string_get_own_property(StringObject const&
if (property_key.is_symbol())
return {};
// 2. Let index be ! CanonicalNumericIndexString(P).
// 2. Let index be CanonicalNumericIndexString(P).
auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
// 3. If index is undefined, return undefined.
@ -94,7 +94,7 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> StringObject::internal_get_own_p
if (descriptor.has_value())
return descriptor;
// 3. Return ! StringGetOwnProperty(S, P).
// 3. Return StringGetOwnProperty(S, P).
return string_get_own_property(*this, property_key);
}
@ -103,7 +103,7 @@ ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey c
{
VERIFY(property_key.is_valid());
// 1. Let stringDesc be ! StringGetOwnProperty(S, P).
// 1. Let stringDesc be StringGetOwnProperty(S, P).
auto string_descriptor = string_get_own_property(*this, property_key);
// 2. If stringDesc is not undefined, then
@ -111,7 +111,7 @@ ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey c
// a. Let extensible be S.[[Extensible]].
auto extensible = m_is_extensible;
// b. Return ! IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc).
// b. Return IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc).
return is_compatible_property_descriptor(extensible, property_descriptor, string_descriptor);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -354,7 +354,7 @@ static ThrowCompletionOr<String> transform_case(GlobalObject& global_object, Str
if (!locale.has_value())
locale = "und"sv;
// 8. Let codePoints be ! StringToCodePoints(S).
// 8. Let codePoints be StringToCodePoints(S).
String new_code_points;
@ -374,7 +374,7 @@ static ThrowCompletionOr<String> transform_case(GlobalObject& global_object, Str
VERIFY_NOT_REACHED();
}
// 11. Return ! CodePointsToString(newCodePoints).
// 11. Return CodePointsToString(newCodePoints).
return new_code_points;
}

View file

@ -80,7 +80,7 @@ inline bool is_valid_integer_index(TypedArrayBase const& typed_array, CanonicalI
if (typed_array.viewed_array_buffer()->is_detached())
return false;
// 2. If ! IsIntegralNumber(index) is false, return false.
// 2. If IsIntegralNumber(index) is false, return false.
// 3. If index is -0𝔽, return false.
if (!property_index.is_index())
return false;
@ -185,11 +185,11 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) {
// i. Let value be ! IntegerIndexedElementGet(O, numericIndex).
// i. Let value be IntegerIndexedElementGet(O, numericIndex).
auto value = integer_indexed_element_get<T>(*this, numeric_index);
// ii. If value is undefined, return undefined.
@ -222,9 +222,9 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, return ! IsValidIntegerIndex(O, numericIndex).
// b. If numericIndex is not undefined, return IsValidIntegerIndex(O, numericIndex).
if (!numeric_index.is_undefined())
return is_valid_integer_index(*this, numeric_index);
}
@ -245,11 +245,11 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) {
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
// i. If IsValidIntegerIndex(O, numericIndex) is false, return false.
if (!is_valid_integer_index(*this, numeric_index))
return false;
@ -261,7 +261,7 @@ public:
if (property_descriptor.enumerable.has_value() && !*property_descriptor.enumerable)
return false;
// iv. If ! IsAccessorDescriptor(Desc) is true, return false.
// iv. If IsAccessorDescriptor(Desc) is true, return false.
if (property_descriptor.is_accessor_descriptor())
return false;
@ -295,11 +295,11 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) {
// i. Return ! IntegerIndexedElementGet(O, numericIndex).
// i. Return IntegerIndexedElementGet(O, numericIndex).
return integer_indexed_element_get<T>(*this, numeric_index);
}
}
@ -322,7 +322,7 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) {
@ -350,11 +350,11 @@ public:
// 1. If Type(P) is String, then
// NOTE: This includes an implementation-defined optimization, see note above!
if (property_key.is_string() || property_key.is_number()) {
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
// a. Let numericIndex be CanonicalNumericIndexString(P).
auto numeric_index = canonical_numeric_index_string(property_key, CanonicalIndexMode::DetectNumericRoundtrip);
// b. If numericIndex is not undefined, then
if (!numeric_index.is_undefined()) {
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
// i. If IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
if (!is_valid_integer_index(*this, numeric_index))
return true;
return false;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -119,11 +119,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayConstructor::of)
MarkedVector<Value> arguments(vm.heap());
arguments.append(Value(length));
auto new_object = TRY(typed_array_create(global_object, constructor.as_function(), move(arguments)));
for (size_t k = 0; k < length; ++k) {
auto success = TRY(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes));
if (!success)
return vm.throw_completion<TypeError>(global_object, ErrorType::TypedArrayFailedSettingIndex, k);
}
for (size_t k = 0; k < length; ++k)
TRY(new_object->set(k, vm.argument(k), Object::ShouldThrowExceptions::Yes));
return new_object;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2021-2022, Idan Horowitz <idan.horowitz@serenityos.org>
*
@ -1383,7 +1383,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::filter)
// b. Let kValue be ! Get(O, Pk).
auto value = MUST(typed_array->get(i));
// c. Let selected be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
// c. Let selected be ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
auto callback_result = TRY(call(global_object, *callback_function, this_value, value, Value((i32)i), typed_array)).to_boolean();
// d. If selected is true, then

View file

@ -282,13 +282,13 @@ ThrowCompletionOr<void> VM::binding_initialization(NonnullRefPtr<BindingPattern>
// 1. Perform ? RequireObjectCoercible(value).
TRY(require_object_coercible(global_object, value));
// 2. Return the result of performing BindingInitialization of ObjectBindingPattern with arguments value and environment.
// 2. Return ? BindingInitialization of ObjectBindingPattern with arguments value and environment.
// BindingInitialization of ObjectBindingPattern
// 1. Perform ? PropertyBindingInitialization of BindingPropertyList with arguments value and environment.
TRY(property_binding_initialization(*target, value, environment, global_object));
// 2. Return NormalCompletion(empty).
// 2. Return unused.
return {};
}
// BindingPattern : ArrayBindingPattern
@ -296,7 +296,7 @@ ThrowCompletionOr<void> VM::binding_initialization(NonnullRefPtr<BindingPattern>
// 1. Let iteratorRecord be ? GetIterator(value).
auto iterator_record = TRY(get_iterator(global_object, value));
// 2. Let result be IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecord and environment.
// 2. Let result be Completion(IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecord and environment).
auto result = iterator_binding_initialization(*target, iterator_record, environment, global_object);
// 3. If iteratorRecord.[[Done]] is false, return ? IteratorClose(iteratorRecord, result).
@ -308,7 +308,7 @@ ThrowCompletionOr<void> VM::binding_initialization(NonnullRefPtr<BindingPattern>
return completion.release_error();
}
// 4. Return result.
// 4. Return ? result.
return result;
}
}
@ -439,7 +439,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
// a. If iteratorRecord.[[Done]] is false, then
if (!iterator_record.done) {
// i. Let next be IteratorStep(iteratorRecord).
// i. Let next be Completion(IteratorStep(iteratorRecord)).
next = iterator_step(global_object, iterator_record);
// ii. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -460,7 +460,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
break;
}
// c. Let nextValue be IteratorValue(next).
// c. Let nextValue be Completion(IteratorValue(next)).
auto next_value = iterator_value(global_object, *next.value());
// d. If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -485,7 +485,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
// 2. If iteratorRecord.[[Done]] is false, then
if (!iterator_record.done) {
// a. Let next be IteratorStep(iteratorRecord).
// a. Let next be Completion(IteratorStep(iteratorRecord)).
auto next = iterator_step(global_object, iterator_record);
// b. If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -501,7 +501,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
}
// e. Else,
else {
// i. Set v to IteratorValue(next).
// i. Set v to Completion(IteratorValue(next)).
auto value_or_error = iterator_value(global_object, *next.value());
// ii. If v is an abrupt completion, set iteratorRecord.[[Done]] to true.
@ -980,7 +980,7 @@ void VM::import_module_dynamically(ScriptOrModule referencing_script_or_module,
}
}
// It must return NormalCompletion(undefined).
// It must return unused.
// Note: Just return void always since the resulting value cannot be accessed by user code.
}
@ -1000,7 +1000,7 @@ void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, Modu
// c. Assert: Evaluate has already been invoked on moduleRecord and successfully completed.
// Note: If HostResolveImportedModule returns a module evaluate will have been called on it.
// d. Let namespace be GetModuleNamespace(moduleRecord).
// d. Let namespace be Completion(GetModuleNamespace(moduleRecord)).
auto namespace_ = module_record->get_module_namespace(vm);
// e. If namespace is an abrupt completion, then
@ -1013,11 +1013,12 @@ void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, Modu
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace.[[Value]] »).
MUST(call(global_object, resolve_function.cell(), js_undefined(), namespace_.release_value()));
}
// g. Return undefined.
// g. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
return js_undefined();
};
// 2. Let onFulfilled be ! CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
// 2. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
auto* on_fulfilled = NativeFunction::create(current_realm()->global_object(), move(fulfilled_closure), 0, "");
// 3. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures promiseCapability and performs the following steps when called:
@ -1025,15 +1026,19 @@ void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, Modu
auto error = vm.argument(0);
// a. Perform ! Call(promiseCapability.[[Reject]], undefined, « error »).
MUST(call(global_object, rejected_function.cell(), js_undefined(), error));
// b. Return undefined.
// b. Return unused.
// NOTE: We don't support returning an empty/optional/unused value here.
return js_undefined();
};
// 4. Let onRejected be ! CreateBuiltinFunction(rejectedClosure, 0, "", « »).
// 4. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »).
auto* on_rejected = NativeFunction::create(current_realm()->global_object(), move(rejected_closure), 0, "");
// 5. Perform ! PerformPromiseThen(innerPromise, onFulfilled, onRejected).
// 5. Perform PerformPromiseThen(innerPromise, onFulfilled, onRejected).
inner_promise->perform_then(on_fulfilled, on_rejected, {});
// 6. Return unused.
}
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -523,7 +523,7 @@ ThrowCompletionOr<BigInt*> Value::to_bigint(GlobalObject& global_object) const
case Type::Double:
return vm.throw_completion<TypeError>(global_object, ErrorType::Convert, "number", "BigInt");
case Type::String: {
// 1. Let n be ! StringToBigInt(prim).
// 1. Let n be StringToBigInt(prim).
auto bigint = primitive.string_to_bigint(global_object);
// 2. If n is undefined, throw a SyntaxError exception.
@ -590,7 +590,7 @@ Optional<BigInt*> Value::string_to_bigint(GlobalObject& global_object) const
{
VERIFY(is_string());
// 1. Let text be ! StringToCodePoints(str).
// 1. Let text be StringToCodePoints(str).
auto text = as_string().string().view().trim_whitespace();
// 2. Let literal be ParseText(text, StringIntegerLiteral).
@ -1429,46 +1429,46 @@ ThrowCompletionOr<bool> is_loosely_equal(GlobalObject& global_object, Value lhs,
// == End of B.3.6.2 ==
// 5. If Type(x) is Number and Type(y) is String, return IsLooselyEqual(x, ! ToNumber(y)).
// 5. If Type(x) is Number and Type(y) is String, return ! IsLooselyEqual(x, ! ToNumber(y)).
if (lhs.is_number() && rhs.is_string())
return is_loosely_equal(global_object, lhs, MUST(rhs.to_number(global_object)));
// 6. If Type(x) is String and Type(y) is Number, return IsLooselyEqual(! ToNumber(x), y).
// 6. If Type(x) is String and Type(y) is Number, return ! IsLooselyEqual(! ToNumber(x), y).
if (lhs.is_string() && rhs.is_number())
return is_loosely_equal(global_object, MUST(lhs.to_number(global_object)), rhs);
// 7. If Type(x) is BigInt and Type(y) is String, then
if (lhs.is_bigint() && rhs.is_string()) {
// a. Let n be ! StringToBigInt(y).
// a. Let n be StringToBigInt(y).
auto bigint = rhs.string_to_bigint(global_object);
// b. If n is undefined, return false.
if (!bigint.has_value())
return false;
// c. Return IsLooselyEqual(x, n).
// c. Return ! IsLooselyEqual(x, n).
return is_loosely_equal(global_object, lhs, *bigint);
}
// 8. If Type(x) is String and Type(y) is BigInt, return IsLooselyEqual(y, x).
// 8. If Type(x) is String and Type(y) is BigInt, return ! IsLooselyEqual(y, x).
if (lhs.is_string() && rhs.is_bigint())
return is_loosely_equal(global_object, rhs, lhs);
// 9. If Type(x) is Boolean, return IsLooselyEqual(! ToNumber(x), y).
// 9. If Type(x) is Boolean, return ! IsLooselyEqual(! ToNumber(x), y).
if (lhs.is_boolean())
return is_loosely_equal(global_object, MUST(lhs.to_number(global_object)), rhs);
// 10. If Type(y) is Boolean, return IsLooselyEqual(x, ! ToNumber(y)).
// 10. If Type(y) is Boolean, return ! IsLooselyEqual(x, ! ToNumber(y)).
if (rhs.is_boolean())
return is_loosely_equal(global_object, lhs, MUST(rhs.to_number(global_object)));
// 11. If Type(x) is either String, Number, BigInt, or Symbol and Type(y) is Object, return IsLooselyEqual(x, ? ToPrimitive(y)).
// 11. If Type(x) is either String, Number, BigInt, or Symbol and Type(y) is Object, return ! IsLooselyEqual(x, ? ToPrimitive(y)).
if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object()) {
auto rhs_primitive = TRY(rhs.to_primitive(global_object));
return is_loosely_equal(global_object, lhs, rhs_primitive);
}
// 12. If Type(x) is Object and Type(y) is either String, Number, BigInt, or Symbol, return IsLooselyEqual(? ToPrimitive(x), y).
// 12. If Type(x) is Object and Type(y) is either String, Number, BigInt, or Symbol, return ! IsLooselyEqual(? ToPrimitive(x), y).
if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || rhs.is_bigint() || rhs.is_symbol())) {
auto lhs_primitive = TRY(lhs.to_primitive(global_object));
return is_loosely_equal(global_object, lhs_primitive, rhs);

View file

@ -16,7 +16,7 @@ ThrowCompletionOr<WrappedFunction*> WrappedFunction::create(GlobalObject& global
auto& vm = global_object.vm();
// 1. Let internalSlotsList be the internal slots listed in Table 2, plus [[Prototype]] and [[Extensible]].
// 2. Let wrapped be ! MakeBasicObject(internalSlotsList).
// 2. Let wrapped be MakeBasicObject(internalSlotsList).
// 3. Set wrapped.[[Prototype]] to callerRealm.[[Intrinsics]].[[%Function.prototype%]].
// 4. Set wrapped.[[Call]] as described in 2.1.
// 5. Set wrapped.[[WrappedTargetFunction]] to Target.

View file

@ -303,7 +303,7 @@ ThrowCompletionOr<Vector<FlyString>> SourceTextModule::get_exported_names(VM& vm
}
// 16.2.1.6.4 InitializeEnvironment ( ), https://tc39.es/ecma262/#sec-source-text-module-record-initialize-environment
Completion SourceTextModule::initialize_environment(VM& vm)
ThrowCompletionOr<void> SourceTextModule::initialize_environment(VM& vm)
{
// 1. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
for (auto& entry : m_indirect_export_entries) {
@ -347,8 +347,8 @@ Completion SourceTextModule::initialize_environment(VM& vm)
// ii. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
MUST(environment->create_immutable_binding(global_object, import_entry.local_name, true));
// iii. Call env.InitializeBinding(in.[[LocalName]], namespace).
environment->initialize_binding(global_object, import_entry.local_name, namespace_);
// iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
MUST(environment->initialize_binding(global_object, import_entry.local_name, namespace_));
}
// d. Else,
else {
@ -367,12 +367,12 @@ Completion SourceTextModule::initialize_environment(VM& vm)
// 2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
MUST(environment->create_immutable_binding(global_object, import_entry.local_name, true));
// 3. Call env.InitializeBinding(in.[[LocalName]], namespace).
// 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
MUST(environment->initialize_binding(global_object, import_entry.local_name, namespace_));
}
// iv. Else,
else {
// 1. Call env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
// 1. Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
MUST(environment->create_import_binding(import_entry.local_name, resolution.module, resolution.export_name));
}
}
@ -422,7 +422,7 @@ Completion SourceTextModule::initialize_environment(VM& vm)
// 1. Perform ! env.CreateMutableBinding(dn, false).
MUST(environment->create_mutable_binding(global_object, name, false));
// 2. Call env.InitializeBinding(dn, undefined).
// 2. Perform ! env.InitializeBinding(dn, undefined).
MUST(environment->initialize_binding(global_object, name, js_undefined()));
// 3. Append dn to declaredVarNames.
@ -459,8 +459,8 @@ Completion SourceTextModule::initialize_environment(VM& vm)
// 1. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
auto* function = ECMAScriptFunctionObject::create(global_object, function_declaration.name(), function_declaration.source_text(), function_declaration.body(), function_declaration.parameters(), function_declaration.function_length(), environment, private_environment, function_declaration.kind(), function_declaration.is_strict_mode(), function_declaration.might_need_arguments_object(), function_declaration.contains_direct_call_to_eval());
// 2. Call env.InitializeBinding(dn, fo).
environment->initialize_binding(global_object, name, function);
// 2. Perform ! env.InitializeBinding(dn, fo).
MUST(environment->initialize_binding(global_object, name, function));
}
});
});
@ -488,8 +488,8 @@ Completion SourceTextModule::initialize_environment(VM& vm)
// 25. Remove moduleContext from the execution context stack.
vm.pop_execution_context();
// 26. Return NormalCompletion(empty).
return normal_completion({});
// 26. Return unused.
return {};
}
// 16.2.1.6.3 ResolveExport ( exportName [ , resolveSet ] ), https://tc39.es/ecma262/#sec-resolveexport
@ -555,7 +555,7 @@ ThrowCompletionOr<ResolvedBinding> SourceTextModule::resolve_export(VM& vm, FlyS
// 1. Assert: module imports a specific binding for this export.
// FIXME: What does this mean? / How do we check this
// 2. Return importedModule.ResolveExport(e.[[ImportName]], resolveSet).
// 2. Return ? importedModule.ResolveExport(e.[[ImportName]], resolveSet).
return imported_module->resolve_export(vm, entry.local_or_import_name, resolve_set);
}
}
@ -622,7 +622,7 @@ ThrowCompletionOr<ResolvedBinding> SourceTextModule::resolve_export(VM& vm, FlyS
}
// 16.2.1.6.5 ExecuteModule ( [ capability ] ), https://tc39.es/ecma262/#sec-source-text-module-record-execute-module
Completion SourceTextModule::execute_module(VM& vm, Optional<PromiseCapability> capability)
ThrowCompletionOr<void> SourceTextModule::execute_module(VM& vm, Optional<PromiseCapability> capability)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] SourceTextModule::execute_module({}, capability has value: {})", filename(), capability.has_value());
@ -668,26 +668,23 @@ Completion SourceTextModule::execute_module(VM& vm, Optional<PromiseCapability>
// e. Resume the context that is now on the top of the execution context stack as the running execution context.
// FIXME: We don't have resume yet.
// f. Return Completion(result).
if (result.is_error())
// f. If result is an abrupt completion, then
if (result.is_error()) {
// i. Return ? result.
return result;
// 16.2.1.11 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-module-semantics-runtime-semantics-evaluation
// -> Replace any empty value with undefined.
result = result.update_empty(js_undefined());
return *result.value();
}
}
// 10. Else,
else {
// a. Assert: capability is a PromiseCapability Record.
VERIFY(capability.has_value());
// a. Assert: capability is a PromiseCapability Record.
VERIFY(capability.has_value());
// b. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
async_block_start(vm, m_ecmascript_code, capability.value(), module_context);
}
// b. Perform ! AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
async_block_start(vm, m_ecmascript_code, capability.value(), module_context);
// c. Return NormalCompletion(empty).
return normal_completion({});
// 11. Return unused.
return {};
}
}

View file

@ -40,8 +40,8 @@ public:
}
protected:
virtual Completion initialize_environment(VM& vm) override;
virtual Completion execute_module(VM& vm, Optional<PromiseCapability> capability) override;
virtual ThrowCompletionOr<void> initialize_environment(VM& vm) override;
virtual ThrowCompletionOr<void> execute_module(VM& vm, Optional<PromiseCapability> capability) override;
private:
SourceTextModule(Realm&, StringView filename, bool has_top_level_await, NonnullRefPtr<Program> body, Vector<ModuleRequest> requested_modules,

View file

@ -67,8 +67,7 @@ ThrowCompletionOr<void> SyntheticModule::link(VM& vm)
environment->initialize_binding(global_object, export_name, js_undefined());
}
// 6. Return undefined.
// Note: This return value is never visible to the outside so we use void.
// 6. Return unused.
return {};
}