Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Unified Diff: src/parsing/parser.cc

Issue 1692713005: ES6: Desugaring of instanceof to support @@hasInstance (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@blah
Patch Set: REBASE plus comment response. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index d926e92d770079fd24f5feefb3f67d4968d06672..8005479a32670b05c34eef744975b0d47d86af17 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -6292,6 +6292,185 @@ Expression* ParserTraits::RewriteYieldStar(
return yield_star;
}
+// Desugaring of (lhs) instanceof (rhs)
+// ====================================
+//
+// We desugar instanceof into a load of property @@hasInstance on the rhs.
+// We end up with roughly the following code (O, C):
+//
+// do {
+// let O = lhs;
+// let C = rhs;
+// if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
+// let handler_result = C[Symbol.hasInstance];
+// if (handler_result === undefined) {
+// if (!IS_CALLABLE(C)) {
+// throw MakeTypeError(kCalledNonCallableInstanceOf);
+// }
+// handler_result = %ordinary_has_instance(C, O);
+// } else {
+// handler_result = !!(%_Call(handler_result, C, O));
+// }
+// handler_result;
+// }
+//
+Expression* ParserTraits::RewriteInstanceof(Expression* lhs, Expression* rhs,
+ int pos) {
+ const int nopos = RelocInfo::kNoPosition;
+
+ auto factory = parser_->factory();
+ auto avfactory = parser_->ast_value_factory();
+ auto scope = parser_->scope_;
+ auto zone = parser_->zone();
+
+ // let O = lhs;
+ Variable* var_O = scope->NewTemporary(avfactory->empty_string());
+ Statement* get_O;
+ {
+ Expression* O_proxy = factory->NewVariableProxy(var_O);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, O_proxy, lhs, nopos);
+ get_O = factory->NewExpressionStatement(assignment, nopos);
+ }
+
+ // let C = lhs;
+ Variable* var_C = scope->NewTemporary(avfactory->empty_string());
+ Statement* get_C;
+ {
+ Expression* C_proxy = factory->NewVariableProxy(var_C);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, C_proxy, rhs, nopos);
+ get_C = factory->NewExpressionStatement(assignment, nopos);
+ }
+
+ // if (!IS_RECEIVER(C)) throw MakeTypeError(kNonObjectInInstanceOfCheck);
+ Statement* validate_C;
+ {
+ auto args = new (zone) ZoneList<Expression*>(1, zone);
+ args->Add(factory->NewVariableProxy(var_C), zone);
+ Expression* is_receiver_call =
+ factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
+ Expression* call =
+ NewThrowTypeError(MessageTemplate::kNonObjectInInstanceOfCheck,
+ avfactory->empty_string(), nopos);
+ Statement* throw_call = factory->NewExpressionStatement(call, nopos);
+
+ validate_C =
+ factory->NewIfStatement(is_receiver_call,
+ factory->NewEmptyStatement(nopos),
+ throw_call,
+ nopos);
+ }
+
+ // let handler_result = C[Symbol.hasInstance];
+ Variable* var_handler_result = scope->NewTemporary(avfactory->empty_string());
+ Statement* initialize_handler;
+ {
+ Expression* hasInstance_symbol_literal =
+ factory->NewSymbolLiteral("hasInstance_symbol", RelocInfo::kNoPosition);
+ Expression* prop = factory->NewProperty(factory->NewVariableProxy(var_C),
+ hasInstance_symbol_literal, pos);
+ Expression* handler_proxy = factory->NewVariableProxy(var_handler_result);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, handler_proxy, prop, nopos);
+ initialize_handler = factory->NewExpressionStatement(assignment, nopos);
+ }
+
+ // if (handler_result === undefined) {
+ // if (!IS_CALLABLE(C)) {
+ // throw MakeTypeError(kCalledNonCallableInstanceOf);
+ // }
+ // result = %ordinary_has_instance(C, O);
+ // } else {
+ // handler_result = !!%_Call(handler_result, C, O);
+ // }
+ Statement* call_handler;
+ {
+ Expression* condition = factory->NewCompareOperation(
+ Token::EQ_STRICT, factory->NewVariableProxy(var_handler_result),
+ factory->NewUndefinedLiteral(nopos), nopos);
+
+ Block* then_side = factory->NewBlock(nullptr, 2, false, nopos);
+ {
+ Expression* throw_expr =
+ NewThrowTypeError(MessageTemplate::kCalledNonCallableInstanceOf,
+ avfactory->empty_string(), nopos);
+ Statement* validate_C = CheckCallable(var_C, throw_expr);
+ ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+ args->Add(factory->NewVariableProxy(var_C), zone);
+ args->Add(factory->NewVariableProxy(var_O), zone);
+ CallRuntime* call = factory->NewCallRuntime(
+ Context::ORDINARY_HAS_INSTANCE_INDEX, args, pos);
+ Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, result_proxy, call, nopos);
+ Statement* assignment_return =
+ factory->NewExpressionStatement(assignment, nopos);
+
+ then_side->statements()->Add(validate_C, zone);
+ then_side->statements()->Add(assignment_return, zone);
+ }
+
+ Statement* else_side;
+ {
+ auto args = new (zone) ZoneList<Expression*>(3, zone);
+ args->Add(factory->NewVariableProxy(var_handler_result), zone);
+ args->Add(factory->NewVariableProxy(var_C), zone);
+ args->Add(factory->NewVariableProxy(var_O), zone);
+ Expression* call =
+ factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
+ Expression* inner_not =
+ factory->NewUnaryOperation(Token::NOT, call, nopos);
+ Expression* outer_not =
+ factory->NewUnaryOperation(Token::NOT, inner_not, nopos);
+ Expression* result_proxy = factory->NewVariableProxy(var_handler_result);
+ Expression* assignment =
+ factory->NewAssignment(Token::ASSIGN, result_proxy, outer_not, nopos);
+
+ else_side = factory->NewExpressionStatement(assignment, nopos);
+ }
+ call_handler =
+ factory->NewIfStatement(condition, then_side, else_side, nopos);
+ }
+
+ // do { ... }
+ DoExpression* instanceof;
+ {
+ Block* block = factory->NewBlock(nullptr, 5, true, nopos);
+ block->statements()->Add(get_O, zone);
+ block->statements()->Add(get_C, zone);
+ block->statements()->Add(validate_C, zone);
+ block->statements()->Add(initialize_handler, zone);
+ block->statements()->Add(call_handler, zone);
+
+ // Here is the desugared instanceof.
+ instanceof = factory->NewDoExpression(block, var_handler_result, nopos);
+ Rewriter::Rewrite(parser_, instanceof, avfactory);
+ }
+
+ return instanceof;
+}
+
+Statement* ParserTraits::CheckCallable(Variable* var, Expression* error) {
+ auto factory = parser_->factory();
+ auto avfactory = parser_->ast_value_factory();
+ const int nopos = RelocInfo::kNoPosition;
+ Statement* validate_var;
+ {
+ Expression* type_of = factory->NewUnaryOperation(
+ Token::TYPEOF, factory->NewVariableProxy(var), nopos);
+ Expression* function_literal =
+ factory->NewStringLiteral(avfactory->function_string(), nopos);
+ Expression* condition = factory->NewCompareOperation(
+ Token::EQ_STRICT, type_of, function_literal, nopos);
+
+ Statement* throw_call = factory->NewExpressionStatement(error, nopos);
+
+ validate_var = factory->NewIfStatement(
+ condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
+ }
+ return validate_var;
+}
void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
Variable* iterator,
@@ -6440,20 +6619,10 @@ void ParserTraits::BuildIteratorCloseForCompletion(
// }
Statement* check_return_callable;
{
- Expression* type_of = factory->NewUnaryOperation(
- Token::TYPEOF, factory->NewVariableProxy(var_return), nopos);
- Expression* function_literal = factory->NewStringLiteral(
- avfactory->function_string(), nopos);
- Expression* condition = factory->NewCompareOperation(
- Token::EQ_STRICT, type_of, function_literal, nopos);
-
- Expression* call = NewThrowTypeError(
+ Expression* throw_expr = NewThrowTypeError(
MessageTemplate::kReturnMethodNotCallable,
avfactory->empty_string(), nopos);
- Statement* throw_call = factory->NewExpressionStatement(call, nopos);
-
- check_return_callable = factory->NewIfStatement(
- condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
+ check_return_callable = CheckCallable(var_return, throw_expr);
}
// output = %_Call(iteratorReturn, iterator);
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698