mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
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:
parent
15f32379bb
commit
9f3f3b0864
Notes:
sideshowbarker
2024-07-17 11:22:30 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/9f3f3b0864 Pull-request: https://github.com/SerenityOS/serenity/pull/13887 Reviewed-by: https://github.com/IdanHo ✅
88 changed files with 792 additions and 735 deletions
|
@ -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&)
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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). */ \
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]]).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); });
|
||||
}
|
||||
|
||||
|
|
|
@ -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]]).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]]).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]]).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -87,7 +87,7 @@ ThrowCompletionOr<void> ModuleEnvironment::create_import_binding(FlyString name,
|
|||
module,
|
||||
move(binding_name) });
|
||||
|
||||
// 4. Return NormalCompletion(empty).
|
||||
// 4. Return unused.
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -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 »).
|
||||
|
|
|
@ -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) \
|
||||
({ \
|
||||
|
|
|
@ -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 }));
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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 »).
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 }.
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue