[parser] Iterate declarations to set initializer positions
This allows us to remove the PatternRewriter. Change-Id: I54ec74ed3bd31e76e38c69f9b0b2a78f8620cd89 Reviewed-on: https://chromium-review.googlesource.com/c/1429863 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59028}
This commit is contained in:
parent
172277f4bd
commit
0b69b05a08
1
BUILD.gn
1
BUILD.gn
@ -2326,7 +2326,6 @@ v8_source_set("v8_base") {
|
||||
"src/parsing/parser.h",
|
||||
"src/parsing/parsing.cc",
|
||||
"src/parsing/parsing.h",
|
||||
"src/parsing/pattern-rewriter.cc",
|
||||
"src/parsing/preparse-data-impl.h",
|
||||
"src/parsing/preparse-data.cc",
|
||||
"src/parsing/preparse-data.h",
|
||||
|
@ -678,6 +678,11 @@ class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
|
||||
MessageTemplate::kParamDupe);
|
||||
}
|
||||
}
|
||||
|
||||
int initializer_position = this->parser()->end_position();
|
||||
for (auto declaration : *result->declarations()) {
|
||||
declaration->var()->set_initializer_position(initializer_position);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -480,16 +480,12 @@ class ParserBase {
|
||||
|
||||
struct DeclarationParsingResult {
|
||||
struct Declaration {
|
||||
Declaration(ExpressionT pattern, int initializer_position,
|
||||
ExpressionT initializer)
|
||||
: pattern(pattern),
|
||||
initializer_position(initializer_position),
|
||||
initializer(initializer) {}
|
||||
Declaration(ExpressionT pattern, ExpressionT initializer)
|
||||
: pattern(pattern), initializer(initializer) {}
|
||||
|
||||
ExpressionT pattern;
|
||||
int initializer_position;
|
||||
int value_beg_position = kNoSourcePosition;
|
||||
ExpressionT initializer;
|
||||
int value_beg_pos = kNoSourcePosition;
|
||||
};
|
||||
|
||||
DeclarationParsingResult()
|
||||
@ -3363,6 +3359,7 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
|
||||
// BindingElement[?Yield, ?GeneratorParameter]
|
||||
FuncNameInferrerState fni_state(&fni_);
|
||||
int pos = peek_position();
|
||||
auto declaration_it = scope()->declarations()->end();
|
||||
ExpressionT pattern = ParseBindingPattern();
|
||||
if (impl()->IsIdentifier(pattern)) {
|
||||
ClassifyParameter(impl()->AsIdentifier(pattern), pos, end_position());
|
||||
@ -3379,11 +3376,17 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
AcceptINScope scope(this, true);
|
||||
AcceptINScope accept_in_scope(this, true);
|
||||
initializer = ParseAssignmentExpression();
|
||||
impl()->SetFunctionNameFromIdentifierRef(initializer, pattern);
|
||||
}
|
||||
|
||||
auto declaration_end = scope()->declarations()->end();
|
||||
int initializer_end = end_position();
|
||||
for (; declaration_it != declaration_end; ++declaration_it) {
|
||||
declaration_it->var()->set_initializer_position(initializer_end);
|
||||
}
|
||||
|
||||
impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),
|
||||
parameters->has_rest);
|
||||
}
|
||||
@ -3473,6 +3476,11 @@ void ParserBase<Impl>::ParseVariableDeclarations(
|
||||
|
||||
VariableDeclarationParsingScope declaration(
|
||||
impl(), parsing_result->descriptor.mode, names);
|
||||
Scope* target_scope = IsLexicalVariableMode(parsing_result->descriptor.mode)
|
||||
? scope()
|
||||
: scope()->GetDeclarationScope();
|
||||
|
||||
auto declaration_it = target_scope->declarations()->end();
|
||||
|
||||
int bindings_start = peek_position();
|
||||
do {
|
||||
@ -3485,12 +3493,10 @@ void ParserBase<Impl>::ParseVariableDeclarations(
|
||||
Scanner::Location variable_loc = scanner()->location();
|
||||
|
||||
ExpressionT value = impl()->NullExpression();
|
||||
int initializer_position = kNoSourcePosition;
|
||||
int value_beg_position = kNoSourcePosition;
|
||||
int value_beg_pos = kNoSourcePosition;
|
||||
if (Check(Token::ASSIGN)) {
|
||||
value_beg_position = peek_position();
|
||||
|
||||
{
|
||||
value_beg_pos = peek_position();
|
||||
AcceptINScope scope(this, var_context != kForStatement);
|
||||
value = ParseAssignmentExpression();
|
||||
}
|
||||
@ -3510,9 +3516,6 @@ void ParserBase<Impl>::ParseVariableDeclarations(
|
||||
}
|
||||
|
||||
impl()->SetFunctionNameFromIdentifierRef(value, pattern);
|
||||
|
||||
// End position of the initializer is after the assignment expression.
|
||||
initializer_position = end_position();
|
||||
} else {
|
||||
if (var_context != kForStatement || !PeekInOrOf()) {
|
||||
// ES6 'const' and binding patterns require initializers.
|
||||
@ -3529,14 +3532,16 @@ void ParserBase<Impl>::ParseVariableDeclarations(
|
||||
value = factory()->NewUndefinedLiteral(position());
|
||||
}
|
||||
}
|
||||
|
||||
// End position of the initializer is after the variable.
|
||||
initializer_position = position();
|
||||
}
|
||||
|
||||
typename DeclarationParsingResult::Declaration decl(
|
||||
pattern, initializer_position, value);
|
||||
decl.value_beg_position = value_beg_position;
|
||||
int initializer_position = end_position();
|
||||
auto declaration_end = target_scope->declarations()->end();
|
||||
for (; declaration_it != declaration_end; ++declaration_it) {
|
||||
declaration_it->var()->set_initializer_position(initializer_position);
|
||||
}
|
||||
|
||||
typename DeclarationParsingResult::Declaration decl(pattern, value);
|
||||
decl.value_beg_pos = value_beg_pos;
|
||||
parsing_result->declarations.push_back(decl);
|
||||
} while (Check(Token::COMMA));
|
||||
|
||||
@ -5179,9 +5184,20 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseTryStatement() {
|
||||
} else {
|
||||
catch_info.variable = catch_info.scope->DeclareCatchVariableName(
|
||||
ast_value_factory()->dot_catch_string());
|
||||
|
||||
auto declaration_it = scope()->declarations()->end();
|
||||
|
||||
VariableDeclarationParsingScope destructuring(
|
||||
impl(), VariableMode::kLet, nullptr);
|
||||
catch_info.pattern = ParseBindingPattern();
|
||||
|
||||
int initializer_position = end_position();
|
||||
auto declaration_end = scope()->declarations()->end();
|
||||
for (; declaration_it != declaration_end; ++declaration_it) {
|
||||
declaration_it->var()->set_initializer_position(
|
||||
initializer_position);
|
||||
}
|
||||
|
||||
RETURN_IF_PARSE_ERROR;
|
||||
catch_statements.Add(impl()->RewriteCatchPattern(&catch_info));
|
||||
}
|
||||
|
@ -1413,6 +1413,7 @@ Statement* Parser::BuildInitializationBlock(
|
||||
DeclarationParsingResult* parsing_result) {
|
||||
ScopedPtrList<Statement> statements(pointer_buffer());
|
||||
for (const auto& declaration : parsing_result->declarations) {
|
||||
if (!declaration.initializer) continue;
|
||||
InitializeVariables(&statements, parsing_result->descriptor.kind,
|
||||
&declaration);
|
||||
}
|
||||
@ -1594,15 +1595,27 @@ Statement* Parser::RewriteSwitchStatement(SwitchStatement* switch_statement,
|
||||
return switch_block;
|
||||
}
|
||||
|
||||
void Parser::InitializeVariables(
|
||||
ScopedPtrList<Statement>* statements, VariableKind kind,
|
||||
const DeclarationParsingResult::Declaration* declaration) {
|
||||
if (has_error()) return;
|
||||
|
||||
DCHECK_NOT_NULL(declaration->initializer);
|
||||
|
||||
int pos = declaration->value_beg_pos;
|
||||
if (pos == kNoSourcePosition) {
|
||||
pos = declaration->initializer->position();
|
||||
}
|
||||
Assignment* assignment = factory()->NewAssignment(
|
||||
Token::INIT, declaration->pattern, declaration->initializer, pos);
|
||||
statements->Add(factory()->NewExpressionStatement(assignment, pos));
|
||||
}
|
||||
|
||||
Block* Parser::RewriteCatchPattern(CatchInfo* catch_info) {
|
||||
DCHECK_NOT_NULL(catch_info->pattern);
|
||||
|
||||
// Initializer position for variables declared by the pattern.
|
||||
const int initializer_position = position();
|
||||
|
||||
DeclarationParsingResult::Declaration decl(
|
||||
catch_info->pattern, initializer_position,
|
||||
factory()->NewVariableProxy(catch_info->variable));
|
||||
catch_info->pattern, factory()->NewVariableProxy(catch_info->variable));
|
||||
|
||||
ScopedPtrList<Statement> init_statements(pointer_buffer());
|
||||
InitializeVariables(&init_statements, NORMAL_VARIABLE, &decl);
|
||||
@ -1797,7 +1810,7 @@ Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
|
||||
init_block->statements()->Add(
|
||||
factory()->NewExpressionStatement(
|
||||
factory()->NewAssignment(Token::ASSIGN, single_var,
|
||||
decl.initializer, kNoSourcePosition),
|
||||
decl.initializer, decl.value_beg_pos),
|
||||
kNoSourcePosition),
|
||||
zone());
|
||||
return init_block;
|
||||
@ -1827,7 +1840,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
|
||||
for_info->parsing_result.declarations[0];
|
||||
Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
|
||||
ScopedPtrList<Statement> each_initialization_statements(pointer_buffer());
|
||||
decl.initializer = factory()->NewVariableProxy(temp);
|
||||
decl.initializer = factory()->NewVariableProxy(temp, for_info->position);
|
||||
InitializeVariables(&each_initialization_statements, NORMAL_VARIABLE, &decl);
|
||||
|
||||
*body_block = factory()->NewBlock(3, false);
|
||||
@ -2617,12 +2630,13 @@ Block* Parser::BuildParameterInitializationBlock(
|
||||
non_simple_param_init_statements.emplace(pointer_buffer());
|
||||
param_init_statements = &non_simple_param_init_statements.value();
|
||||
// Rewrite the outer initializer to point to param_scope
|
||||
ReparentExpressionScope(stack_limit(), parameter->pattern, param_scope);
|
||||
ReparentExpressionScope(stack_limit(), initial_value, param_scope);
|
||||
}
|
||||
|
||||
BlockState block_state(&scope_, param_scope);
|
||||
DeclarationParsingResult::Declaration decl(
|
||||
parameter->pattern, parameter->initializer_end_position, initial_value);
|
||||
DeclarationParsingResult::Declaration decl(parameter->pattern,
|
||||
initial_value);
|
||||
|
||||
InitializeVariables(param_init_statements, PARAMETER_VARIABLE, &decl);
|
||||
|
||||
|
@ -1,218 +0,0 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/message-template.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/parsing/expression-scope-reparenter.h"
|
||||
#include "src/parsing/parser.h"
|
||||
|
||||
namespace v8 {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// An AST visitor which performs declaration and assignment related tasks,
|
||||
// particularly for destructuring patterns:
|
||||
//
|
||||
// 1. Declares variables from variable proxies (particularly for destructuring
|
||||
// declarations),
|
||||
// 2. Marks destructuring-assigned variable proxies as assigned, and
|
||||
// 3. Rewrites scopes for parameters containing a sloppy eval.
|
||||
//
|
||||
// Historically this also rewrote destructuring assignments/declarations as a
|
||||
// block of multiple assignments, hence the named, however this is now done
|
||||
// during bytecode generation.
|
||||
//
|
||||
// TODO(leszeks): Rename or remove this class
|
||||
class PatternRewriter final : public AstVisitor<PatternRewriter> {
|
||||
public:
|
||||
typedef Parser::DeclarationDescriptor DeclarationDescriptor;
|
||||
|
||||
static void InitializeVariables(
|
||||
Parser* parser, VariableKind kind,
|
||||
const Parser::DeclarationParsingResult::Declaration* declaration);
|
||||
|
||||
private:
|
||||
PatternRewriter(Parser* parser, VariableKind kind, int initializer_position,
|
||||
bool declares_parameter_containing_sloppy_eval)
|
||||
: parser_(parser),
|
||||
initializer_position_(initializer_position),
|
||||
declares_parameter_containing_sloppy_eval_(
|
||||
declares_parameter_containing_sloppy_eval) {}
|
||||
|
||||
#define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node);
|
||||
// Visiting functions for AST nodes make this an AstVisitor.
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
|
||||
Expression* Visit(Assignment* assign) {
|
||||
if (parser_->has_error()) return parser_->FailureExpression();
|
||||
DCHECK_EQ(Token::ASSIGN, assign->op());
|
||||
|
||||
Expression* pattern = assign->target();
|
||||
if (pattern->IsObjectLiteral()) {
|
||||
VisitObjectLiteral(pattern->AsObjectLiteral());
|
||||
} else {
|
||||
DCHECK(pattern->IsArrayLiteral());
|
||||
VisitArrayLiteral(pattern->AsArrayLiteral());
|
||||
}
|
||||
return assign;
|
||||
}
|
||||
|
||||
void RewriteParameterScopes(Expression* expr);
|
||||
|
||||
Scope* scope() const { return parser_->scope(); }
|
||||
|
||||
Parser* const parser_;
|
||||
const int initializer_position_;
|
||||
const bool declares_parameter_containing_sloppy_eval_;
|
||||
|
||||
DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
|
||||
};
|
||||
|
||||
void Parser::InitializeVariables(
|
||||
ScopedPtrList<Statement>* statements, VariableKind kind,
|
||||
const DeclarationParsingResult::Declaration* declaration) {
|
||||
if (has_error()) return;
|
||||
|
||||
if (!declaration->initializer) {
|
||||
// The parameter scope is only a block scope if the initializer calls sloppy
|
||||
// eval. Since there is no initializer, we can't be calling sloppy eval.
|
||||
DCHECK_IMPLIES(kind == PARAMETER_VARIABLE, scope()->is_function_scope());
|
||||
return;
|
||||
}
|
||||
|
||||
PatternRewriter::InitializeVariables(this, kind, declaration);
|
||||
int pos = declaration->value_beg_position;
|
||||
if (pos == kNoSourcePosition) {
|
||||
pos = declaration->initializer_position;
|
||||
}
|
||||
Assignment* assignment = factory()->NewAssignment(
|
||||
Token::INIT, declaration->pattern, declaration->initializer, pos);
|
||||
statements->Add(factory()->NewExpressionStatement(assignment, pos));
|
||||
}
|
||||
|
||||
void PatternRewriter::InitializeVariables(
|
||||
Parser* parser, VariableKind kind,
|
||||
const Parser::DeclarationParsingResult::Declaration* declaration) {
|
||||
PatternRewriter rewriter(
|
||||
parser, kind, declaration->initializer_position,
|
||||
kind == PARAMETER_VARIABLE && parser->scope()->is_block_scope());
|
||||
|
||||
rewriter.Visit(declaration->pattern);
|
||||
}
|
||||
|
||||
void PatternRewriter::VisitVariableProxy(VariableProxy* proxy) {
|
||||
DCHECK(!parser_->has_error());
|
||||
Variable* var =
|
||||
proxy->is_resolved()
|
||||
? proxy->var()
|
||||
: scope()->GetDeclarationScope()->LookupLocal(proxy->raw_name());
|
||||
|
||||
DCHECK_NOT_NULL(var);
|
||||
|
||||
DCHECK_NE(initializer_position_, kNoSourcePosition);
|
||||
var->set_initializer_position(initializer_position_);
|
||||
}
|
||||
|
||||
// When an extra declaration scope needs to be inserted to account for
|
||||
// a sloppy eval in a default parameter or function body, the expressions
|
||||
// needs to be in that new inner scope which was added after initial
|
||||
// parsing.
|
||||
void PatternRewriter::RewriteParameterScopes(Expression* expr) {
|
||||
if (declares_parameter_containing_sloppy_eval_) {
|
||||
ReparentExpressionScope(parser_->stack_limit(), expr, scope());
|
||||
}
|
||||
}
|
||||
|
||||
void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) {
|
||||
for (ObjectLiteralProperty* property : *pattern->properties()) {
|
||||
Expression* key = property->key();
|
||||
if (!key->IsLiteral()) {
|
||||
// Computed property names contain expressions which might require
|
||||
// scope rewriting.
|
||||
RewriteParameterScopes(key);
|
||||
}
|
||||
Visit(property->value());
|
||||
}
|
||||
}
|
||||
|
||||
void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
for (Expression* value : *node->values()) {
|
||||
if (value->IsTheHoleLiteral()) continue;
|
||||
Visit(value);
|
||||
}
|
||||
}
|
||||
|
||||
void PatternRewriter::VisitAssignment(Assignment* node) {
|
||||
DCHECK_EQ(Token::ASSIGN, node->op());
|
||||
|
||||
// Initializer may have been parsed in the wrong scope.
|
||||
RewriteParameterScopes(node->value());
|
||||
|
||||
Visit(node->target());
|
||||
}
|
||||
|
||||
void PatternRewriter::VisitSpread(Spread* node) { Visit(node->expression()); }
|
||||
|
||||
// =============== UNREACHABLE =============================
|
||||
|
||||
#define NOT_A_PATTERN(Node) \
|
||||
void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); }
|
||||
|
||||
NOT_A_PATTERN(BinaryOperation)
|
||||
NOT_A_PATTERN(NaryOperation)
|
||||
NOT_A_PATTERN(Block)
|
||||
NOT_A_PATTERN(BreakStatement)
|
||||
NOT_A_PATTERN(Call)
|
||||
NOT_A_PATTERN(CallNew)
|
||||
NOT_A_PATTERN(CallRuntime)
|
||||
NOT_A_PATTERN(ClassLiteral)
|
||||
NOT_A_PATTERN(CompareOperation)
|
||||
NOT_A_PATTERN(CompoundAssignment)
|
||||
NOT_A_PATTERN(Conditional)
|
||||
NOT_A_PATTERN(ContinueStatement)
|
||||
NOT_A_PATTERN(CountOperation)
|
||||
NOT_A_PATTERN(DebuggerStatement)
|
||||
NOT_A_PATTERN(DoExpression)
|
||||
NOT_A_PATTERN(DoWhileStatement)
|
||||
NOT_A_PATTERN(EmptyStatement)
|
||||
NOT_A_PATTERN(EmptyParentheses)
|
||||
NOT_A_PATTERN(ExpressionStatement)
|
||||
NOT_A_PATTERN(ForInStatement)
|
||||
NOT_A_PATTERN(ForOfStatement)
|
||||
NOT_A_PATTERN(ForStatement)
|
||||
NOT_A_PATTERN(FunctionDeclaration)
|
||||
NOT_A_PATTERN(FunctionLiteral)
|
||||
NOT_A_PATTERN(GetTemplateObject)
|
||||
NOT_A_PATTERN(IfStatement)
|
||||
NOT_A_PATTERN(ImportCallExpression)
|
||||
NOT_A_PATTERN(Literal)
|
||||
NOT_A_PATTERN(NativeFunctionLiteral)
|
||||
NOT_A_PATTERN(Property)
|
||||
NOT_A_PATTERN(RegExpLiteral)
|
||||
NOT_A_PATTERN(ResolvedProperty)
|
||||
NOT_A_PATTERN(ReturnStatement)
|
||||
NOT_A_PATTERN(SloppyBlockFunctionStatement)
|
||||
NOT_A_PATTERN(StoreInArrayLiteral)
|
||||
NOT_A_PATTERN(SuperPropertyReference)
|
||||
NOT_A_PATTERN(SuperCallReference)
|
||||
NOT_A_PATTERN(SwitchStatement)
|
||||
NOT_A_PATTERN(TemplateLiteral)
|
||||
NOT_A_PATTERN(ThisFunction)
|
||||
NOT_A_PATTERN(Throw)
|
||||
NOT_A_PATTERN(TryCatchStatement)
|
||||
NOT_A_PATTERN(TryFinallyStatement)
|
||||
NOT_A_PATTERN(UnaryOperation)
|
||||
NOT_A_PATTERN(VariableDeclaration)
|
||||
NOT_A_PATTERN(WhileStatement)
|
||||
NOT_A_PATTERN(WithStatement)
|
||||
NOT_A_PATTERN(Yield)
|
||||
NOT_A_PATTERN(YieldStar)
|
||||
NOT_A_PATTERN(Await)
|
||||
NOT_A_PATTERN(InitializeClassMembersStatement)
|
||||
|
||||
#undef NOT_A_PATTERN
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -18,7 +18,7 @@ bytecodes: [
|
||||
B(CreateRestParameter),
|
||||
B(Star), R(1),
|
||||
/* 10 E> */ B(StackCheck),
|
||||
/* 22 S> */ B(Star), R(0),
|
||||
B(Star), R(0),
|
||||
/* 42 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -38,8 +38,8 @@ bytecodes: [
|
||||
B(CreateRestParameter),
|
||||
B(Star), R(2),
|
||||
/* 10 E> */ B(StackCheck),
|
||||
/* 12 S> */ B(Mov), R(arg0), R(0),
|
||||
/* 25 S> */ B(Mov), R(2), R(1),
|
||||
B(Mov), R(arg0), R(0),
|
||||
B(Mov), R(2), R(1),
|
||||
/* 29 S> */ B(Ldar), R(1),
|
||||
/* 45 S> */ B(Return),
|
||||
]
|
||||
@ -60,8 +60,8 @@ bytecodes: [
|
||||
B(CreateRestParameter),
|
||||
B(Star), R(2),
|
||||
/* 10 E> */ B(StackCheck),
|
||||
/* 12 S> */ B(Mov), R(arg0), R(0),
|
||||
/* 25 S> */ B(Mov), R(2), R(1),
|
||||
B(Mov), R(arg0), R(0),
|
||||
B(Mov), R(2), R(1),
|
||||
/* 29 S> */ B(LdaZero),
|
||||
/* 44 E> */ B(LdaKeyedProperty), R(1), U8(0),
|
||||
/* 48 S> */ B(Return),
|
||||
@ -85,8 +85,8 @@ bytecodes: [
|
||||
B(CreateRestParameter),
|
||||
B(Star), R(2),
|
||||
/* 10 E> */ B(StackCheck),
|
||||
/* 12 S> */ B(Mov), R(arg0), R(0),
|
||||
/* 25 S> */ B(Mov), R(2), R(1),
|
||||
B(Mov), R(arg0), R(0),
|
||||
B(Mov), R(2), R(1),
|
||||
/* 29 S> */ B(LdaZero),
|
||||
/* 44 E> */ B(LdaKeyedProperty), R(1), U8(1),
|
||||
B(Star), R(4),
|
||||
|
@ -57,7 +57,7 @@ bytecodes: [
|
||||
B(Star), R(3),
|
||||
B(Mov), R(closure), R(1),
|
||||
/* 128 E> */ B(StackCheck),
|
||||
/* 136 S> */ B(Mov), R(3), R(2),
|
||||
B(Mov), R(3), R(2),
|
||||
/* 140 S> */ B(Ldar), R(closure),
|
||||
B(GetSuperConstructor), R(5),
|
||||
B(LdaSmi), I8(1),
|
||||
@ -99,7 +99,7 @@ bytecodes: [
|
||||
B(Star), R(3),
|
||||
B(Mov), R(closure), R(1),
|
||||
/* 128 E> */ B(StackCheck),
|
||||
/* 136 S> */ B(Mov), R(3), R(2),
|
||||
B(Mov), R(3), R(2),
|
||||
/* 140 S> */ B(Ldar), R(closure),
|
||||
B(GetSuperConstructor), R(5),
|
||||
B(CreateEmptyArrayLiteral), U8(0),
|
||||
|
@ -26,84 +26,84 @@ function listener(event, exec_state, event_data, data) {
|
||||
|
||||
Debug.setListener(listener);
|
||||
|
||||
var id = x => x; // B11 B12 B42 B43
|
||||
var id = x => x; // B9 B10 B36 B37
|
||||
|
||||
function test() {
|
||||
debugger; // B0
|
||||
function fx1([
|
||||
a, // B3
|
||||
b // B4
|
||||
]) { // B2
|
||||
assertEquals([1, 2], [a, b]); // B5
|
||||
} // B6
|
||||
a, // B2
|
||||
b // B3
|
||||
]) {
|
||||
assertEquals([1, 2], [a, b]); // B4
|
||||
} // B5
|
||||
fx1([1, 2, 3]); // B1
|
||||
|
||||
function f2([
|
||||
a, // B9
|
||||
b = id(3) // B10
|
||||
]) { // B8
|
||||
assertEquals([4, 3], [a, b]); // B13
|
||||
} // B14
|
||||
f2([4]); // B7
|
||||
a, // B7
|
||||
b = id(3) // B8
|
||||
]) {
|
||||
assertEquals([4, 3], [a, b]); // B11
|
||||
} // B12
|
||||
f2([4]); // B6
|
||||
|
||||
function f3({
|
||||
x: a, // B17
|
||||
y: b // B18
|
||||
}) { // B16
|
||||
assertEquals([5, 6], [a, b]); // B19
|
||||
} // B20
|
||||
f3({y: 6, x: 5}); // B15
|
||||
x: a, // B14
|
||||
y: b // B15
|
||||
}) {
|
||||
assertEquals([5, 6], [a, b]); // B16
|
||||
} // B17
|
||||
f3({y: 6, x: 5}); // B13
|
||||
|
||||
function f4([
|
||||
a, // B23
|
||||
a, // B19
|
||||
{
|
||||
b, // B24
|
||||
c, // B25
|
||||
b, // B20
|
||||
c, // B21
|
||||
}
|
||||
]) { // B22
|
||||
assertEquals([2, 4, 6], [a, b, c]); // B26
|
||||
} // B27
|
||||
f4([2, {c: 6, b: 4}]); // B21
|
||||
]) { // B19
|
||||
assertEquals([2, 4, 6], [a, b, c]); // B22
|
||||
} // B23
|
||||
f4([2, {c: 6, b: 4}]); // B18
|
||||
|
||||
function f5([
|
||||
{
|
||||
a, // B30
|
||||
b = 7 // B31
|
||||
a, // B25
|
||||
b = 7 // B26
|
||||
},
|
||||
c = 3 // B32
|
||||
] = [{a:1}]) { // B29
|
||||
assertEquals([1, 7, 3], [a, b, c]); // B33
|
||||
} // B34
|
||||
f5(); // B28
|
||||
c = 3 // B27
|
||||
] = [{a:1}]) {
|
||||
assertEquals([1, 7, 3], [a, b, c]); // B28
|
||||
} // B29
|
||||
f5(); // B24
|
||||
|
||||
var name = "x"; // B35
|
||||
var name = "x"; // B30
|
||||
function f6({
|
||||
[id(name)]: a, // B40 B41
|
||||
b = a // B44
|
||||
}) { // B39
|
||||
assertEquals([9, 9], [a, b]); // B45
|
||||
} // B46
|
||||
var o6 = {}; // B36
|
||||
o6[name] = 9; // B37
|
||||
f6(o6); // B38
|
||||
[id(name)]: a, // B34 B35
|
||||
b = a // B38
|
||||
}) {
|
||||
assertEquals([9, 9], [a, b]); // B39
|
||||
} // B40
|
||||
var o6 = {}; // B31
|
||||
o6[name] = 9; // B32
|
||||
f6(o6); // B33
|
||||
|
||||
try {
|
||||
throw [3, 4]; // B47
|
||||
throw [3, 4]; // B41
|
||||
} catch ([
|
||||
a, // B49
|
||||
b, // B50
|
||||
c = 6 // B51
|
||||
]) { // B48
|
||||
assertEquals([3, 4, 6], [a, b, c]); // B52
|
||||
a, // B42
|
||||
b, // B43
|
||||
c = 6 // B44
|
||||
]) {
|
||||
assertEquals([3, 4, 6], [a, b, c]); // B45
|
||||
}
|
||||
|
||||
var {
|
||||
x: a, // B54
|
||||
y: b = 9 // B55
|
||||
} = { x: 4 }; // B53
|
||||
assertEquals([4, 9], [a, b]); // B56
|
||||
} // B57
|
||||
x: a, // B47
|
||||
y: b = 9 // B48
|
||||
} = { x: 4 }; // B46
|
||||
assertEquals([4, 9], [a, b]); // B49
|
||||
} // B50
|
||||
|
||||
test();
|
||||
Debug.setListener(null); // B58
|
||||
Debug.setListener(null); // B51
|
||||
assertNull(exception);
|
||||
|
@ -41,5 +41,5 @@ Debug.setListener(null); // c
|
||||
assertNull(exception);
|
||||
assertEquals("default", result);
|
||||
|
||||
assertEquals(["a0","b13","f31b13","f18b13","d2f18b13","d19f18b13","g14b13","c0"],
|
||||
assertEquals(["a0","b13","f18b13","d2f18b13","d19f18b13","g14b13","c0"],
|
||||
log);
|
||||
|
@ -10,12 +10,6 @@ paused
|
||||
#c(f, 2);
|
||||
}
|
||||
|
||||
paused
|
||||
function c(f#, ...args) { return f(...args); }
|
||||
|
||||
paused
|
||||
function c(f, ...args#) { return f(...args); }
|
||||
|
||||
paused
|
||||
function c(f, ...args) { #return f(...args); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user