AbstractOperations.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Function.h>
  8. #include <AK/Result.h>
  9. #include <AK/TemporaryChange.h>
  10. #include <LibJS/Interpreter.h>
  11. #include <LibJS/Parser.h>
  12. #include <LibJS/Runtime/AbstractOperations.h>
  13. #include <LibJS/Runtime/BoundFunction.h>
  14. #include <LibJS/Runtime/DeclarativeEnvironmentRecord.h>
  15. #include <LibJS/Runtime/ErrorTypes.h>
  16. #include <LibJS/Runtime/Function.h>
  17. #include <LibJS/Runtime/FunctionEnvironmentRecord.h>
  18. #include <LibJS/Runtime/GlobalEnvironmentRecord.h>
  19. #include <LibJS/Runtime/GlobalObject.h>
  20. #include <LibJS/Runtime/Object.h>
  21. #include <LibJS/Runtime/ObjectEnvironmentRecord.h>
  22. #include <LibJS/Runtime/PropertyName.h>
  23. #include <LibJS/Runtime/ProxyObject.h>
  24. namespace JS {
  25. // Used in various abstract operations to make it obvious when a non-optional return value must be discarded.
  26. static constexpr double INVALID { 0 };
  27. // 7.2.1 RequireObjectCoercible ( argument ), https://tc39.es/ecma262/#sec-requireobjectcoercible
  28. Value require_object_coercible(GlobalObject& global_object, Value value)
  29. {
  30. auto& vm = global_object.vm();
  31. if (value.is_nullish()) {
  32. vm.throw_exception<TypeError>(global_object, ErrorType::NotObjectCoercible, value.to_string_without_side_effects());
  33. return {};
  34. }
  35. return value;
  36. }
  37. // 7.3.18 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
  38. size_t length_of_array_like(GlobalObject& global_object, Object const& object)
  39. {
  40. auto& vm = global_object.vm();
  41. auto result = object.get(vm.names.length).value_or(js_undefined());
  42. if (vm.exception())
  43. return INVALID;
  44. return result.to_length(global_object);
  45. }
  46. // 7.3.19 CreateListFromArrayLike ( obj [ , elementTypes ] ), https://tc39.es/ecma262/#sec-createlistfromarraylike
  47. MarkedValueList create_list_from_array_like(GlobalObject& global_object, Value value, AK::Function<Result<void, ErrorType>(Value)> check_value)
  48. {
  49. auto& vm = global_object.vm();
  50. auto& heap = global_object.heap();
  51. if (!value.is_object()) {
  52. vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
  53. return MarkedValueList { heap };
  54. }
  55. auto& array_like = value.as_object();
  56. auto length = length_of_array_like(global_object, array_like);
  57. if (vm.exception())
  58. return MarkedValueList { heap };
  59. auto list = MarkedValueList { heap };
  60. for (size_t i = 0; i < length; ++i) {
  61. auto index_name = String::number(i);
  62. auto next = array_like.get(index_name).value_or(js_undefined());
  63. if (vm.exception())
  64. return MarkedValueList { heap };
  65. if (check_value) {
  66. auto result = check_value(next);
  67. if (result.is_error()) {
  68. vm.throw_exception<TypeError>(global_object, result.release_error());
  69. return MarkedValueList { heap };
  70. }
  71. }
  72. list.append(next);
  73. }
  74. return list;
  75. }
  76. // 7.3.22 SpeciesConstructor ( O, defaultConstructor ), https://tc39.es/ecma262/#sec-speciesconstructor
  77. Function* species_constructor(GlobalObject& global_object, Object const& object, Function& default_constructor)
  78. {
  79. auto& vm = global_object.vm();
  80. auto constructor = object.get(vm.names.constructor).value_or(js_undefined());
  81. if (vm.exception())
  82. return nullptr;
  83. if (constructor.is_undefined())
  84. return &default_constructor;
  85. if (!constructor.is_object()) {
  86. vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, constructor.to_string_without_side_effects());
  87. return nullptr;
  88. }
  89. auto species = constructor.as_object().get(*vm.well_known_symbol_species()).value_or(js_undefined());
  90. if (species.is_nullish())
  91. return &default_constructor;
  92. if (species.is_constructor())
  93. return &species.as_function();
  94. vm.throw_exception<TypeError>(global_object, ErrorType::NotAConstructor, species.to_string_without_side_effects());
  95. return nullptr;
  96. }
  97. // 7.3.24 GetFunctionRealm ( obj ), https://tc39.es/ecma262/#sec-getfunctionrealm
  98. GlobalObject* get_function_realm(GlobalObject& global_object, Function const& function)
  99. {
  100. auto& vm = global_object.vm();
  101. // FIXME: not sure how to do this currently.
  102. // 2. If obj has a [[Realm]] internal slot, then
  103. // a. Return obj.[[Realm]].
  104. if (is<BoundFunction>(function)) {
  105. auto& bound_function = static_cast<BoundFunction const&>(function);
  106. auto& target = bound_function.target_function();
  107. return get_function_realm(global_object, target);
  108. }
  109. if (is<ProxyObject>(function)) {
  110. auto& proxy = static_cast<ProxyObject const&>(function);
  111. if (proxy.is_revoked()) {
  112. vm.throw_exception<TypeError>(global_object, ErrorType::ProxyRevoked);
  113. return nullptr;
  114. }
  115. auto& proxy_target = proxy.target();
  116. VERIFY(proxy_target.is_function());
  117. return get_function_realm(global_object, static_cast<Function const&>(proxy_target));
  118. }
  119. // 5. Return the current Realm Record.
  120. return &global_object;
  121. }
  122. // 10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
  123. Object* get_prototype_from_constructor(GlobalObject& global_object, Function const& constructor, Object* (GlobalObject::*intrinsic_default_prototype)())
  124. {
  125. auto& vm = global_object.vm();
  126. auto prototype = constructor.get(vm.names.prototype);
  127. if (vm.exception())
  128. return nullptr;
  129. if (!prototype.is_object()) {
  130. auto* realm = get_function_realm(global_object, constructor);
  131. if (vm.exception())
  132. return nullptr;
  133. prototype = (realm->*intrinsic_default_prototype)();
  134. }
  135. return &prototype.as_object();
  136. }
  137. // 9.1.2.2 NewDeclarativeEnvironment ( E ), https://tc39.es/ecma262/#sec-newdeclarativeenvironment
  138. DeclarativeEnvironmentRecord* new_declarative_environment(EnvironmentRecord& environment_record)
  139. {
  140. auto& global_object = environment_record.global_object();
  141. return global_object.heap().allocate<DeclarativeEnvironmentRecord>(global_object, &environment_record);
  142. }
  143. // 9.1.2.3 NewObjectEnvironment ( O, W, E ), https://tc39.es/ecma262/#sec-newobjectenvironment
  144. ObjectEnvironmentRecord* new_object_environment(Object& object, bool is_with_environment, EnvironmentRecord* environment_record)
  145. {
  146. auto& global_object = object.global_object();
  147. return global_object.heap().allocate<ObjectEnvironmentRecord>(global_object, object, is_with_environment ? ObjectEnvironmentRecord::IsWithEnvironment::Yes : ObjectEnvironmentRecord::IsWithEnvironment::No, environment_record);
  148. }
  149. // 9.4.3 GetThisEnvironment ( ), https://tc39.es/ecma262/#sec-getthisenvironment
  150. EnvironmentRecord& get_this_environment(VM& vm)
  151. {
  152. for (auto* env = vm.lexical_environment(); env; env = env->outer_environment()) {
  153. if (env->has_this_binding())
  154. return *env;
  155. }
  156. VERIFY_NOT_REACHED();
  157. }
  158. // 13.3.7.2 GetSuperConstructor ( ), https://tc39.es/ecma262/#sec-getsuperconstructor
  159. Object* get_super_constructor(VM& vm)
  160. {
  161. auto& env = get_this_environment(vm);
  162. auto& active_function = verify_cast<FunctionEnvironmentRecord>(env).function_object();
  163. auto* super_constructor = active_function.prototype();
  164. return super_constructor;
  165. }
  166. // 19.2.1.1 PerformEval ( x, callerRealm, strictCaller, direct ), https://tc39.es/ecma262/#sec-performeval
  167. Value perform_eval(Value x, GlobalObject& caller_realm, CallerMode strict_caller, EvalMode direct)
  168. {
  169. VERIFY(direct == EvalMode::Direct || strict_caller == CallerMode::NonStrict);
  170. if (!x.is_string())
  171. return x;
  172. auto& vm = caller_realm.vm();
  173. auto& code_string = x.as_string();
  174. Parser parser { Lexer { code_string.string() } };
  175. auto program = parser.parse_program(strict_caller == CallerMode::Strict);
  176. if (parser.has_errors()) {
  177. auto& error = parser.errors()[0];
  178. vm.throw_exception<SyntaxError>(caller_realm, error.to_string());
  179. return {};
  180. }
  181. auto& interpreter = vm.interpreter();
  182. if (direct == EvalMode::Direct)
  183. return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
  184. TemporaryChange scope_change(vm.running_execution_context().lexical_environment, static_cast<EnvironmentRecord*>(&caller_realm.environment_record()));
  185. return interpreter.execute_statement(caller_realm, program).value_or(js_undefined());
  186. }
  187. }