Op.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/HashTable.h>
  9. #include <LibJS/Bytecode/Interpreter.h>
  10. #include <LibJS/Bytecode/Op.h>
  11. #include <LibJS/Runtime/AbstractOperations.h>
  12. #include <LibJS/Runtime/Array.h>
  13. #include <LibJS/Runtime/BigInt.h>
  14. #include <LibJS/Runtime/DeclarativeEnvironment.h>
  15. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  16. #include <LibJS/Runtime/Environment.h>
  17. #include <LibJS/Runtime/GlobalObject.h>
  18. #include <LibJS/Runtime/Iterator.h>
  19. #include <LibJS/Runtime/IteratorOperations.h>
  20. #include <LibJS/Runtime/NativeFunction.h>
  21. #include <LibJS/Runtime/ObjectEnvironment.h>
  22. #include <LibJS/Runtime/RegExpObject.h>
  23. #include <LibJS/Runtime/Value.h>
  24. namespace JS::Bytecode {
  25. String Instruction::to_string(Bytecode::Executable const& executable) const
  26. {
  27. #define __BYTECODE_OP(op) \
  28. case Instruction::Type::op: \
  29. return static_cast<Bytecode::Op::op const&>(*this).to_string_impl(executable);
  30. switch (type()) {
  31. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  32. default:
  33. VERIFY_NOT_REACHED();
  34. }
  35. #undef __BYTECODE_OP
  36. }
  37. }
  38. namespace JS::Bytecode::Op {
  39. static ThrowCompletionOr<void> put_by_property_key(Object* object, Value value, PropertyKey name, Bytecode::Interpreter& interpreter, PropertyKind kind)
  40. {
  41. if (kind == PropertyKind::Getter || kind == PropertyKind::Setter) {
  42. // The generator should only pass us functions for getters and setters.
  43. VERIFY(value.is_function());
  44. }
  45. switch (kind) {
  46. case PropertyKind::Getter: {
  47. auto& function = value.as_function();
  48. if (function.name().is_empty() && is<ECMAScriptFunctionObject>(function))
  49. static_cast<ECMAScriptFunctionObject*>(&function)->set_name(String::formatted("get {}", name));
  50. object->define_direct_accessor(name, &function, nullptr, Attribute::Configurable | Attribute::Enumerable);
  51. break;
  52. }
  53. case PropertyKind::Setter: {
  54. auto& function = value.as_function();
  55. if (function.name().is_empty() && is<ECMAScriptFunctionObject>(function))
  56. static_cast<ECMAScriptFunctionObject*>(&function)->set_name(String::formatted("set {}", name));
  57. object->define_direct_accessor(name, nullptr, &function, Attribute::Configurable | Attribute::Enumerable);
  58. break;
  59. }
  60. case PropertyKind::KeyValue:
  61. TRY(object->set(name, interpreter.accumulator(), Object::ShouldThrowExceptions::Yes));
  62. break;
  63. case PropertyKind::Spread:
  64. TRY(object->copy_data_properties(value, {}, interpreter.global_object()));
  65. break;
  66. case PropertyKind::ProtoSetter:
  67. if (value.is_object() || value.is_null())
  68. MUST(object->internal_set_prototype_of(value.is_object() ? &value.as_object() : nullptr));
  69. break;
  70. }
  71. return {};
  72. }
  73. ThrowCompletionOr<void> Load::execute_impl(Bytecode::Interpreter& interpreter) const
  74. {
  75. interpreter.accumulator() = interpreter.reg(m_src);
  76. return {};
  77. }
  78. ThrowCompletionOr<void> LoadImmediate::execute_impl(Bytecode::Interpreter& interpreter) const
  79. {
  80. interpreter.accumulator() = m_value;
  81. return {};
  82. }
  83. ThrowCompletionOr<void> Store::execute_impl(Bytecode::Interpreter& interpreter) const
  84. {
  85. interpreter.reg(m_dst) = interpreter.accumulator();
  86. return {};
  87. }
  88. static ThrowCompletionOr<Value> abstract_inequals(GlobalObject& global_object, Value src1, Value src2)
  89. {
  90. return Value(!TRY(is_loosely_equal(global_object, src1, src2)));
  91. }
  92. static ThrowCompletionOr<Value> abstract_equals(GlobalObject& global_object, Value src1, Value src2)
  93. {
  94. return Value(TRY(is_loosely_equal(global_object, src1, src2)));
  95. }
  96. static ThrowCompletionOr<Value> typed_inequals(GlobalObject&, Value src1, Value src2)
  97. {
  98. return Value(!is_strictly_equal(src1, src2));
  99. }
  100. static ThrowCompletionOr<Value> typed_equals(GlobalObject&, Value src1, Value src2)
  101. {
  102. return Value(is_strictly_equal(src1, src2));
  103. }
  104. #define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  105. ThrowCompletionOr<void> OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
  106. { \
  107. auto lhs = interpreter.reg(m_lhs_reg); \
  108. auto rhs = interpreter.accumulator(); \
  109. interpreter.accumulator() = TRY(op_snake_case(interpreter.global_object(), lhs, rhs)); \
  110. return {}; \
  111. } \
  112. String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
  113. { \
  114. return String::formatted(#OpTitleCase " {}", m_lhs_reg); \
  115. }
  116. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP)
  117. static ThrowCompletionOr<Value> not_(GlobalObject&, Value value)
  118. {
  119. return Value(!value.to_boolean());
  120. }
  121. static ThrowCompletionOr<Value> typeof_(GlobalObject& global_object, Value value)
  122. {
  123. return Value(js_string(global_object.vm(), value.typeof()));
  124. }
  125. #define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  126. ThrowCompletionOr<void> OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
  127. { \
  128. interpreter.accumulator() = TRY(op_snake_case(interpreter.global_object(), interpreter.accumulator())); \
  129. return {}; \
  130. } \
  131. String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
  132. { \
  133. return #OpTitleCase; \
  134. }
  135. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP)
  136. ThrowCompletionOr<void> NewBigInt::execute_impl(Bytecode::Interpreter& interpreter) const
  137. {
  138. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint);
  139. return {};
  140. }
  141. ThrowCompletionOr<void> NewArray::execute_impl(Bytecode::Interpreter& interpreter) const
  142. {
  143. auto* array = MUST(Array::create(interpreter.global_object(), 0));
  144. for (size_t i = 0; i < m_element_count; i++) {
  145. auto& value = interpreter.reg(Register(m_elements[0].index() + i));
  146. array->indexed_properties().put(i, value, default_attributes);
  147. }
  148. interpreter.accumulator() = array;
  149. return {};
  150. }
  151. // FIXME: Since the accumulator is a Value, we store an object there and have to convert back and forth between that an Iterator records. Not great.
  152. // Make sure to put this into the accumulator before the iterator object disappears from the stack to prevent the members from being GC'd.
  153. static Object* iterator_to_object(GlobalObject& global_object, Iterator iterator)
  154. {
  155. auto& vm = global_object.vm();
  156. auto* object = Object::create(global_object, nullptr);
  157. object->define_direct_property(vm.names.iterator, iterator.iterator, 0);
  158. object->define_direct_property(vm.names.next, iterator.next_method, 0);
  159. object->define_direct_property(vm.names.done, Value(iterator.done), 0);
  160. return object;
  161. }
  162. static Iterator object_to_iterator(GlobalObject& global_object, Object& object)
  163. {
  164. auto& vm = global_object.vm();
  165. return Iterator {
  166. .iterator = &MUST(object.get(vm.names.iterator)).as_object(),
  167. .next_method = MUST(object.get(vm.names.next)),
  168. .done = MUST(object.get(vm.names.done)).as_bool()
  169. };
  170. }
  171. ThrowCompletionOr<void> IteratorToArray::execute_impl(Bytecode::Interpreter& interpreter) const
  172. {
  173. auto& global_object = interpreter.global_object();
  174. auto iterator_object = TRY(interpreter.accumulator().to_object(global_object));
  175. auto iterator = object_to_iterator(global_object, *iterator_object);
  176. auto* array = MUST(Array::create(global_object, 0));
  177. size_t index = 0;
  178. while (true) {
  179. auto* iterator_result = TRY(iterator_next(global_object, iterator));
  180. auto complete = TRY(iterator_complete(global_object, *iterator_result));
  181. if (complete) {
  182. interpreter.accumulator() = array;
  183. return {};
  184. }
  185. auto value = TRY(iterator_value(global_object, *iterator_result));
  186. MUST(array->create_data_property_or_throw(index, value));
  187. index++;
  188. }
  189. return {};
  190. }
  191. ThrowCompletionOr<void> NewString::execute_impl(Bytecode::Interpreter& interpreter) const
  192. {
  193. interpreter.accumulator() = js_string(interpreter.vm(), interpreter.current_executable().get_string(m_string));
  194. return {};
  195. }
  196. ThrowCompletionOr<void> NewObject::execute_impl(Bytecode::Interpreter& interpreter) const
  197. {
  198. interpreter.accumulator() = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
  199. return {};
  200. }
  201. ThrowCompletionOr<void> NewRegExp::execute_impl(Bytecode::Interpreter& interpreter) const
  202. {
  203. auto source = interpreter.current_executable().get_string(m_source_index);
  204. auto flags = interpreter.current_executable().get_string(m_flags_index);
  205. interpreter.accumulator() = TRY(regexp_create(interpreter.global_object(), js_string(interpreter.vm(), source), js_string(interpreter.vm(), flags)));
  206. return {};
  207. }
  208. ThrowCompletionOr<void> CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpreter) const
  209. {
  210. auto* from_object = TRY(interpreter.reg(m_from_object).to_object(interpreter.global_object()));
  211. auto* to_object = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
  212. HashTable<Value, ValueTraits> excluded_names;
  213. for (size_t i = 0; i < m_excluded_names_count; ++i)
  214. excluded_names.set(interpreter.reg(m_excluded_names[i]));
  215. auto own_keys = TRY(from_object->internal_own_property_keys());
  216. for (auto& key : own_keys) {
  217. if (!excluded_names.contains(key)) {
  218. auto property_key = TRY(key.to_property_key(interpreter.global_object()));
  219. auto property_value = TRY(from_object->get(property_key));
  220. to_object->define_direct_property(property_key, property_value, JS::default_attributes);
  221. }
  222. }
  223. interpreter.accumulator() = to_object;
  224. return {};
  225. }
  226. ThrowCompletionOr<void> ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const
  227. {
  228. interpreter.reg(m_lhs) = TRY(add(interpreter.global_object(), interpreter.reg(m_lhs), interpreter.accumulator()));
  229. return {};
  230. }
  231. ThrowCompletionOr<void> GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  232. {
  233. auto get_reference = [&]() -> ThrowCompletionOr<Reference> {
  234. auto const& string = interpreter.current_executable().get_identifier(m_identifier);
  235. if (m_cached_environment_coordinate.has_value()) {
  236. auto* environment = interpreter.vm().running_execution_context().lexical_environment;
  237. for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i)
  238. environment = environment->outer_environment();
  239. VERIFY(environment);
  240. VERIFY(environment->is_declarative_environment());
  241. if (!environment->is_permanently_screwed_by_eval()) {
  242. return Reference { *environment, string, interpreter.vm().in_strict_mode(), m_cached_environment_coordinate };
  243. }
  244. m_cached_environment_coordinate = {};
  245. }
  246. auto reference = TRY(interpreter.vm().resolve_binding(string));
  247. if (reference.environment_coordinate().has_value())
  248. m_cached_environment_coordinate = reference.environment_coordinate();
  249. return reference;
  250. };
  251. auto reference = TRY(get_reference());
  252. interpreter.accumulator() = TRY(reference.get_value(interpreter.global_object()));
  253. return {};
  254. }
  255. ThrowCompletionOr<void> DeleteVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  256. {
  257. auto const& string = interpreter.current_executable().get_identifier(m_identifier);
  258. auto reference = TRY(interpreter.vm().resolve_binding(string));
  259. interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object())));
  260. return {};
  261. }
  262. ThrowCompletionOr<void> CreateEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
  263. {
  264. auto make_and_swap_envs = [&](auto*& old_environment) {
  265. Environment* environment = new_declarative_environment(*old_environment);
  266. swap(old_environment, environment);
  267. return environment;
  268. };
  269. if (m_mode == EnvironmentMode::Lexical)
  270. interpreter.saved_lexical_environment_stack().append(make_and_swap_envs(interpreter.vm().running_execution_context().lexical_environment));
  271. else if (m_mode == EnvironmentMode::Var)
  272. interpreter.saved_variable_environment_stack().append(make_and_swap_envs(interpreter.vm().running_execution_context().variable_environment));
  273. return {};
  274. }
  275. ThrowCompletionOr<void> EnterObjectEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
  276. {
  277. auto& old_environment = interpreter.vm().running_execution_context().lexical_environment;
  278. interpreter.saved_lexical_environment_stack().append(old_environment);
  279. auto object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  280. interpreter.vm().running_execution_context().lexical_environment = new_object_environment(*object, true, old_environment);
  281. return {};
  282. }
  283. ThrowCompletionOr<void> CreateVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  284. {
  285. auto& vm = interpreter.vm();
  286. auto const& name = interpreter.current_executable().get_identifier(m_identifier);
  287. if (m_mode == EnvironmentMode::Lexical) {
  288. // Note: This is papering over an issue where "FunctionDeclarationInstantiation" creates these bindings for us.
  289. // Instead of crashing in there, we'll just raise an exception here.
  290. if (TRY(vm.lexical_environment()->has_binding(name)))
  291. return vm.throw_completion<InternalError>(interpreter.global_object(), String::formatted("Lexical environment already has binding '{}'", name));
  292. if (m_is_immutable)
  293. vm.lexical_environment()->create_immutable_binding(interpreter.global_object(), name, vm.in_strict_mode());
  294. else
  295. vm.lexical_environment()->create_mutable_binding(interpreter.global_object(), name, vm.in_strict_mode());
  296. } else {
  297. if (m_is_immutable)
  298. vm.variable_environment()->create_immutable_binding(interpreter.global_object(), name, vm.in_strict_mode());
  299. else
  300. vm.variable_environment()->create_mutable_binding(interpreter.global_object(), name, vm.in_strict_mode());
  301. }
  302. return {};
  303. }
  304. ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  305. {
  306. auto& vm = interpreter.vm();
  307. auto const& name = interpreter.current_executable().get_identifier(m_identifier);
  308. auto environment = m_mode == EnvironmentMode::Lexical ? vm.running_execution_context().lexical_environment : vm.running_execution_context().variable_environment;
  309. auto reference = TRY(vm.resolve_binding(name, environment));
  310. switch (m_initialization_mode) {
  311. case InitializationMode::Initialize:
  312. TRY(reference.initialize_referenced_binding(interpreter.global_object(), interpreter.accumulator()));
  313. break;
  314. case InitializationMode::Set:
  315. TRY(reference.put_value(interpreter.global_object(), interpreter.accumulator()));
  316. break;
  317. case InitializationMode::InitializeOrSet:
  318. VERIFY(reference.is_environment_reference());
  319. VERIFY(reference.base_environment().is_declarative_environment());
  320. TRY(static_cast<DeclarativeEnvironment&>(reference.base_environment()).initialize_or_set_mutable_binding(interpreter.global_object(), name, interpreter.accumulator()));
  321. break;
  322. }
  323. return {};
  324. }
  325. ThrowCompletionOr<void> GetById::execute_impl(Bytecode::Interpreter& interpreter) const
  326. {
  327. auto* object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  328. interpreter.accumulator() = TRY(object->get(interpreter.current_executable().get_identifier(m_property)));
  329. return {};
  330. }
  331. ThrowCompletionOr<void> PutById::execute_impl(Bytecode::Interpreter& interpreter) const
  332. {
  333. auto* object = TRY(interpreter.reg(m_base).to_object(interpreter.global_object()));
  334. PropertyKey name = interpreter.current_executable().get_identifier(m_property);
  335. auto value = interpreter.accumulator();
  336. return put_by_property_key(object, value, name, interpreter, m_kind);
  337. }
  338. ThrowCompletionOr<void> DeleteById::execute_impl(Bytecode::Interpreter& interpreter) const
  339. {
  340. auto* object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  341. auto const& identifier = interpreter.current_executable().get_identifier(m_property);
  342. bool strict = interpreter.vm().in_strict_mode();
  343. auto reference = Reference { object, identifier, {}, strict };
  344. interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object())));
  345. return {};
  346. };
  347. ThrowCompletionOr<void> Jump::execute_impl(Bytecode::Interpreter& interpreter) const
  348. {
  349. interpreter.jump(*m_true_target);
  350. return {};
  351. }
  352. ThrowCompletionOr<void> ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const
  353. {
  354. interpreter.accumulator() = TRY(interpreter.vm().resolve_this_binding(interpreter.global_object()));
  355. return {};
  356. }
  357. ThrowCompletionOr<void> GetNewTarget::execute_impl(Bytecode::Interpreter& interpreter) const
  358. {
  359. interpreter.accumulator() = interpreter.vm().get_new_target();
  360. return {};
  361. }
  362. void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  363. {
  364. if (m_true_target.has_value() && &m_true_target->block() == &from)
  365. m_true_target = Label { to };
  366. if (m_false_target.has_value() && &m_false_target->block() == &from)
  367. m_false_target = Label { to };
  368. }
  369. ThrowCompletionOr<void> JumpConditional::execute_impl(Bytecode::Interpreter& interpreter) const
  370. {
  371. VERIFY(m_true_target.has_value());
  372. VERIFY(m_false_target.has_value());
  373. auto result = interpreter.accumulator();
  374. if (result.to_boolean())
  375. interpreter.jump(m_true_target.value());
  376. else
  377. interpreter.jump(m_false_target.value());
  378. return {};
  379. }
  380. ThrowCompletionOr<void> JumpNullish::execute_impl(Bytecode::Interpreter& interpreter) const
  381. {
  382. VERIFY(m_true_target.has_value());
  383. VERIFY(m_false_target.has_value());
  384. auto result = interpreter.accumulator();
  385. if (result.is_nullish())
  386. interpreter.jump(m_true_target.value());
  387. else
  388. interpreter.jump(m_false_target.value());
  389. return {};
  390. }
  391. ThrowCompletionOr<void> JumpUndefined::execute_impl(Bytecode::Interpreter& interpreter) const
  392. {
  393. VERIFY(m_true_target.has_value());
  394. VERIFY(m_false_target.has_value());
  395. auto result = interpreter.accumulator();
  396. if (result.is_undefined())
  397. interpreter.jump(m_true_target.value());
  398. else
  399. interpreter.jump(m_false_target.value());
  400. return {};
  401. }
  402. ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) const
  403. {
  404. auto callee = interpreter.reg(m_callee);
  405. if (m_type == CallType::Call && !callee.is_function())
  406. return interpreter.vm().throw_completion<TypeError>(interpreter.global_object(), ErrorType::IsNotA, callee.to_string_without_side_effects(), "function"sv);
  407. if (m_type == CallType::Construct && !callee.is_constructor())
  408. return interpreter.vm().throw_completion<TypeError>(interpreter.global_object(), ErrorType::IsNotA, callee.to_string_without_side_effects(), "constructor"sv);
  409. auto& function = callee.as_function();
  410. auto this_value = interpreter.reg(m_this_value);
  411. MarkedVector<Value> argument_values { interpreter.vm().heap() };
  412. for (size_t i = 0; i < m_argument_count; ++i)
  413. argument_values.append(interpreter.reg(m_arguments[i]));
  414. Value return_value;
  415. if (m_type == CallType::Call)
  416. return_value = TRY(call(interpreter.global_object(), function, this_value, move(argument_values)));
  417. else
  418. return_value = TRY(construct(interpreter.global_object(), function, move(argument_values)));
  419. interpreter.accumulator() = return_value;
  420. return {};
  421. }
  422. ThrowCompletionOr<void> NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const
  423. {
  424. auto& vm = interpreter.vm();
  425. interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.source_text(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.is_arrow_function());
  426. return {};
  427. }
  428. ThrowCompletionOr<void> Return::execute_impl(Bytecode::Interpreter& interpreter) const
  429. {
  430. interpreter.do_return(interpreter.accumulator().value_or(js_undefined()));
  431. return {};
  432. }
  433. ThrowCompletionOr<void> Increment::execute_impl(Bytecode::Interpreter& interpreter) const
  434. {
  435. auto old_value = TRY(interpreter.accumulator().to_numeric(interpreter.global_object()));
  436. if (old_value.is_number())
  437. interpreter.accumulator() = Value(old_value.as_double() + 1);
  438. else
  439. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 }));
  440. return {};
  441. }
  442. ThrowCompletionOr<void> Decrement::execute_impl(Bytecode::Interpreter& interpreter) const
  443. {
  444. auto old_value = TRY(interpreter.accumulator().to_numeric(interpreter.global_object()));
  445. if (old_value.is_number())
  446. interpreter.accumulator() = Value(old_value.as_double() - 1);
  447. else
  448. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 }));
  449. return {};
  450. }
  451. ThrowCompletionOr<void> Throw::execute_impl(Bytecode::Interpreter& interpreter) const
  452. {
  453. return throw_completion(interpreter.accumulator());
  454. }
  455. ThrowCompletionOr<void> EnterUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
  456. {
  457. interpreter.enter_unwind_context(m_handler_target, m_finalizer_target);
  458. interpreter.jump(m_entry_point);
  459. return {};
  460. }
  461. void EnterUnwindContext::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  462. {
  463. if (&m_entry_point.block() == &from)
  464. m_entry_point = Label { to };
  465. if (m_handler_target.has_value() && &m_handler_target->block() == &from)
  466. m_handler_target = Label { to };
  467. if (m_finalizer_target.has_value() && &m_finalizer_target->block() == &from)
  468. m_finalizer_target = Label { to };
  469. }
  470. ThrowCompletionOr<void> FinishUnwind::execute_impl(Bytecode::Interpreter& interpreter) const
  471. {
  472. interpreter.leave_unwind_context();
  473. interpreter.jump(m_next_target);
  474. return {};
  475. }
  476. void FinishUnwind::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  477. {
  478. if (&m_next_target.block() == &from)
  479. m_next_target = Label { to };
  480. }
  481. ThrowCompletionOr<void> LeaveEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
  482. {
  483. if (m_mode == EnvironmentMode::Lexical)
  484. interpreter.vm().running_execution_context().lexical_environment = interpreter.saved_lexical_environment_stack().take_last();
  485. if (m_mode == EnvironmentMode::Var)
  486. interpreter.vm().running_execution_context().variable_environment = interpreter.saved_variable_environment_stack().take_last();
  487. return {};
  488. }
  489. ThrowCompletionOr<void> LeaveUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
  490. {
  491. interpreter.leave_unwind_context();
  492. return {};
  493. }
  494. ThrowCompletionOr<void> ContinuePendingUnwind::execute_impl(Bytecode::Interpreter& interpreter) const
  495. {
  496. return interpreter.continue_pending_unwind(m_resume_target);
  497. }
  498. void ContinuePendingUnwind::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  499. {
  500. if (&m_resume_target.block() == &from)
  501. m_resume_target = Label { to };
  502. }
  503. ThrowCompletionOr<void> PushDeclarativeEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
  504. {
  505. auto* environment = interpreter.vm().heap().allocate_without_global_object<DeclarativeEnvironment>(interpreter.vm().lexical_environment());
  506. interpreter.vm().running_execution_context().lexical_environment = environment;
  507. interpreter.vm().running_execution_context().variable_environment = environment;
  508. return {};
  509. }
  510. ThrowCompletionOr<void> Yield::execute_impl(Bytecode::Interpreter& interpreter) const
  511. {
  512. auto yielded_value = interpreter.accumulator().value_or(js_undefined());
  513. auto object = JS::Object::create(interpreter.global_object(), nullptr);
  514. object->define_direct_property("result", yielded_value, JS::default_attributes);
  515. if (m_continuation_label.has_value())
  516. object->define_direct_property("continuation", Value(static_cast<double>(reinterpret_cast<u64>(&m_continuation_label->block()))), JS::default_attributes);
  517. else
  518. object->define_direct_property("continuation", Value(0), JS::default_attributes);
  519. interpreter.do_return(object);
  520. return {};
  521. }
  522. void Yield::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  523. {
  524. if (m_continuation_label.has_value() && &m_continuation_label->block() == &from)
  525. m_continuation_label = Label { to };
  526. }
  527. ThrowCompletionOr<void> GetByValue::execute_impl(Bytecode::Interpreter& interpreter) const
  528. {
  529. auto* object = TRY(interpreter.reg(m_base).to_object(interpreter.global_object()));
  530. auto property_key = TRY(interpreter.accumulator().to_property_key(interpreter.global_object()));
  531. interpreter.accumulator() = TRY(object->get(property_key));
  532. return {};
  533. }
  534. ThrowCompletionOr<void> PutByValue::execute_impl(Bytecode::Interpreter& interpreter) const
  535. {
  536. auto* object = TRY(interpreter.reg(m_base).to_object(interpreter.global_object()));
  537. auto property_key = TRY(interpreter.reg(m_property).to_property_key(interpreter.global_object()));
  538. return put_by_property_key(object, interpreter.accumulator(), property_key, interpreter, m_kind);
  539. }
  540. ThrowCompletionOr<void> DeleteByValue::execute_impl(Bytecode::Interpreter& interpreter) const
  541. {
  542. auto* object = TRY(interpreter.reg(m_base).to_object(interpreter.global_object()));
  543. auto property_key = TRY(interpreter.accumulator().to_property_key(interpreter.global_object()));
  544. bool strict = interpreter.vm().in_strict_mode();
  545. auto reference = Reference { object, property_key, {}, strict };
  546. interpreter.accumulator() = Value(TRY(reference.delete_(interpreter.global_object())));
  547. return {};
  548. }
  549. ThrowCompletionOr<void> GetIterator::execute_impl(Bytecode::Interpreter& interpreter) const
  550. {
  551. auto iterator = TRY(get_iterator(interpreter.global_object(), interpreter.accumulator()));
  552. interpreter.accumulator() = iterator_to_object(interpreter.global_object(), iterator);
  553. return {};
  554. }
  555. // 14.7.5.9 EnumerateObjectProperties ( O ), https://tc39.es/ecma262/#sec-enumerate-object-properties
  556. ThrowCompletionOr<void> GetObjectPropertyIterator::execute_impl(Bytecode::Interpreter& interpreter) const
  557. {
  558. // While the spec does provide an algorithm, it allows us to implement it ourselves so long as we meet the following invariants:
  559. // 1- Returned property keys do not include keys that are Symbols
  560. // 2- Properties of the target object may be deleted during enumeration. A property that is deleted before it is processed by the iterator's next method is ignored
  561. // 3- If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration
  562. // 4- A property name will be returned by the iterator's next method at most once in any enumeration.
  563. // 5- Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively;
  564. // but a property of a prototype is not processed if it has the same name as a property that has already been processed by the iterator's next method.
  565. // 6- The values of [[Enumerable]] attributes are not considered when determining if a property of a prototype object has already been processed.
  566. // 7- The enumerable property names of prototype objects must be obtained by invoking EnumerateObjectProperties passing the prototype object as the argument.
  567. // 8- EnumerateObjectProperties must obtain the own property keys of the target object by calling its [[OwnPropertyKeys]] internal method.
  568. // 9- Property attributes of the target object must be obtained by calling its [[GetOwnProperty]] internal method
  569. // Invariant 3 effectively allows the implementation to ignore newly added keys, and we do so (similar to other implementations).
  570. // Invariants 1 and 6 through 9 are implemented in `enumerable_own_property_names`, which implements the EnumerableOwnPropertyNames AO.
  571. auto* object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  572. // Note: While the spec doesn't explicitly require these to be ordered, it says that the values should be retrieved via OwnPropertyKeys,
  573. // so we just keep the order consistent anyway.
  574. OrderedHashTable<PropertyKey> properties;
  575. HashTable<Object*> seen_objects;
  576. // Collect all keys immediately (invariant no. 5)
  577. for (auto* object_to_check = object; object_to_check && !seen_objects.contains(object_to_check); object_to_check = TRY(object_to_check->internal_get_prototype_of())) {
  578. seen_objects.set(object_to_check);
  579. for (auto& key : TRY(object_to_check->enumerable_own_property_names(Object::PropertyKind::Key))) {
  580. properties.set(TRY(PropertyKey::from_value(interpreter.global_object(), key)));
  581. }
  582. }
  583. Iterator iterator {
  584. .iterator = object,
  585. .next_method = NativeFunction::create(
  586. interpreter.global_object(),
  587. [seen_items = HashTable<PropertyKey>(), items = move(properties)](VM& vm, GlobalObject& global_object) mutable -> ThrowCompletionOr<Value> {
  588. auto iterated_object_value = vm.this_value(global_object);
  589. if (!iterated_object_value.is_object())
  590. return vm.throw_completion<InternalError>(global_object, "Invalid state for GetObjectPropertyIterator.next");
  591. auto& iterated_object = iterated_object_value.as_object();
  592. auto* result_object = Object::create(global_object, nullptr);
  593. while (true) {
  594. if (items.is_empty()) {
  595. result_object->define_direct_property(vm.names.done, JS::Value(true), default_attributes);
  596. return result_object;
  597. }
  598. auto it = items.begin();
  599. auto key = *it;
  600. items.remove(it);
  601. // If the key was already seen, skip over it (invariant no. 4)
  602. auto result = seen_items.set(key);
  603. if (result != AK::HashSetResult::InsertedNewEntry)
  604. continue;
  605. // If the property is deleted, don't include it (invariant no. 2)
  606. if (!TRY(iterated_object.has_property(key)))
  607. continue;
  608. result_object->define_direct_property(vm.names.done, JS::Value(false), default_attributes);
  609. if (key.is_number())
  610. result_object->define_direct_property(vm.names.value, JS::Value(key.as_number()), default_attributes);
  611. else if (key.is_string())
  612. result_object->define_direct_property(vm.names.value, js_string(vm.heap(), key.as_string()), default_attributes);
  613. else
  614. VERIFY_NOT_REACHED(); // We should not have non-string/number keys.
  615. return result_object;
  616. }
  617. },
  618. 1,
  619. interpreter.vm().names.next),
  620. .done = false,
  621. };
  622. interpreter.accumulator() = iterator_to_object(interpreter.global_object(), move(iterator));
  623. return {};
  624. }
  625. ThrowCompletionOr<void> IteratorNext::execute_impl(Bytecode::Interpreter& interpreter) const
  626. {
  627. auto* iterator_object = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  628. auto iterator = object_to_iterator(interpreter.global_object(), *iterator_object);
  629. interpreter.accumulator() = TRY(iterator_next(interpreter.global_object(), iterator));
  630. return {};
  631. }
  632. ThrowCompletionOr<void> IteratorResultDone::execute_impl(Bytecode::Interpreter& interpreter) const
  633. {
  634. auto* iterator_result = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  635. auto complete = TRY(iterator_complete(interpreter.global_object(), *iterator_result));
  636. interpreter.accumulator() = Value(complete);
  637. return {};
  638. }
  639. ThrowCompletionOr<void> IteratorResultValue::execute_impl(Bytecode::Interpreter& interpreter) const
  640. {
  641. auto* iterator_result = TRY(interpreter.accumulator().to_object(interpreter.global_object()));
  642. interpreter.accumulator() = TRY(iterator_value(interpreter.global_object(), *iterator_result));
  643. return {};
  644. }
  645. ThrowCompletionOr<void> NewClass::execute_impl(Bytecode::Interpreter& interpreter) const
  646. {
  647. auto name = m_class_expression.name();
  648. auto scope = interpreter.ast_interpreter_scope();
  649. auto& ast_interpreter = scope.interpreter();
  650. auto class_object = TRY(m_class_expression.class_definition_evaluation(ast_interpreter, interpreter.global_object(), name, name.is_null() ? "" : name));
  651. interpreter.accumulator() = class_object;
  652. return {};
  653. }
  654. String Load::to_string_impl(Bytecode::Executable const&) const
  655. {
  656. return String::formatted("Load {}", m_src);
  657. }
  658. String LoadImmediate::to_string_impl(Bytecode::Executable const&) const
  659. {
  660. return String::formatted("LoadImmediate {}", m_value);
  661. }
  662. String Store::to_string_impl(Bytecode::Executable const&) const
  663. {
  664. return String::formatted("Store {}", m_dst);
  665. }
  666. String NewBigInt::to_string_impl(Bytecode::Executable const&) const
  667. {
  668. return String::formatted("NewBigInt \"{}\"", m_bigint.to_base(10));
  669. }
  670. String NewArray::to_string_impl(Bytecode::Executable const&) const
  671. {
  672. StringBuilder builder;
  673. builder.append("NewArray");
  674. if (m_element_count != 0) {
  675. builder.appendff(" [{}-{}]", m_elements[0], m_elements[1]);
  676. }
  677. return builder.to_string();
  678. }
  679. String IteratorToArray::to_string_impl(Bytecode::Executable const&) const
  680. {
  681. return "IteratorToArray";
  682. }
  683. String NewString::to_string_impl(Bytecode::Executable const& executable) const
  684. {
  685. return String::formatted("NewString {} (\"{}\")", m_string, executable.string_table->get(m_string));
  686. }
  687. String NewObject::to_string_impl(Bytecode::Executable const&) const
  688. {
  689. return "NewObject";
  690. }
  691. String NewRegExp::to_string_impl(Bytecode::Executable const& executable) const
  692. {
  693. return String::formatted("NewRegExp source:{} (\"{}\") flags:{} (\"{}\")", m_source_index, executable.get_string(m_source_index), m_flags_index, executable.get_string(m_flags_index));
  694. }
  695. String CopyObjectExcludingProperties::to_string_impl(Bytecode::Executable const&) const
  696. {
  697. StringBuilder builder;
  698. builder.appendff("CopyObjectExcludingProperties from:{}", m_from_object);
  699. if (m_excluded_names_count != 0) {
  700. builder.append(" excluding:[");
  701. for (size_t i = 0; i < m_excluded_names_count; ++i) {
  702. builder.appendff("{}", m_excluded_names[i]);
  703. if (i != m_excluded_names_count - 1)
  704. builder.append(',');
  705. }
  706. builder.append(']');
  707. }
  708. return builder.to_string();
  709. }
  710. String ConcatString::to_string_impl(Bytecode::Executable const&) const
  711. {
  712. return String::formatted("ConcatString {}", m_lhs);
  713. }
  714. String GetVariable::to_string_impl(Bytecode::Executable const& executable) const
  715. {
  716. return String::formatted("GetVariable {} ({})", m_identifier, executable.identifier_table->get(m_identifier));
  717. }
  718. String DeleteVariable::to_string_impl(Bytecode::Executable const& executable) const
  719. {
  720. return String::formatted("DeleteVariable {} ({})", m_identifier, executable.identifier_table->get(m_identifier));
  721. }
  722. String CreateEnvironment::to_string_impl(Bytecode::Executable const&) const
  723. {
  724. auto mode_string = m_mode == EnvironmentMode::Lexical
  725. ? "Lexical"
  726. : "Variable";
  727. return String::formatted("CreateEnvironment mode:{}", mode_string);
  728. }
  729. String CreateVariable::to_string_impl(Bytecode::Executable const& executable) const
  730. {
  731. auto mode_string = m_mode == EnvironmentMode::Lexical ? "Lexical" : "Variable";
  732. return String::formatted("CreateVariable env:{} immutable:{} {} ({})", mode_string, m_is_immutable, m_identifier, executable.identifier_table->get(m_identifier));
  733. }
  734. String EnterObjectEnvironment::to_string_impl(Executable const&) const
  735. {
  736. return String::formatted("EnterObjectEnvironment");
  737. }
  738. String SetVariable::to_string_impl(Bytecode::Executable const& executable) const
  739. {
  740. auto initialization_mode_name = m_initialization_mode == InitializationMode ::Initialize ? "Initialize"
  741. : m_initialization_mode == InitializationMode::Set ? "Set"
  742. : "InitializeOrSet";
  743. auto mode_string = m_mode == EnvironmentMode::Lexical ? "Lexical" : "Variable";
  744. return String::formatted("SetVariable env:{} init:{} {} ({})", mode_string, initialization_mode_name, m_identifier, executable.identifier_table->get(m_identifier));
  745. }
  746. String PutById::to_string_impl(Bytecode::Executable const& executable) const
  747. {
  748. auto kind = m_kind == PropertyKind::Getter
  749. ? "getter"
  750. : m_kind == PropertyKind::Setter
  751. ? "setter"
  752. : "property";
  753. return String::formatted("PutById kind:{} base:{}, property:{} ({})", kind, m_base, m_property, executable.identifier_table->get(m_property));
  754. }
  755. String GetById::to_string_impl(Bytecode::Executable const& executable) const
  756. {
  757. return String::formatted("GetById {} ({})", m_property, executable.identifier_table->get(m_property));
  758. }
  759. String DeleteById::to_string_impl(Bytecode::Executable const& executable) const
  760. {
  761. return String::formatted("DeleteById {} ({})", m_property, executable.identifier_table->get(m_property));
  762. }
  763. String Jump::to_string_impl(Bytecode::Executable const&) const
  764. {
  765. if (m_true_target.has_value())
  766. return String::formatted("Jump {}", *m_true_target);
  767. return String::formatted("Jump <empty>");
  768. }
  769. String JumpConditional::to_string_impl(Bytecode::Executable const&) const
  770. {
  771. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  772. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  773. return String::formatted("JumpConditional true:{} false:{}", true_string, false_string);
  774. }
  775. String JumpNullish::to_string_impl(Bytecode::Executable const&) const
  776. {
  777. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  778. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  779. return String::formatted("JumpNullish null:{} nonnull:{}", true_string, false_string);
  780. }
  781. String JumpUndefined::to_string_impl(Bytecode::Executable const&) const
  782. {
  783. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  784. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  785. return String::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string);
  786. }
  787. String Call::to_string_impl(Bytecode::Executable const&) const
  788. {
  789. StringBuilder builder;
  790. builder.appendff("Call callee:{}, this:{}", m_callee, m_this_value);
  791. if (m_argument_count != 0) {
  792. builder.append(", arguments:[");
  793. for (size_t i = 0; i < m_argument_count; ++i) {
  794. builder.appendff("{}", m_arguments[i]);
  795. if (i != m_argument_count - 1)
  796. builder.append(',');
  797. }
  798. builder.append(']');
  799. }
  800. return builder.to_string();
  801. }
  802. String NewFunction::to_string_impl(Bytecode::Executable const&) const
  803. {
  804. return "NewFunction";
  805. }
  806. String NewClass::to_string_impl(Bytecode::Executable const&) const
  807. {
  808. return "NewClass";
  809. }
  810. String Return::to_string_impl(Bytecode::Executable const&) const
  811. {
  812. return "Return";
  813. }
  814. String Increment::to_string_impl(Bytecode::Executable const&) const
  815. {
  816. return "Increment";
  817. }
  818. String Decrement::to_string_impl(Bytecode::Executable const&) const
  819. {
  820. return "Decrement";
  821. }
  822. String Throw::to_string_impl(Bytecode::Executable const&) const
  823. {
  824. return "Throw";
  825. }
  826. String EnterUnwindContext::to_string_impl(Bytecode::Executable const&) const
  827. {
  828. auto handler_string = m_handler_target.has_value() ? String::formatted("{}", *m_handler_target) : "<empty>";
  829. auto finalizer_string = m_finalizer_target.has_value() ? String::formatted("{}", *m_finalizer_target) : "<empty>";
  830. return String::formatted("EnterUnwindContext handler:{} finalizer:{} entry:{}", handler_string, finalizer_string, m_entry_point);
  831. }
  832. String FinishUnwind::to_string_impl(Bytecode::Executable const&) const
  833. {
  834. return String::formatted("FinishUnwind next:{}", m_next_target);
  835. }
  836. String LeaveEnvironment::to_string_impl(Bytecode::Executable const&) const
  837. {
  838. auto mode_string = m_mode == EnvironmentMode::Lexical
  839. ? "Lexical"
  840. : "Variable";
  841. return String::formatted("LeaveEnvironment env:{}", mode_string);
  842. }
  843. String LeaveUnwindContext::to_string_impl(Bytecode::Executable const&) const
  844. {
  845. return "LeaveUnwindContext";
  846. }
  847. String ContinuePendingUnwind::to_string_impl(Bytecode::Executable const&) const
  848. {
  849. return String::formatted("ContinuePendingUnwind resume:{}", m_resume_target);
  850. }
  851. String PushDeclarativeEnvironment::to_string_impl(Bytecode::Executable const& executable) const
  852. {
  853. StringBuilder builder;
  854. builder.append("PushDeclarativeEnvironment");
  855. if (!m_variables.is_empty()) {
  856. builder.append(" {");
  857. Vector<String> names;
  858. for (auto& it : m_variables)
  859. names.append(executable.get_string(it.key));
  860. builder.join(", ", names);
  861. builder.append("}");
  862. }
  863. return builder.to_string();
  864. }
  865. String Yield::to_string_impl(Bytecode::Executable const&) const
  866. {
  867. if (m_continuation_label.has_value())
  868. return String::formatted("Yield continuation:@{}", m_continuation_label->block().name());
  869. return String::formatted("Yield return");
  870. }
  871. String GetByValue::to_string_impl(Bytecode::Executable const&) const
  872. {
  873. return String::formatted("GetByValue base:{}", m_base);
  874. }
  875. String PutByValue::to_string_impl(Bytecode::Executable const&) const
  876. {
  877. auto kind = m_kind == PropertyKind::Getter
  878. ? "getter"
  879. : m_kind == PropertyKind::Setter
  880. ? "setter"
  881. : "property";
  882. return String::formatted("PutByValue kind:{} base:{}, property:{}", kind, m_base, m_property);
  883. }
  884. String DeleteByValue::to_string_impl(Bytecode::Executable const&) const
  885. {
  886. return String::formatted("DeleteByValue base:{}", m_base);
  887. }
  888. String GetIterator::to_string_impl(Executable const&) const
  889. {
  890. return "GetIterator";
  891. }
  892. String GetObjectPropertyIterator::to_string_impl(Bytecode::Executable const&) const
  893. {
  894. return "GetObjectPropertyIterator";
  895. }
  896. String IteratorNext::to_string_impl(Executable const&) const
  897. {
  898. return "IteratorNext";
  899. }
  900. String IteratorResultDone::to_string_impl(Executable const&) const
  901. {
  902. return "IteratorResultDone";
  903. }
  904. String IteratorResultValue::to_string_impl(Executable const&) const
  905. {
  906. return "IteratorResultValue";
  907. }
  908. String ResolveThisBinding::to_string_impl(Bytecode::Executable const&) const
  909. {
  910. return "ResolveThisBinding"sv;
  911. }
  912. String GetNewTarget::to_string_impl(Bytecode::Executable const&) const
  913. {
  914. return "GetNewTarget"sv;
  915. }
  916. }