VM.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Debug.h>
  8. #include <AK/ScopeGuard.h>
  9. #include <AK/StringBuilder.h>
  10. #include <LibJS/Interpreter.h>
  11. #include <LibJS/Runtime/Array.h>
  12. #include <LibJS/Runtime/Error.h>
  13. #include <LibJS/Runtime/GlobalObject.h>
  14. #include <LibJS/Runtime/NativeFunction.h>
  15. #include <LibJS/Runtime/PromiseReaction.h>
  16. #include <LibJS/Runtime/Reference.h>
  17. #include <LibJS/Runtime/ScriptFunction.h>
  18. #include <LibJS/Runtime/Symbol.h>
  19. #include <LibJS/Runtime/TemporaryClearException.h>
  20. #include <LibJS/Runtime/VM.h>
  21. namespace JS {
  22. NonnullRefPtr<VM> VM::create()
  23. {
  24. return adopt_ref(*new VM);
  25. }
  26. VM::VM()
  27. : m_heap(*this)
  28. {
  29. m_empty_string = m_heap.allocate_without_global_object<PrimitiveString>(String::empty());
  30. for (size_t i = 0; i < 128; ++i) {
  31. m_single_ascii_character_strings[i] = m_heap.allocate_without_global_object<PrimitiveString>(String::formatted("{:c}", i));
  32. }
  33. m_scope_object_shape = m_heap.allocate_without_global_object<Shape>(Shape::ShapeWithoutGlobalObjectTag::Tag);
  34. #define __JS_ENUMERATE(SymbolName, snake_name) \
  35. m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
  36. JS_ENUMERATE_WELL_KNOWN_SYMBOLS
  37. #undef __JS_ENUMERATE
  38. }
  39. VM::~VM()
  40. {
  41. }
  42. Interpreter& VM::interpreter()
  43. {
  44. VERIFY(!m_interpreters.is_empty());
  45. return *m_interpreters.last();
  46. }
  47. Interpreter* VM::interpreter_if_exists()
  48. {
  49. if (m_interpreters.is_empty())
  50. return nullptr;
  51. return m_interpreters.last();
  52. }
  53. void VM::push_interpreter(Interpreter& interpreter)
  54. {
  55. m_interpreters.append(&interpreter);
  56. }
  57. void VM::pop_interpreter(Interpreter& interpreter)
  58. {
  59. VERIFY(!m_interpreters.is_empty());
  60. auto* popped_interpreter = m_interpreters.take_last();
  61. VERIFY(popped_interpreter == &interpreter);
  62. }
  63. VM::InterpreterExecutionScope::InterpreterExecutionScope(Interpreter& interpreter)
  64. : m_interpreter(interpreter)
  65. {
  66. m_interpreter.vm().push_interpreter(m_interpreter);
  67. }
  68. VM::InterpreterExecutionScope::~InterpreterExecutionScope()
  69. {
  70. m_interpreter.vm().pop_interpreter(m_interpreter);
  71. }
  72. void VM::gather_roots(HashTable<Cell*>& roots)
  73. {
  74. roots.set(m_empty_string);
  75. for (auto* string : m_single_ascii_character_strings)
  76. roots.set(string);
  77. roots.set(m_scope_object_shape);
  78. roots.set(m_exception);
  79. if (m_last_value.is_cell())
  80. roots.set(&m_last_value.as_cell());
  81. for (auto& call_frame : m_call_stack) {
  82. if (call_frame->this_value.is_cell())
  83. roots.set(&call_frame->this_value.as_cell());
  84. roots.set(call_frame->arguments_object);
  85. for (auto& argument : call_frame->arguments) {
  86. if (argument.is_cell())
  87. roots.set(&argument.as_cell());
  88. }
  89. roots.set(call_frame->scope);
  90. }
  91. #define __JS_ENUMERATE(SymbolName, snake_name) \
  92. roots.set(well_known_symbol_##snake_name());
  93. JS_ENUMERATE_WELL_KNOWN_SYMBOLS
  94. #undef __JS_ENUMERATE
  95. for (auto& symbol : m_global_symbol_map)
  96. roots.set(symbol.value);
  97. for (auto* job : m_promise_jobs)
  98. roots.set(job);
  99. }
  100. Symbol* VM::get_global_symbol(const String& description)
  101. {
  102. auto result = m_global_symbol_map.get(description);
  103. if (result.has_value())
  104. return result.value();
  105. auto new_global_symbol = js_symbol(*this, description, true);
  106. m_global_symbol_map.set(description, new_global_symbol);
  107. return new_global_symbol;
  108. }
  109. void VM::set_variable(const FlyString& name, Value value, GlobalObject& global_object, bool first_assignment)
  110. {
  111. if (m_call_stack.size()) {
  112. for (auto* scope = current_scope(); scope; scope = scope->parent()) {
  113. auto possible_match = scope->get_from_scope(name);
  114. if (possible_match.has_value()) {
  115. if (!first_assignment && possible_match.value().declaration_kind == DeclarationKind::Const) {
  116. throw_exception<TypeError>(global_object, ErrorType::InvalidAssignToConst);
  117. return;
  118. }
  119. scope->put_to_scope(name, { value, possible_match.value().declaration_kind });
  120. return;
  121. }
  122. }
  123. }
  124. global_object.put(move(name), move(value));
  125. }
  126. Value VM::get_variable(const FlyString& name, GlobalObject& global_object)
  127. {
  128. if (!m_call_stack.is_empty()) {
  129. if (name == names.arguments && !call_frame().callee.is_empty()) {
  130. // HACK: Special handling for the name "arguments":
  131. // If the name "arguments" is defined in the current scope, for example via
  132. // a function parameter, or by a local var declaration, we use that.
  133. // Otherwise, we return a lazily constructed Array with all the argument values.
  134. // FIXME: Do something much more spec-compliant.
  135. auto possible_match = current_scope()->get_from_scope(name);
  136. if (possible_match.has_value())
  137. return possible_match.value().value;
  138. if (!call_frame().arguments_object) {
  139. call_frame().arguments_object = Array::create(global_object);
  140. call_frame().arguments_object->put(names.callee, call_frame().callee);
  141. for (auto argument : call_frame().arguments) {
  142. call_frame().arguments_object->indexed_properties().append(argument);
  143. }
  144. }
  145. return call_frame().arguments_object;
  146. }
  147. for (auto* scope = current_scope(); scope; scope = scope->parent()) {
  148. auto possible_match = scope->get_from_scope(name);
  149. if (exception())
  150. return {};
  151. if (possible_match.has_value())
  152. return possible_match.value().value;
  153. }
  154. }
  155. auto value = global_object.get(name);
  156. if (m_underscore_is_last_value && name == "_" && value.is_empty())
  157. return m_last_value;
  158. return value;
  159. }
  160. Reference VM::get_reference(const FlyString& name)
  161. {
  162. if (m_call_stack.size()) {
  163. for (auto* scope = current_scope(); scope; scope = scope->parent()) {
  164. if (is<GlobalObject>(scope))
  165. break;
  166. auto possible_match = scope->get_from_scope(name);
  167. if (possible_match.has_value())
  168. return { Reference::LocalVariable, name };
  169. }
  170. }
  171. return { Reference::GlobalVariable, name };
  172. }
  173. Value VM::construct(Function& function, Function& new_target, Optional<MarkedValueList> arguments, GlobalObject& global_object)
  174. {
  175. CallFrame call_frame;
  176. call_frame.callee = &function;
  177. if (auto* interpreter = interpreter_if_exists())
  178. call_frame.current_node = interpreter->current_node();
  179. call_frame.is_strict_mode = function.is_strict_mode();
  180. push_call_frame(call_frame, function.global_object());
  181. if (exception())
  182. return {};
  183. ArmedScopeGuard call_frame_popper = [&] {
  184. pop_call_frame();
  185. };
  186. call_frame.function_name = function.name();
  187. call_frame.arguments = function.bound_arguments();
  188. if (arguments.has_value())
  189. call_frame.arguments.append(arguments.value().values());
  190. auto* environment = function.create_environment();
  191. call_frame.scope = environment;
  192. environment->set_new_target(&new_target);
  193. Object* new_object = nullptr;
  194. if (function.constructor_kind() == Function::ConstructorKind::Base) {
  195. new_object = Object::create_empty(global_object);
  196. environment->bind_this_value(global_object, new_object);
  197. if (exception())
  198. return {};
  199. auto prototype = new_target.get(names.prototype);
  200. if (exception())
  201. return {};
  202. if (prototype.is_object()) {
  203. new_object->set_prototype(&prototype.as_object());
  204. if (exception())
  205. return {};
  206. }
  207. }
  208. // If we are a Derived constructor, |this| has not been constructed before super is called.
  209. Value this_value = function.constructor_kind() == Function::ConstructorKind::Base ? new_object : Value {};
  210. call_frame.this_value = this_value;
  211. auto result = function.construct(new_target);
  212. this_value = call_frame.scope->get_this_binding(global_object);
  213. pop_call_frame();
  214. call_frame_popper.disarm();
  215. // If we are constructing an instance of a derived class,
  216. // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
  217. if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
  218. VERIFY(is<LexicalEnvironment>(current_scope()));
  219. static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result);
  220. auto prototype = new_target.get(names.prototype);
  221. if (exception())
  222. return {};
  223. if (prototype.is_object()) {
  224. result.as_object().set_prototype(&prototype.as_object());
  225. if (exception())
  226. return {};
  227. }
  228. return result;
  229. }
  230. if (exception())
  231. return {};
  232. if (result.is_object())
  233. return result;
  234. return this_value;
  235. }
  236. void VM::throw_exception(Exception& exception)
  237. {
  238. set_exception(exception);
  239. unwind(ScopeType::Try);
  240. }
  241. String VM::join_arguments(size_t start_index) const
  242. {
  243. StringBuilder joined_arguments;
  244. for (size_t i = start_index; i < argument_count(); ++i) {
  245. joined_arguments.append(argument(i).to_string_without_side_effects().characters());
  246. if (i != argument_count() - 1)
  247. joined_arguments.append(' ');
  248. }
  249. return joined_arguments.build();
  250. }
  251. Value VM::resolve_this_binding(GlobalObject& global_object) const
  252. {
  253. return find_this_scope()->get_this_binding(global_object);
  254. }
  255. const ScopeObject* VM::find_this_scope() const
  256. {
  257. // We will always return because the Global environment will always be reached, which has a |this| binding.
  258. for (auto* scope = current_scope(); scope; scope = scope->parent()) {
  259. if (scope->has_this_binding())
  260. return scope;
  261. }
  262. VERIFY_NOT_REACHED();
  263. }
  264. Value VM::get_new_target() const
  265. {
  266. VERIFY(is<LexicalEnvironment>(find_this_scope()));
  267. return static_cast<const LexicalEnvironment*>(find_this_scope())->new_target();
  268. }
  269. Value VM::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)
  270. {
  271. VERIFY(!exception());
  272. VERIFY(!this_value.is_empty());
  273. CallFrame call_frame;
  274. call_frame.callee = &function;
  275. if (auto* interpreter = interpreter_if_exists())
  276. call_frame.current_node = interpreter->current_node();
  277. call_frame.is_strict_mode = function.is_strict_mode();
  278. call_frame.function_name = function.name();
  279. call_frame.this_value = function.bound_this().value_or(this_value);
  280. call_frame.arguments = function.bound_arguments();
  281. if (arguments.has_value())
  282. call_frame.arguments.append(move(arguments.release_value().values()));
  283. auto* environment = function.create_environment();
  284. call_frame.scope = environment;
  285. VERIFY(environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
  286. environment->bind_this_value(function.global_object(), call_frame.this_value);
  287. if (exception())
  288. return {};
  289. push_call_frame(call_frame, function.global_object());
  290. if (exception())
  291. return {};
  292. auto result = function.call();
  293. pop_call_frame();
  294. return result;
  295. }
  296. bool VM::in_strict_mode() const
  297. {
  298. if (call_stack().is_empty())
  299. return false;
  300. return call_frame().is_strict_mode;
  301. }
  302. void VM::run_queued_promise_jobs()
  303. {
  304. dbgln_if(PROMISE_DEBUG, "Running queued promise jobs");
  305. // Temporarily get rid of the exception, if any - job functions must be called
  306. // either way, and that can't happen if we already have an exception stored.
  307. TemporaryClearException clear_exception(*this);
  308. while (!m_promise_jobs.is_empty()) {
  309. auto* job = m_promise_jobs.take_first();
  310. dbgln_if(PROMISE_DEBUG, "Calling promise job function @ {}", job);
  311. [[maybe_unused]] auto result = call(*job, js_undefined());
  312. }
  313. // Ensure no job has created a new exception, they must clean up after themselves.
  314. VERIFY(!m_exception);
  315. }
  316. // 9.4.4 HostEnqueuePromiseJob, https://tc39.es/ecma262/#sec-hostenqueuepromisejob
  317. void VM::enqueue_promise_job(NativeFunction& job)
  318. {
  319. m_promise_jobs.append(&job);
  320. }
  321. // 27.2.1.9 HostPromiseRejectionTracker, https://tc39.es/ecma262/#sec-host-promise-rejection-tracker
  322. void VM::promise_rejection_tracker(const Promise& promise, Promise::RejectionOperation operation) const
  323. {
  324. switch (operation) {
  325. case Promise::RejectionOperation::Reject:
  326. // A promise was rejected without any handlers
  327. if (on_promise_unhandled_rejection)
  328. on_promise_unhandled_rejection(promise);
  329. break;
  330. case Promise::RejectionOperation::Handle:
  331. // A handler was added to an already rejected promise
  332. if (on_promise_rejection_handled)
  333. on_promise_rejection_handled(promise);
  334. break;
  335. default:
  336. VERIFY_NOT_REACHED();
  337. }
  338. }
  339. }