ScriptFunction.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (c) 2020, Stephan Unverwerth <s.unverwerth@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Debug.h>
  7. #include <AK/Function.h>
  8. #include <LibJS/AST.h>
  9. #include <LibJS/Bytecode/BasicBlock.h>
  10. #include <LibJS/Bytecode/Generator.h>
  11. #include <LibJS/Bytecode/Interpreter.h>
  12. #include <LibJS/Bytecode/PassManager.h>
  13. #include <LibJS/Interpreter.h>
  14. #include <LibJS/Runtime/Array.h>
  15. #include <LibJS/Runtime/Error.h>
  16. #include <LibJS/Runtime/GeneratorObject.h>
  17. #include <LibJS/Runtime/GlobalObject.h>
  18. #include <LibJS/Runtime/NativeFunction.h>
  19. #include <LibJS/Runtime/ScriptFunction.h>
  20. #include <LibJS/Runtime/Value.h>
  21. namespace JS {
  22. static ScriptFunction* typed_this(VM& vm, GlobalObject& global_object)
  23. {
  24. auto* this_object = vm.this_value(global_object).to_object(global_object);
  25. if (!this_object)
  26. return nullptr;
  27. if (!this_object->is_function()) {
  28. vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunctionNoParam);
  29. return nullptr;
  30. }
  31. return static_cast<ScriptFunction*>(this_object);
  32. }
  33. ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function)
  34. {
  35. return global_object.heap().allocate<ScriptFunction>(global_object, global_object, name, body, move(parameters), m_function_length, parent_scope, *global_object.function_prototype(), kind, is_strict, is_arrow_function);
  36. }
  37. ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function)
  38. : Function(prototype, is_arrow_function ? vm().this_value(global_object) : Value(), {})
  39. , m_name(name)
  40. , m_body(body)
  41. , m_parameters(move(parameters))
  42. , m_parent_scope(parent_scope)
  43. , m_function_length(m_function_length)
  44. , m_kind(kind)
  45. , m_is_strict(is_strict)
  46. , m_is_arrow_function(is_arrow_function)
  47. {
  48. }
  49. void ScriptFunction::initialize(GlobalObject& global_object)
  50. {
  51. auto& vm = this->vm();
  52. Function::initialize(global_object);
  53. if (!m_is_arrow_function) {
  54. Object* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_script_function_prototype_object_shape());
  55. prototype->define_property(vm.names.constructor, this, Attribute::Writable | Attribute::Configurable);
  56. define_property(vm.names.prototype, prototype, Attribute::Writable);
  57. }
  58. define_native_property(vm.names.length, length_getter, {}, Attribute::Configurable);
  59. define_native_property(vm.names.name, name_getter, {}, Attribute::Configurable);
  60. }
  61. ScriptFunction::~ScriptFunction()
  62. {
  63. }
  64. void ScriptFunction::visit_edges(Visitor& visitor)
  65. {
  66. Function::visit_edges(visitor);
  67. visitor.visit(m_parent_scope);
  68. }
  69. LexicalEnvironment* ScriptFunction::create_environment()
  70. {
  71. HashMap<FlyString, Variable> variables;
  72. for (auto& parameter : m_parameters) {
  73. parameter.binding.visit(
  74. [&](const FlyString& name) { variables.set(name, { js_undefined(), DeclarationKind::Var }); },
  75. [&](const NonnullRefPtr<BindingPattern>& binding) {
  76. binding->for_each_assigned_name([&](const auto& name) {
  77. variables.set(name, { js_undefined(), DeclarationKind::Var });
  78. });
  79. });
  80. }
  81. if (is<ScopeNode>(body())) {
  82. for (auto& declaration : static_cast<const ScopeNode&>(body()).variables()) {
  83. for (auto& declarator : declaration.declarations()) {
  84. declarator.target().visit(
  85. [&](const NonnullRefPtr<Identifier>& id) {
  86. variables.set(id->string(), { js_undefined(), declaration.declaration_kind() });
  87. },
  88. [&](const NonnullRefPtr<BindingPattern>& binding) {
  89. binding->for_each_assigned_name([&](const auto& name) {
  90. variables.set(name, { js_undefined(), declaration.declaration_kind() });
  91. });
  92. });
  93. }
  94. }
  95. }
  96. auto* environment = heap().allocate<LexicalEnvironment>(global_object(), move(variables), m_parent_scope, LexicalEnvironment::EnvironmentRecordType::Function);
  97. environment->set_home_object(home_object());
  98. environment->set_current_function(*this);
  99. if (m_is_arrow_function) {
  100. if (is<LexicalEnvironment>(m_parent_scope))
  101. environment->set_new_target(static_cast<LexicalEnvironment*>(m_parent_scope)->new_target());
  102. }
  103. return environment;
  104. }
  105. Value ScriptFunction::execute_function_body()
  106. {
  107. auto& vm = this->vm();
  108. Interpreter* ast_interpreter = nullptr;
  109. auto* bytecode_interpreter = Bytecode::Interpreter::current();
  110. auto prepare_arguments = [&] {
  111. auto& call_frame_args = vm.call_frame().arguments;
  112. for (size_t i = 0; i < m_parameters.size(); ++i) {
  113. auto& parameter = m_parameters[i];
  114. parameter.binding.visit(
  115. [&](const auto& param) {
  116. Value argument_value;
  117. if (parameter.is_rest) {
  118. auto* array = Array::create(global_object());
  119. for (size_t rest_index = i; rest_index < call_frame_args.size(); ++rest_index)
  120. array->indexed_properties().append(call_frame_args[rest_index]);
  121. argument_value = move(array);
  122. } else if (i < call_frame_args.size() && !call_frame_args[i].is_undefined()) {
  123. argument_value = call_frame_args[i];
  124. } else if (parameter.default_value) {
  125. // FIXME: Support default arguments in the bytecode world!
  126. if (!bytecode_interpreter)
  127. argument_value = parameter.default_value->execute(*ast_interpreter, global_object());
  128. if (vm.exception())
  129. return;
  130. } else {
  131. argument_value = js_undefined();
  132. }
  133. if (i >= call_frame_args.size())
  134. call_frame_args.resize(i + 1);
  135. call_frame_args[i] = argument_value;
  136. vm.assign(param, argument_value, global_object(), true, vm.current_scope());
  137. });
  138. if (vm.exception())
  139. return;
  140. }
  141. };
  142. if (bytecode_interpreter) {
  143. prepare_arguments();
  144. if (!m_bytecode_executable.has_value()) {
  145. m_bytecode_executable = Bytecode::Generator::generate(m_body, m_kind == FunctionKind::Generator);
  146. auto& passes = JS::Bytecode::Interpreter::optimization_pipeline();
  147. passes.perform(*m_bytecode_executable);
  148. if constexpr (JS_BYTECODE_DEBUG) {
  149. dbgln("Optimisation passes took {}us", passes.elapsed());
  150. dbgln("Compiled Bytecode::Block for function '{}':", m_name);
  151. for (auto& block : m_bytecode_executable->basic_blocks)
  152. block.dump(*m_bytecode_executable);
  153. }
  154. }
  155. auto result = bytecode_interpreter->run(*m_bytecode_executable);
  156. if (m_kind != FunctionKind::Generator)
  157. return result;
  158. return GeneratorObject::create(global_object(), result, this, vm.call_frame().scope, bytecode_interpreter->snapshot_frame());
  159. } else {
  160. VERIFY(m_kind != FunctionKind::Generator);
  161. OwnPtr<Interpreter> local_interpreter;
  162. ast_interpreter = vm.interpreter_if_exists();
  163. if (!ast_interpreter) {
  164. local_interpreter = Interpreter::create_with_existing_global_object(global_object());
  165. ast_interpreter = local_interpreter.ptr();
  166. }
  167. VM::InterpreterExecutionScope scope(*ast_interpreter);
  168. prepare_arguments();
  169. if (vm.exception())
  170. return {};
  171. return ast_interpreter->execute_statement(global_object(), m_body, ScopeType::Function);
  172. }
  173. }
  174. Value ScriptFunction::call()
  175. {
  176. if (m_is_class_constructor) {
  177. vm().throw_exception<TypeError>(global_object(), ErrorType::ClassConstructorWithoutNew, m_name);
  178. return {};
  179. }
  180. return execute_function_body();
  181. }
  182. Value ScriptFunction::construct(Function&)
  183. {
  184. if (m_is_arrow_function) {
  185. vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, m_name);
  186. return {};
  187. }
  188. return execute_function_body();
  189. }
  190. JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter)
  191. {
  192. auto* function = typed_this(vm, global_object);
  193. if (!function)
  194. return {};
  195. return Value(static_cast<i32>(function->m_function_length));
  196. }
  197. JS_DEFINE_NATIVE_GETTER(ScriptFunction::name_getter)
  198. {
  199. auto* function = typed_this(vm, global_object);
  200. if (!function)
  201. return {};
  202. return js_string(vm, function->name().is_null() ? "" : function->name());
  203. }
  204. }