Serenity Operating System
at hosted 1155 lines 32 kB view raw
1/* 2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/Function.h> 28#include <AK/HashMap.h> 29#include <AK/ScopeGuard.h> 30#include <AK/StringBuilder.h> 31#include <LibJS/AST.h> 32#include <LibJS/Interpreter.h> 33#include <LibJS/Runtime/Array.h> 34#include <LibJS/Runtime/Error.h> 35#include <LibJS/Runtime/GlobalObject.h> 36#include <LibJS/Runtime/NativeFunction.h> 37#include <LibJS/Runtime/PrimitiveString.h> 38#include <LibJS/Runtime/ScriptFunction.h> 39#include <LibJS/Runtime/Value.h> 40#include <stdio.h> 41 42namespace JS { 43 44Value ScopeNode::execute(Interpreter& interpreter) const 45{ 46 return interpreter.run(*this); 47} 48 49Value FunctionDeclaration::execute(Interpreter& interpreter) const 50{ 51 auto* function = interpreter.heap().allocate<ScriptFunction>(body(), parameters()); 52 interpreter.set_variable(name(), function); 53 return js_undefined(); 54} 55 56Value FunctionExpression::execute(Interpreter& interpreter) const 57{ 58 return interpreter.heap().allocate<ScriptFunction>(body(), parameters()); 59} 60 61Value ExpressionStatement::execute(Interpreter& interpreter) const 62{ 63 return m_expression->execute(interpreter); 64} 65 66CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interpreter& interpreter) const 67{ 68 if (is_new_expression()) { 69 // Computing |this| is irrelevant for "new" expression. 70 return { js_undefined(), m_callee->execute(interpreter) }; 71 } 72 73 if (m_callee->is_member_expression()) { 74 auto& member_expression = static_cast<const MemberExpression&>(*m_callee); 75 auto object_value = member_expression.object().execute(interpreter); 76 if (interpreter.exception()) 77 return {}; 78 auto* this_value = object_value.to_object(interpreter.heap()); 79 if (interpreter.exception()) 80 return {}; 81 auto callee = this_value->get(member_expression.computed_property_name(interpreter)).value_or(js_undefined()); 82 return { this_value, callee }; 83 } 84 return { &interpreter.global_object(), m_callee->execute(interpreter) }; 85} 86 87Value CallExpression::execute(Interpreter& interpreter) const 88{ 89 auto [this_value, callee] = compute_this_and_callee(interpreter); 90 if (interpreter.exception()) 91 return {}; 92 93 ASSERT(!callee.is_empty()); 94 95 if (is_new_expression()) { 96 if (!callee.is_object() 97 || !callee.as_object().is_function() 98 || (callee.as_object().is_native_function() 99 && !static_cast<NativeFunction&>(callee.as_object()).has_constructor())) 100 return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a constructor", callee.to_string().characters())); 101 } 102 103 if (!callee.is_object() || !callee.as_object().is_function()) 104 return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a function", callee.to_string().characters())); 105 106 auto& function = static_cast<Function&>(callee.as_object()); 107 108 Vector<Value> arguments; 109 arguments.ensure_capacity(m_arguments.size()); 110 for (size_t i = 0; i < m_arguments.size(); ++i) { 111 auto value = m_arguments[i].execute(interpreter); 112 if (interpreter.exception()) 113 return {}; 114 arguments.append(value); 115 if (interpreter.exception()) 116 return {}; 117 } 118 119 auto& call_frame = interpreter.push_call_frame(); 120 call_frame.arguments = move(arguments); 121 122 Object* new_object = nullptr; 123 Value result; 124 if (is_new_expression()) { 125 new_object = interpreter.heap().allocate<Object>(); 126 auto prototype = function.get("prototype"); 127 if (prototype.has_value() && prototype.value().is_object()) 128 new_object->set_prototype(&prototype.value().as_object()); 129 call_frame.this_value = new_object; 130 result = function.construct(interpreter); 131 } else { 132 call_frame.this_value = this_value; 133 result = function.call(interpreter); 134 } 135 136 if (interpreter.exception()) 137 return {}; 138 139 interpreter.pop_call_frame(); 140 141 if (is_new_expression()) { 142 if (result.is_object()) 143 return result; 144 return new_object; 145 } 146 return result; 147} 148 149Value ReturnStatement::execute(Interpreter& interpreter) const 150{ 151 auto value = argument() ? argument()->execute(interpreter) : js_undefined(); 152 if (interpreter.exception()) 153 return {}; 154 interpreter.unwind(ScopeType::Function); 155 return value; 156} 157 158Value IfStatement::execute(Interpreter& interpreter) const 159{ 160 auto predicate_result = m_predicate->execute(interpreter); 161 if (interpreter.exception()) 162 return {}; 163 164 if (predicate_result.to_boolean()) 165 return interpreter.run(*m_consequent); 166 167 if (m_alternate) 168 return interpreter.run(*m_alternate); 169 170 return js_undefined(); 171} 172 173Value WhileStatement::execute(Interpreter& interpreter) const 174{ 175 Value last_value = js_undefined(); 176 while (m_test->execute(interpreter).to_boolean()) { 177 if (interpreter.exception()) 178 return {}; 179 last_value = interpreter.run(*m_body); 180 if (interpreter.exception()) 181 return {}; 182 } 183 184 return last_value; 185} 186 187Value DoWhileStatement::execute(Interpreter& interpreter) const 188{ 189 Value last_value = js_undefined(); 190 do { 191 if (interpreter.exception()) 192 return {}; 193 last_value = interpreter.run(*m_body); 194 if (interpreter.exception()) 195 return {}; 196 } while (m_test->execute(interpreter).to_boolean()); 197 198 return last_value; 199} 200 201Value ForStatement::execute(Interpreter& interpreter) const 202{ 203 RefPtr<BlockStatement> wrapper; 204 205 if (m_init && m_init->is_variable_declaration() && static_cast<const VariableDeclaration*>(m_init.ptr())->declaration_kind() != DeclarationKind::Var) { 206 wrapper = create_ast_node<BlockStatement>(); 207 interpreter.enter_scope(*wrapper, {}, ScopeType::Block); 208 } 209 210 auto wrapper_cleanup = ScopeGuard([&] { 211 if (wrapper) 212 interpreter.exit_scope(*wrapper); 213 }); 214 215 Value last_value = js_undefined(); 216 217 if (m_init) { 218 m_init->execute(interpreter); 219 if (interpreter.exception()) 220 return {}; 221 } 222 223 if (m_test) { 224 while (m_test->execute(interpreter).to_boolean()) { 225 if (interpreter.exception()) 226 return {}; 227 last_value = interpreter.run(*m_body); 228 if (interpreter.exception()) 229 return {}; 230 if (interpreter.should_unwind()) { 231 if (interpreter.should_unwind_until(ScopeType::Continuable)) { 232 interpreter.stop_unwind(); 233 } else if (interpreter.should_unwind_until(ScopeType::Breakable)) { 234 interpreter.stop_unwind(); 235 break; 236 } else { 237 return js_undefined(); 238 } 239 } 240 if (m_update) { 241 m_update->execute(interpreter); 242 if (interpreter.exception()) 243 return {}; 244 } 245 } 246 } else { 247 while (true) { 248 last_value = interpreter.run(*m_body); 249 if (interpreter.exception()) 250 return {}; 251 if (interpreter.should_unwind()) { 252 if (interpreter.should_unwind_until(ScopeType::Continuable)) { 253 interpreter.stop_unwind(); 254 } else if (interpreter.should_unwind_until(ScopeType::Breakable)) { 255 interpreter.stop_unwind(); 256 break; 257 } else { 258 return js_undefined(); 259 } 260 } 261 if (m_update) { 262 m_update->execute(interpreter); 263 if (interpreter.exception()) 264 return {}; 265 } 266 } 267 } 268 269 return last_value; 270} 271 272Value BinaryExpression::execute(Interpreter& interpreter) const 273{ 274 auto lhs_result = m_lhs->execute(interpreter); 275 if (interpreter.exception()) 276 return {}; 277 auto rhs_result = m_rhs->execute(interpreter); 278 if (interpreter.exception()) 279 return {}; 280 281 switch (m_op) { 282 case BinaryOp::Addition: 283 return add(lhs_result, rhs_result); 284 case BinaryOp::Subtraction: 285 return sub(lhs_result, rhs_result); 286 case BinaryOp::Multiplication: 287 return mul(lhs_result, rhs_result); 288 case BinaryOp::Division: 289 return div(lhs_result, rhs_result); 290 case BinaryOp::Modulo: 291 return mod(lhs_result, rhs_result); 292 case BinaryOp::Exponentiation: 293 return exp(lhs_result, rhs_result); 294 case BinaryOp::TypedEquals: 295 return typed_eq(lhs_result, rhs_result); 296 case BinaryOp::TypedInequals: 297 return Value(!typed_eq(lhs_result, rhs_result).as_bool()); 298 case BinaryOp::AbstractEquals: 299 return eq(lhs_result, rhs_result); 300 case BinaryOp::AbstractInequals: 301 return Value(!eq(lhs_result, rhs_result).as_bool()); 302 case BinaryOp::GreaterThan: 303 return greater_than(lhs_result, rhs_result); 304 case BinaryOp::GreaterThanEquals: 305 return greater_than_equals(lhs_result, rhs_result); 306 case BinaryOp::LessThan: 307 return less_than(lhs_result, rhs_result); 308 case BinaryOp::LessThanEquals: 309 return less_than_equals(lhs_result, rhs_result); 310 case BinaryOp::BitwiseAnd: 311 return bitwise_and(lhs_result, rhs_result); 312 case BinaryOp::BitwiseOr: 313 return bitwise_or(lhs_result, rhs_result); 314 case BinaryOp::BitwiseXor: 315 return bitwise_xor(lhs_result, rhs_result); 316 case BinaryOp::LeftShift: 317 return left_shift(lhs_result, rhs_result); 318 case BinaryOp::RightShift: 319 return right_shift(lhs_result, rhs_result); 320 case BinaryOp::InstanceOf: 321 return instance_of(lhs_result, rhs_result); 322 } 323 324 ASSERT_NOT_REACHED(); 325} 326 327Value LogicalExpression::execute(Interpreter& interpreter) const 328{ 329 auto lhs_result = m_lhs->execute(interpreter); 330 if (interpreter.exception()) 331 return {}; 332 333 switch (m_op) { 334 case LogicalOp::And: 335 if (lhs_result.to_boolean()) { 336 auto rhs_result = m_rhs->execute(interpreter); 337 if (interpreter.exception()) 338 return {}; 339 340 return Value(rhs_result); 341 } 342 343 return Value(lhs_result); 344 case LogicalOp::Or: 345 if (lhs_result.to_boolean()) 346 return Value(lhs_result); 347 348 auto rhs_result = m_rhs->execute(interpreter); 349 if (interpreter.exception()) 350 return {}; 351 352 return Value(rhs_result); 353 } 354 355 ASSERT_NOT_REACHED(); 356} 357 358Value UnaryExpression::execute(Interpreter& interpreter) const 359{ 360 auto lhs_result = m_lhs->execute(interpreter); 361 if (interpreter.exception()) 362 return {}; 363 switch (m_op) { 364 case UnaryOp::BitwiseNot: 365 return bitwise_not(lhs_result); 366 case UnaryOp::Not: 367 return Value(!lhs_result.to_boolean()); 368 case UnaryOp::Plus: 369 return unary_plus(lhs_result); 370 case UnaryOp::Minus: 371 return unary_minus(lhs_result); 372 case UnaryOp::Typeof: 373 switch (lhs_result.type()) { 374 case Value::Type::Empty: 375 ASSERT_NOT_REACHED(); 376 return {}; 377 case Value::Type::Undefined: 378 return js_string(interpreter, "undefined"); 379 case Value::Type::Null: 380 // yes, this is on purpose. yes, this is how javascript works. 381 // yes, it's silly. 382 return js_string(interpreter, "object"); 383 case Value::Type::Number: 384 return js_string(interpreter, "number"); 385 case Value::Type::String: 386 return js_string(interpreter, "string"); 387 case Value::Type::Object: 388 if (lhs_result.as_object().is_function()) 389 return js_string(interpreter, "function"); 390 return js_string(interpreter, "object"); 391 case Value::Type::Boolean: 392 return js_string(interpreter, "boolean"); 393 } 394 } 395 396 ASSERT_NOT_REACHED(); 397} 398 399static void print_indent(int indent) 400{ 401 for (int i = 0; i < indent * 2; ++i) 402 putchar(' '); 403} 404 405void ASTNode::dump(int indent) const 406{ 407 print_indent(indent); 408 printf("%s\n", class_name()); 409} 410 411void ScopeNode::dump(int indent) const 412{ 413 ASTNode::dump(indent); 414 for (auto& child : children()) 415 child.dump(indent + 1); 416} 417 418void BinaryExpression::dump(int indent) const 419{ 420 const char* op_string = nullptr; 421 switch (m_op) { 422 case BinaryOp::Addition: 423 op_string = "+"; 424 break; 425 case BinaryOp::Subtraction: 426 op_string = "-"; 427 break; 428 case BinaryOp::Multiplication: 429 op_string = "*"; 430 break; 431 case BinaryOp::Division: 432 op_string = "/"; 433 break; 434 case BinaryOp::Modulo: 435 op_string = "%"; 436 break; 437 case BinaryOp::Exponentiation: 438 op_string = "**"; 439 break; 440 case BinaryOp::TypedEquals: 441 op_string = "==="; 442 break; 443 case BinaryOp::TypedInequals: 444 op_string = "!=="; 445 break; 446 case BinaryOp::AbstractEquals: 447 op_string = "=="; 448 break; 449 case BinaryOp::AbstractInequals: 450 op_string = "!="; 451 break; 452 case BinaryOp::GreaterThan: 453 op_string = ">"; 454 break; 455 case BinaryOp::GreaterThanEquals: 456 op_string = ">="; 457 break; 458 case BinaryOp::LessThan: 459 op_string = "<"; 460 break; 461 case BinaryOp::LessThanEquals: 462 op_string = "<="; 463 break; 464 case BinaryOp::BitwiseAnd: 465 op_string = "&"; 466 break; 467 case BinaryOp::BitwiseOr: 468 op_string = "|"; 469 break; 470 case BinaryOp::BitwiseXor: 471 op_string = "^"; 472 break; 473 case BinaryOp::LeftShift: 474 op_string = "<<"; 475 break; 476 case BinaryOp::RightShift: 477 op_string = ">>"; 478 break; 479 case BinaryOp::InstanceOf: 480 op_string = "instanceof"; 481 break; 482 } 483 484 print_indent(indent); 485 printf("%s\n", class_name()); 486 m_lhs->dump(indent + 1); 487 print_indent(indent + 1); 488 printf("%s\n", op_string); 489 m_rhs->dump(indent + 1); 490} 491 492void LogicalExpression::dump(int indent) const 493{ 494 const char* op_string = nullptr; 495 switch (m_op) { 496 case LogicalOp::And: 497 op_string = "&&"; 498 break; 499 case LogicalOp::Or: 500 op_string = "||"; 501 break; 502 } 503 504 print_indent(indent); 505 printf("%s\n", class_name()); 506 m_lhs->dump(indent + 1); 507 print_indent(indent + 1); 508 printf("%s\n", op_string); 509 m_rhs->dump(indent + 1); 510} 511 512void UnaryExpression::dump(int indent) const 513{ 514 const char* op_string = nullptr; 515 switch (m_op) { 516 case UnaryOp::BitwiseNot: 517 op_string = "~"; 518 break; 519 case UnaryOp::Not: 520 op_string = "!"; 521 break; 522 case UnaryOp::Plus: 523 op_string = "+"; 524 break; 525 case UnaryOp::Minus: 526 op_string = "-"; 527 break; 528 case UnaryOp::Typeof: 529 op_string = "typeof "; 530 break; 531 } 532 533 print_indent(indent); 534 printf("%s\n", class_name()); 535 print_indent(indent + 1); 536 printf("%s\n", op_string); 537 m_lhs->dump(indent + 1); 538} 539 540void CallExpression::dump(int indent) const 541{ 542 print_indent(indent); 543 printf("CallExpression %s\n", is_new_expression() ? "[new]" : ""); 544 m_callee->dump(indent + 1); 545 for (auto& argument : m_arguments) 546 argument.dump(indent + 1); 547} 548 549void StringLiteral::dump(int indent) const 550{ 551 print_indent(indent); 552 printf("StringLiteral \"%s\"\n", m_value.characters()); 553} 554 555void NumericLiteral::dump(int indent) const 556{ 557 print_indent(indent); 558 printf("NumericLiteral %g\n", m_value); 559} 560 561void BooleanLiteral::dump(int indent) const 562{ 563 print_indent(indent); 564 printf("BooleanLiteral %s\n", m_value ? "true" : "false"); 565} 566 567void NullLiteral::dump(int indent) const 568{ 569 print_indent(indent); 570 printf("null\n"); 571} 572 573void FunctionNode::dump(int indent, const char* class_name) const 574{ 575 StringBuilder parameters_builder; 576 parameters_builder.join(',', parameters()); 577 578 print_indent(indent); 579 printf("%s '%s(%s)'\n", class_name, name().characters(), parameters_builder.build().characters()); 580 body().dump(indent + 1); 581} 582 583void FunctionDeclaration::dump(int indent) const 584{ 585 FunctionNode::dump(indent, class_name()); 586} 587 588void FunctionExpression::dump(int indent) const 589{ 590 FunctionNode::dump(indent, class_name()); 591} 592 593void ReturnStatement::dump(int indent) const 594{ 595 ASTNode::dump(indent); 596 if (argument()) 597 argument()->dump(indent + 1); 598} 599 600void IfStatement::dump(int indent) const 601{ 602 ASTNode::dump(indent); 603 604 print_indent(indent); 605 printf("If\n"); 606 predicate().dump(indent + 1); 607 consequent().dump(indent + 1); 608 if (alternate()) { 609 print_indent(indent); 610 printf("Else\n"); 611 alternate()->dump(indent + 1); 612 } 613} 614 615void WhileStatement::dump(int indent) const 616{ 617 ASTNode::dump(indent); 618 619 print_indent(indent); 620 printf("While\n"); 621 test().dump(indent + 1); 622 body().dump(indent + 1); 623} 624 625void DoWhileStatement::dump(int indent) const 626{ 627 ASTNode::dump(indent); 628 629 print_indent(indent); 630 printf("DoWhile\n"); 631 test().dump(indent + 1); 632 body().dump(indent + 1); 633} 634 635void ForStatement::dump(int indent) const 636{ 637 ASTNode::dump(indent); 638 639 print_indent(indent); 640 printf("For\n"); 641 if (init()) 642 init()->dump(indent + 1); 643 if (test()) 644 test()->dump(indent + 1); 645 if (update()) 646 update()->dump(indent + 1); 647 body().dump(indent + 1); 648} 649 650Value Identifier::execute(Interpreter& interpreter) const 651{ 652 auto variable = interpreter.get_variable(string()); 653 if (!variable.has_value()) 654 return interpreter.throw_exception<Error>("ReferenceError", String::format("'%s' not known", string().characters())); 655 return variable.value(); 656} 657 658void Identifier::dump(int indent) const 659{ 660 print_indent(indent); 661 printf("Identifier \"%s\"\n", m_string.characters()); 662} 663 664Value AssignmentExpression::execute(Interpreter& interpreter) const 665{ 666 auto rhs_result = m_rhs->execute(interpreter); 667 if (interpreter.exception()) 668 return {}; 669 670 Value lhs_result; 671 switch (m_op) { 672 case AssignmentOp::Assignment: 673 break; 674 case AssignmentOp::AdditionAssignment: 675 lhs_result = m_lhs->execute(interpreter); 676 if (interpreter.exception()) 677 return {}; 678 rhs_result = add(lhs_result, rhs_result); 679 break; 680 case AssignmentOp::SubtractionAssignment: 681 lhs_result = m_lhs->execute(interpreter); 682 if (interpreter.exception()) 683 return {}; 684 rhs_result = sub(lhs_result, rhs_result); 685 break; 686 case AssignmentOp::MultiplicationAssignment: 687 lhs_result = m_lhs->execute(interpreter); 688 if (interpreter.exception()) 689 return {}; 690 rhs_result = mul(lhs_result, rhs_result); 691 break; 692 case AssignmentOp::DivisionAssignment: 693 lhs_result = m_lhs->execute(interpreter); 694 if (interpreter.exception()) 695 return {}; 696 rhs_result = div(lhs_result, rhs_result); 697 break; 698 } 699 if (interpreter.exception()) 700 return {}; 701 702 if (m_lhs->is_identifier()) { 703 auto name = static_cast<const Identifier&>(*m_lhs).string(); 704 interpreter.set_variable(name, rhs_result); 705 } else if (m_lhs->is_member_expression()) { 706 auto object_value = static_cast<const MemberExpression&>(*m_lhs).object().execute(interpreter); 707 if (interpreter.exception()) 708 return {}; 709 if (auto* object = object_value.to_object(interpreter.heap())) { 710 auto property_name = static_cast<const MemberExpression&>(*m_lhs).computed_property_name(interpreter); 711 object->put(property_name, rhs_result); 712 } 713 } else { 714 ASSERT_NOT_REACHED(); 715 } 716 717 return rhs_result; 718} 719 720Value UpdateExpression::execute(Interpreter& interpreter) const 721{ 722 ASSERT(m_argument->is_identifier()); 723 auto name = static_cast<const Identifier&>(*m_argument).string(); 724 725 auto previous_variable = interpreter.get_variable(name); 726 ASSERT(previous_variable.has_value()); 727 auto previous_value = previous_variable.value(); 728 ASSERT(previous_value.is_number()); 729 730 int op_result = 0; 731 switch (m_op) { 732 case UpdateOp::Increment: 733 op_result = 1; 734 break; 735 case UpdateOp::Decrement: 736 op_result = -1; 737 break; 738 } 739 740 interpreter.set_variable(name, Value(previous_value.as_double() + op_result)); 741 742 if (m_prefixed) 743 return JS::Value(previous_value.as_double() + op_result); 744 745 return previous_value; 746} 747 748void AssignmentExpression::dump(int indent) const 749{ 750 const char* op_string = nullptr; 751 switch (m_op) { 752 case AssignmentOp::Assignment: 753 op_string = "="; 754 break; 755 case AssignmentOp::AdditionAssignment: 756 op_string = "+="; 757 break; 758 case AssignmentOp::SubtractionAssignment: 759 op_string = "-="; 760 break; 761 case AssignmentOp::MultiplicationAssignment: 762 op_string = "*="; 763 break; 764 case AssignmentOp::DivisionAssignment: 765 op_string = "/="; 766 break; 767 } 768 769 ASTNode::dump(indent); 770 print_indent(indent + 1); 771 printf("%s\n", op_string); 772 m_lhs->dump(indent + 1); 773 m_rhs->dump(indent + 1); 774} 775 776void UpdateExpression::dump(int indent) const 777{ 778 const char* op_string = nullptr; 779 switch (m_op) { 780 case UpdateOp::Increment: 781 op_string = "++"; 782 break; 783 case UpdateOp::Decrement: 784 op_string = "--"; 785 break; 786 } 787 788 ASTNode::dump(indent); 789 print_indent(indent + 1); 790 if (m_prefixed) 791 printf("%s\n", op_string); 792 m_argument->dump(indent + 1); 793 if (!m_prefixed) { 794 print_indent(indent + 1); 795 printf("%s\n", op_string); 796 } 797} 798 799Value VariableDeclaration::execute(Interpreter& interpreter) const 800{ 801 for (auto& declarator : m_declarations) { 802 interpreter.declare_variable(declarator.id().string(), m_declaration_kind); 803 if (auto* init = declarator.init()) { 804 auto initalizer_result = init->execute(interpreter); 805 if (interpreter.exception()) 806 return {}; 807 interpreter.set_variable(declarator.id().string(), initalizer_result, true); 808 } 809 } 810 return js_undefined(); 811} 812 813Value VariableDeclarator::execute(Interpreter&) const 814{ 815 // NOTE: This node is handled by VariableDeclaration. 816 ASSERT_NOT_REACHED(); 817} 818 819void VariableDeclaration::dump(int indent) const 820{ 821 const char* declaration_kind_string = nullptr; 822 switch (m_declaration_kind) { 823 case DeclarationKind::Let: 824 declaration_kind_string = "Let"; 825 break; 826 case DeclarationKind::Var: 827 declaration_kind_string = "Var"; 828 break; 829 case DeclarationKind::Const: 830 declaration_kind_string = "Const"; 831 break; 832 } 833 834 ASTNode::dump(indent); 835 print_indent(indent + 1); 836 printf("%s\n", declaration_kind_string); 837 838 for (auto& declarator : m_declarations) 839 declarator.dump(indent + 1); 840} 841 842void VariableDeclarator::dump(int indent) const 843{ 844 ASTNode::dump(indent); 845 m_id->dump(indent + 1); 846 if (m_init) 847 m_init->dump(indent + 1); 848} 849 850void ObjectExpression::dump(int indent) const 851{ 852 ASTNode::dump(indent); 853 for (auto it : m_properties) { 854 print_indent(indent + 1); 855 printf("%s: ", it.key.characters()); 856 it.value->dump(0); 857 } 858} 859 860void ExpressionStatement::dump(int indent) const 861{ 862 ASTNode::dump(indent); 863 m_expression->dump(indent + 1); 864} 865 866Value ObjectExpression::execute(Interpreter& interpreter) const 867{ 868 auto object = interpreter.heap().allocate<Object>(); 869 for (auto it : m_properties) { 870 auto value = it.value->execute(interpreter); 871 if (interpreter.exception()) 872 return {}; 873 object->put(it.key, value); 874 } 875 return object; 876} 877 878void MemberExpression::dump(int indent) const 879{ 880 print_indent(indent); 881 printf("%s (computed=%s)\n", class_name(), is_computed() ? "true" : "false"); 882 m_object->dump(indent + 1); 883 m_property->dump(indent + 1); 884} 885 886PropertyName MemberExpression::computed_property_name(Interpreter& interpreter) const 887{ 888 if (!is_computed()) { 889 ASSERT(m_property->is_identifier()); 890 return PropertyName(static_cast<const Identifier&>(*m_property).string()); 891 } 892 auto index = m_property->execute(interpreter); 893 if (interpreter.exception()) 894 return {}; 895 ASSERT(!index.is_empty()); 896 // FIXME: What about non-integer numbers tho. 897 if (index.is_number() && index.to_i32() >= 0) 898 return PropertyName(index.to_i32()); 899 return PropertyName(index.to_string()); 900} 901 902Value MemberExpression::execute(Interpreter& interpreter) const 903{ 904 auto object_value = m_object->execute(interpreter); 905 if (interpreter.exception()) 906 return {}; 907 auto* object_result = object_value.to_object(interpreter.heap()); 908 if (interpreter.exception()) 909 return {}; 910 auto result = object_result->get(computed_property_name(interpreter)); 911 if (result.has_value()) { 912 ASSERT(!result.value().is_empty()); 913 } 914 return result.value_or(js_undefined()); 915} 916 917Value StringLiteral::execute(Interpreter& interpreter) const 918{ 919 return js_string(interpreter, m_value); 920} 921 922Value NumericLiteral::execute(Interpreter&) const 923{ 924 return Value(m_value); 925} 926 927Value BooleanLiteral::execute(Interpreter&) const 928{ 929 return Value(m_value); 930} 931 932Value NullLiteral::execute(Interpreter&) const 933{ 934 return js_null(); 935} 936 937void ArrayExpression::dump(int indent) const 938{ 939 ASTNode::dump(indent); 940 for (auto& element : m_elements) { 941 element.dump(indent + 1); 942 } 943} 944 945Value ArrayExpression::execute(Interpreter& interpreter) const 946{ 947 auto* array = interpreter.heap().allocate<Array>(); 948 for (auto& element : m_elements) { 949 auto value = element.execute(interpreter); 950 if (interpreter.exception()) 951 return {}; 952 array->push(value); 953 } 954 return array; 955} 956 957void TryStatement::dump(int indent) const 958{ 959 ASTNode::dump(indent); 960 print_indent(indent); 961 printf("(Block)\n"); 962 block().dump(indent + 1); 963 964 if (handler()) { 965 print_indent(indent); 966 printf("(Handler)\n"); 967 handler()->dump(indent + 1); 968 } 969 970 if (finalizer()) { 971 print_indent(indent); 972 printf("(Finalizer)\n"); 973 finalizer()->dump(indent + 1); 974 } 975} 976 977void CatchClause::dump(int indent) const 978{ 979 print_indent(indent); 980 printf("CatchClause"); 981 if (!m_parameter.is_null()) 982 printf(" (%s)", m_parameter.characters()); 983 printf("\n"); 984 body().dump(indent + 1); 985} 986 987void ThrowStatement::dump(int indent) const 988{ 989 ASTNode::dump(indent); 990 argument().dump(indent + 1); 991} 992 993Value TryStatement::execute(Interpreter& interpreter) const 994{ 995 interpreter.run(block(), {}, ScopeType::Try); 996 if (auto* exception = interpreter.exception()) { 997 if (m_handler) { 998 interpreter.clear_exception(); 999 ArgumentVector arguments { { m_handler->parameter(), exception->value() } }; 1000 interpreter.run(m_handler->body(), move(arguments)); 1001 } 1002 } 1003 1004 if (m_finalizer) 1005 m_finalizer->execute(interpreter); 1006 1007 return js_undefined(); 1008} 1009 1010Value CatchClause::execute(Interpreter&) const 1011{ 1012 // NOTE: CatchClause execution is handled by TryStatement. 1013 ASSERT_NOT_REACHED(); 1014 return {}; 1015} 1016 1017Value ThrowStatement::execute(Interpreter& interpreter) const 1018{ 1019 auto value = m_argument->execute(interpreter); 1020 if (interpreter.exception()) 1021 return {}; 1022 return interpreter.throw_exception(value); 1023} 1024 1025Value SwitchStatement::execute(Interpreter& interpreter) const 1026{ 1027 auto discriminant_result = m_discriminant->execute(interpreter); 1028 if (interpreter.exception()) 1029 return {}; 1030 1031 bool falling_through = false; 1032 1033 for (auto& switch_case : m_cases) { 1034 if (!falling_through && switch_case.test()) { 1035 auto test_result = switch_case.test()->execute(interpreter); 1036 if (interpreter.exception()) 1037 return {}; 1038 if (!eq(discriminant_result, test_result).to_boolean()) 1039 continue; 1040 } 1041 falling_through = true; 1042 1043 for (auto& statement : switch_case.consequent()) { 1044 statement.execute(interpreter); 1045 if (interpreter.exception()) 1046 return {}; 1047 if (interpreter.should_unwind()) { 1048 if (interpreter.should_unwind_until(ScopeType::Breakable)) { 1049 interpreter.stop_unwind(); 1050 return {}; 1051 } 1052 return {}; 1053 } 1054 } 1055 } 1056 1057 return js_undefined(); 1058} 1059 1060Value SwitchCase::execute(Interpreter& interpreter) const 1061{ 1062 (void)interpreter; 1063 return {}; 1064} 1065 1066Value BreakStatement::execute(Interpreter& interpreter) const 1067{ 1068 interpreter.unwind(ScopeType::Breakable); 1069 return js_undefined(); 1070} 1071 1072Value ContinueStatement::execute(Interpreter& interpreter) const 1073{ 1074 interpreter.unwind(ScopeType::Continuable); 1075 return js_undefined(); 1076} 1077 1078void SwitchStatement::dump(int indent) const 1079{ 1080 ASTNode::dump(indent); 1081 m_discriminant->dump(indent + 1); 1082 for (auto& switch_case : m_cases) { 1083 switch_case.dump(indent + 1); 1084 } 1085} 1086 1087void SwitchCase::dump(int indent) const 1088{ 1089 ASTNode::dump(indent); 1090 print_indent(indent); 1091 if (m_test) { 1092 printf("(Test)\n"); 1093 m_test->dump(indent + 1); 1094 } else { 1095 printf("(Default)\n"); 1096 } 1097 print_indent(indent); 1098 printf("(Consequent)\n"); 1099 int i = 0; 1100 for (auto& statement : m_consequent) { 1101 print_indent(indent); 1102 printf("[%d]\n", i++); 1103 statement.dump(indent + 1); 1104 } 1105} 1106 1107Value ConditionalExpression::execute(Interpreter& interpreter) const 1108{ 1109 auto test_result = m_test->execute(interpreter); 1110 if (interpreter.exception()) 1111 return {}; 1112 Value result; 1113 if (test_result.to_boolean()) { 1114 result = m_consequent->execute(interpreter); 1115 } else { 1116 result = m_alternate->execute(interpreter); 1117 } 1118 if (interpreter.exception()) 1119 return {}; 1120 return result; 1121} 1122 1123void ConditionalExpression::dump(int indent) const 1124{ 1125 ASTNode::dump(indent); 1126 print_indent(indent); 1127 printf("(Test)\n"); 1128 m_test->dump(indent + 1); 1129 print_indent(indent); 1130 printf("(Consequent)\n"); 1131 m_test->dump(indent + 1); 1132 print_indent(indent); 1133 printf("(Alternate)\n"); 1134 m_test->dump(indent + 1); 1135} 1136 1137void SequenceExpression::dump(int indent) const 1138{ 1139 ASTNode::dump(indent); 1140 for (auto& expression : m_expressions) 1141 expression.dump(indent + 1); 1142} 1143 1144Value SequenceExpression::execute(Interpreter& interpreter) const 1145{ 1146 Value last_value; 1147 for (auto& expression : m_expressions) { 1148 last_value = expression.execute(interpreter); 1149 if (interpreter.exception()) 1150 return {}; 1151 } 1152 return last_value; 1153} 1154 1155}