ProxyObject.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
  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. #include <LibJS/Interpreter.h>
  27. #include <LibJS/Runtime/Accessor.h>
  28. #include <LibJS/Runtime/Array.h>
  29. #include <LibJS/Runtime/Error.h>
  30. #include <LibJS/Runtime/GlobalObject.h>
  31. #include <LibJS/Runtime/ProxyObject.h>
  32. namespace JS {
  33. bool static is_compatible_property_descriptor(Interpreter& interpreter, bool is_extensible, PropertyDescriptor new_descriptor, Optional<PropertyDescriptor> current_descriptor_optional)
  34. {
  35. if (!current_descriptor_optional.has_value())
  36. return is_extensible;
  37. auto current_descriptor = current_descriptor_optional.value();
  38. if (new_descriptor.attributes.is_empty() && new_descriptor.value.is_empty() && !new_descriptor.getter && !new_descriptor.setter)
  39. return true;
  40. if (!current_descriptor.attributes.is_configurable()) {
  41. if (new_descriptor.attributes.is_configurable())
  42. return false;
  43. if (new_descriptor.attributes.has_enumerable() && new_descriptor.attributes.is_enumerable() != current_descriptor.attributes.is_enumerable())
  44. return false;
  45. }
  46. if (new_descriptor.is_generic_descriptor())
  47. return true;
  48. if (current_descriptor.is_data_descriptor() != new_descriptor.is_data_descriptor() && !current_descriptor.attributes.is_configurable())
  49. return false;
  50. if (current_descriptor.is_data_descriptor() && new_descriptor.is_data_descriptor() && !current_descriptor.attributes.is_configurable() && !current_descriptor.attributes.is_writable()) {
  51. if (new_descriptor.attributes.is_writable())
  52. return false;
  53. return new_descriptor.value.is_empty() && same_value(interpreter, new_descriptor.value, current_descriptor.value);
  54. }
  55. return true;
  56. }
  57. ProxyObject* ProxyObject::create(GlobalObject& global_object, Object& target, Object& handler)
  58. {
  59. return global_object.heap().allocate<ProxyObject>(global_object, target, handler, *global_object.proxy_prototype());
  60. }
  61. ProxyObject::ProxyObject(Object& target, Object& handler, Object& prototype)
  62. : Function(prototype)
  63. , m_target(target)
  64. , m_handler(handler)
  65. {
  66. }
  67. ProxyObject::~ProxyObject()
  68. {
  69. }
  70. Object* ProxyObject::prototype()
  71. {
  72. if (m_is_revoked) {
  73. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  74. return nullptr;
  75. }
  76. auto trap = m_handler.get("getPrototypeOf");
  77. if (interpreter().exception())
  78. return nullptr;
  79. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  80. return m_target.prototype();
  81. if (!trap.is_function()) {
  82. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "getPrototypeOf");
  83. return nullptr;
  84. }
  85. MarkedValueList arguments(interpreter().heap());
  86. arguments.values().append(Value(&m_target));
  87. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments));
  88. if (interpreter().exception())
  89. return nullptr;
  90. if (!trap_result.is_object() && !trap_result.is_null()) {
  91. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetPrototypeOfReturn);
  92. return nullptr;
  93. }
  94. if (m_target.is_extensible()) {
  95. if (interpreter().exception())
  96. return nullptr;
  97. if (trap_result.is_null())
  98. return nullptr;
  99. return &trap_result.as_object();
  100. }
  101. auto target_proto = m_target.prototype();
  102. if (interpreter().exception())
  103. return nullptr;
  104. if (!same_value(interpreter(), trap_result, Value(target_proto))) {
  105. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetPrototypeOfNonExtensible);
  106. return nullptr;
  107. }
  108. return &trap_result.as_object();
  109. }
  110. const Object* ProxyObject::prototype() const
  111. {
  112. if (m_is_revoked) {
  113. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  114. return nullptr;
  115. }
  116. return const_cast<const Object*>(const_cast<ProxyObject*>(this)->prototype());
  117. }
  118. bool ProxyObject::set_prototype(Object* object)
  119. {
  120. if (m_is_revoked) {
  121. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  122. return false;
  123. }
  124. auto trap = m_handler.get("setPrototypeOf");
  125. if (interpreter().exception())
  126. return false;
  127. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  128. return m_target.set_prototype(object);
  129. if (!trap.is_function()) {
  130. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "setPrototypeOf");
  131. return false;
  132. }
  133. MarkedValueList arguments(interpreter().heap());
  134. arguments.values().append(Value(&m_target));
  135. arguments.values().append(Value(object));
  136. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  137. if (interpreter().exception() || !trap_result)
  138. return false;
  139. if (m_target.is_extensible())
  140. return true;
  141. auto* target_proto = m_target.prototype();
  142. if (interpreter().exception())
  143. return false;
  144. if (!same_value(interpreter(), Value(object), Value(target_proto))) {
  145. interpreter().throw_exception<TypeError>(ErrorType::ProxySetPrototypeOfNonExtensible);
  146. return false;
  147. }
  148. return true;
  149. }
  150. bool ProxyObject::is_extensible() const
  151. {
  152. if (m_is_revoked) {
  153. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  154. return false;
  155. }
  156. auto trap = m_handler.get("isExtensible");
  157. if (interpreter().exception())
  158. return false;
  159. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  160. return m_target.is_extensible();
  161. if (!trap.is_function()) {
  162. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "isExtensible");
  163. return {};
  164. }
  165. MarkedValueList arguments(interpreter().heap());
  166. arguments.values().append(Value(&m_target));
  167. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  168. if (interpreter().exception())
  169. return false;
  170. if (trap_result != m_target.is_extensible()) {
  171. if (!interpreter().exception())
  172. interpreter().throw_exception<TypeError>(ErrorType::ProxyIsExtensibleReturn);
  173. return false;
  174. }
  175. return trap_result;
  176. }
  177. bool ProxyObject::prevent_extensions()
  178. {
  179. if (m_is_revoked) {
  180. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  181. return false;
  182. }
  183. auto trap = m_handler.get("preventExtensions");
  184. if (interpreter().exception())
  185. return false;
  186. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  187. return m_target.prevent_extensions();
  188. if (!trap.is_function()) {
  189. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "preventExtensions");
  190. return {};
  191. }
  192. MarkedValueList arguments(interpreter().heap());
  193. arguments.values().append(Value(&m_target));
  194. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  195. if (interpreter().exception())
  196. return false;
  197. if (trap_result && m_target.is_extensible()) {
  198. if (!interpreter().exception())
  199. interpreter().throw_exception<TypeError>(ErrorType::ProxyPreventExtensionsReturn);
  200. return false;
  201. }
  202. return trap_result;
  203. }
  204. Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(PropertyName name) const
  205. {
  206. if (m_is_revoked) {
  207. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  208. return {};
  209. }
  210. auto trap = m_handler.get("getOwnPropertyDescriptor");
  211. if (interpreter().exception())
  212. return {};
  213. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  214. return m_target.get_own_property_descriptor(name);
  215. if (!trap.is_function()) {
  216. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor");
  217. return {};
  218. }
  219. MarkedValueList arguments(interpreter().heap());
  220. arguments.values().append(Value(&m_target));
  221. arguments.values().append(js_string(interpreter(), name.to_string()));
  222. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments));
  223. if (interpreter().exception())
  224. return {};
  225. if (!trap_result.is_object() && !trap_result.is_undefined()) {
  226. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorReturn);
  227. return {};
  228. }
  229. auto target_desc = m_target.get_own_property_descriptor(name);
  230. if (interpreter().exception())
  231. return {};
  232. if (trap_result.is_undefined()) {
  233. if (!target_desc.has_value())
  234. return {};
  235. if (!target_desc.value().attributes.is_configurable()) {
  236. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorNonConfigurable);
  237. return {};
  238. }
  239. if (!m_target.is_extensible()) {
  240. if (!interpreter().exception())
  241. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorUndefReturn);
  242. return {};
  243. }
  244. return {};
  245. }
  246. auto result_desc = PropertyDescriptor::from_dictionary(interpreter(), trap_result.as_object());
  247. if (interpreter().exception())
  248. return {};
  249. if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), result_desc, target_desc)) {
  250. if (!interpreter().exception())
  251. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorInvalidDescriptor);
  252. return {};
  253. }
  254. if (!result_desc.attributes.is_configurable() && (!target_desc.has_value() || target_desc.value().attributes.is_configurable())) {
  255. interpreter().throw_exception<TypeError>(ErrorType::ProxyGetOwnDescriptorInvalidNonConfig);
  256. return {};
  257. }
  258. return result_desc;
  259. }
  260. bool ProxyObject::define_property(const FlyString& property_name, const Object& descriptor, bool throw_exceptions)
  261. {
  262. if (m_is_revoked) {
  263. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  264. return false;
  265. }
  266. auto trap = m_handler.get("defineProperty");
  267. if (interpreter().exception())
  268. return false;
  269. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  270. return m_target.define_property(property_name, descriptor, throw_exceptions);
  271. if (!trap.is_function()) {
  272. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "defineProperty");
  273. return false;
  274. }
  275. MarkedValueList arguments(interpreter().heap());
  276. arguments.values().append(Value(&m_target));
  277. arguments.values().append(js_string(interpreter(), property_name));
  278. arguments.values().append(Value(const_cast<Object*>(&descriptor)));
  279. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  280. if (interpreter().exception() || !trap_result)
  281. return false;
  282. auto target_desc = m_target.get_own_property_descriptor(property_name);
  283. if (interpreter().exception())
  284. return false;
  285. bool setting_config_false = false;
  286. if (descriptor.has_property("configurable") && !descriptor.get("configurable").to_boolean())
  287. setting_config_false = true;
  288. if (interpreter().exception())
  289. return false;
  290. if (!target_desc.has_value()) {
  291. if (!m_target.is_extensible()) {
  292. if (!interpreter().exception())
  293. interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropNonExtensible);
  294. return false;
  295. }
  296. if (setting_config_false) {
  297. interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropNonConfigurableNonExisting);
  298. return false;
  299. }
  300. } else {
  301. if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), PropertyDescriptor::from_dictionary(interpreter(), descriptor), target_desc)) {
  302. if (!interpreter().exception())
  303. interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropIncompatibleDescriptor);
  304. return false;
  305. }
  306. if (setting_config_false && target_desc.value().attributes.is_configurable()) {
  307. interpreter().throw_exception<TypeError>(ErrorType::ProxyDefinePropExistingConfigurable);
  308. return false;
  309. }
  310. }
  311. return true;
  312. }
  313. bool ProxyObject::has_property(PropertyName name) const
  314. {
  315. if (m_is_revoked) {
  316. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  317. return false;
  318. }
  319. auto trap = m_handler.get("has");
  320. if (interpreter().exception())
  321. return false;
  322. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  323. return m_target.has_property(name);
  324. if (!trap.is_function()) {
  325. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "has");
  326. return false;
  327. }
  328. MarkedValueList arguments(interpreter().heap());
  329. arguments.values().append(Value(&m_target));
  330. arguments.values().append(js_string(interpreter(), name.to_string()));
  331. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  332. if (interpreter().exception())
  333. return false;
  334. if (!trap_result) {
  335. auto target_desc = m_target.get_own_property_descriptor(name);
  336. if (interpreter().exception())
  337. return false;
  338. if (target_desc.has_value()) {
  339. if (!target_desc.value().attributes.is_configurable()) {
  340. interpreter().throw_exception<TypeError>(ErrorType::ProxyHasExistingNonConfigurable);
  341. return false;
  342. }
  343. if (!m_target.is_extensible()) {
  344. if (!interpreter().exception())
  345. interpreter().throw_exception<TypeError>(ErrorType::ProxyHasExistingNonExtensible);
  346. return false;
  347. }
  348. }
  349. }
  350. return trap_result;
  351. }
  352. Value ProxyObject::get(PropertyName name, Value) const
  353. {
  354. if (m_is_revoked) {
  355. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  356. return {};
  357. }
  358. auto trap = m_handler.get("get");
  359. if (interpreter().exception())
  360. return {};
  361. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  362. return m_target.get(name);
  363. if (!trap.is_function())
  364. return interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "get");
  365. MarkedValueList arguments(interpreter().heap());
  366. arguments.values().append(Value(&m_target));
  367. arguments.values().append(js_string(interpreter(), name.to_string()));
  368. arguments.values().append(Value(const_cast<ProxyObject*>(this)));
  369. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments));
  370. if (interpreter().exception())
  371. return {};
  372. auto target_desc = m_target.get_own_property_descriptor(name);
  373. if (target_desc.has_value()) {
  374. if (interpreter().exception())
  375. return {};
  376. if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), trap_result, target_desc.value().value))
  377. return interpreter().throw_exception<TypeError>(ErrorType::ProxyGetImmutableDataProperty);
  378. if (target_desc.value().is_accessor_descriptor() && target_desc.value().getter == nullptr && !trap_result.is_undefined())
  379. return interpreter().throw_exception<TypeError>(ErrorType::ProxyGetNonConfigurableAccessor);
  380. }
  381. return trap_result;
  382. }
  383. bool ProxyObject::put(PropertyName name, Value value, Value)
  384. {
  385. if (m_is_revoked) {
  386. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  387. return false;
  388. }
  389. auto trap = m_handler.get("set");
  390. if (interpreter().exception())
  391. return false;
  392. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  393. return m_target.put(name, value);
  394. if (!trap.is_function()) {
  395. interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "set");
  396. return false;
  397. }
  398. MarkedValueList arguments(interpreter().heap());
  399. arguments.values().append(Value(&m_target));
  400. arguments.values().append(js_string(interpreter(), name.to_string()));
  401. arguments.values().append(value);
  402. arguments.values().append(Value(const_cast<ProxyObject*>(this)));
  403. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  404. if (interpreter().exception() || !trap_result)
  405. return false;
  406. auto target_desc = m_target.get_own_property_descriptor(name);
  407. if (interpreter().exception())
  408. return false;
  409. if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) {
  410. if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), value, target_desc.value().value)) {
  411. interpreter().throw_exception<TypeError>(ErrorType::ProxySetImmutableDataProperty);
  412. return false;
  413. }
  414. if (target_desc.value().is_accessor_descriptor() && !target_desc.value().setter) {
  415. interpreter().throw_exception<TypeError>(ErrorType::ProxySetNonConfigurableAccessor);
  416. }
  417. }
  418. return true;
  419. }
  420. Value ProxyObject::delete_property(PropertyName name)
  421. {
  422. if (m_is_revoked) {
  423. interpreter().throw_exception<TypeError>(ErrorType::ProxyRevoked);
  424. return {};
  425. }
  426. auto trap = m_handler.get("deleteProperty");
  427. if (interpreter().exception())
  428. return {};
  429. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  430. return m_target.delete_property(name);
  431. if (!trap.is_function())
  432. return interpreter().throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "deleteProperty");
  433. MarkedValueList arguments(interpreter().heap());
  434. arguments.values().append(Value(&m_target));
  435. arguments.values().append(js_string(interpreter(), name.to_string()));
  436. auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), move(arguments)).to_boolean();
  437. if (interpreter().exception())
  438. return {};
  439. if (!trap_result)
  440. return Value(false);
  441. auto target_desc = m_target.get_own_property_descriptor(name);
  442. if (interpreter().exception())
  443. return {};
  444. if (!target_desc.has_value())
  445. return Value(true);
  446. if (!target_desc.value().attributes.is_configurable())
  447. return interpreter().throw_exception<TypeError>(ErrorType::ProxyDeleteNonConfigurable);
  448. return Value(true);
  449. }
  450. void ProxyObject::visit_children(Cell::Visitor& visitor)
  451. {
  452. Function::visit_children(visitor);
  453. visitor.visit(&m_target);
  454. visitor.visit(&m_handler);
  455. }
  456. Value ProxyObject::call(Interpreter& interpreter) {
  457. if (!is_function())
  458. return interpreter.throw_exception<TypeError>(ErrorType::NotAFunction, Value(this).to_string_without_side_effects().characters());
  459. if (m_is_revoked) {
  460. interpreter.throw_exception<TypeError>(ErrorType::ProxyRevoked);
  461. return {};
  462. }
  463. auto trap = m_handler.get("apply");
  464. if (interpreter.exception())
  465. return {};
  466. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  467. return static_cast<Function&>(m_target).call(interpreter);
  468. if (!trap.is_function())
  469. return interpreter.throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "apply");
  470. MarkedValueList arguments(interpreter.heap());
  471. arguments.values().append(Value(&m_target));
  472. arguments.values().append(Value(&m_handler));
  473. // FIXME: Pass global object
  474. auto arguments_array = Array::create(interpreter.global_object());
  475. interpreter.for_each_argument([&](auto& argument) {
  476. arguments_array->indexed_properties().append(argument);
  477. });
  478. arguments.values().append(arguments_array);
  479. return interpreter.call(trap.as_function(), Value(&m_handler), move(arguments));
  480. }
  481. Value ProxyObject::construct(Interpreter& interpreter) {
  482. if (!is_function())
  483. return interpreter.throw_exception<TypeError>(ErrorType::NotAConstructor, Value(this).to_string_without_side_effects().characters());
  484. if (m_is_revoked) {
  485. interpreter.throw_exception<TypeError>(ErrorType::ProxyRevoked);
  486. return {};
  487. }
  488. auto trap = m_handler.get("construct");
  489. if (interpreter.exception())
  490. return {};
  491. if (trap.is_empty() || trap.is_undefined() || trap.is_null())
  492. return static_cast<Function&>(m_target).construct(interpreter);
  493. if (!trap.is_function())
  494. return interpreter.throw_exception<TypeError>(ErrorType::ProxyInvalidTrap, "construct");
  495. MarkedValueList arguments(interpreter.heap());
  496. arguments.values().append(Value(&m_target));
  497. auto arguments_array = Array::create(interpreter.global_object());
  498. interpreter.for_each_argument([&](auto& argument) {
  499. arguments_array->indexed_properties().append(argument);
  500. });
  501. arguments.values().append(arguments_array);
  502. // FIXME: We need access to the actual newTarget property here. This is just
  503. // a quick fix
  504. arguments.values().append(Value(this));
  505. auto result = interpreter.call(trap.as_function(), Value(&m_handler), move(arguments));
  506. if (!result.is_object())
  507. return interpreter.throw_exception<TypeError>(ErrorType::ProxyConstructBadReturnType);
  508. return result;
  509. }
  510. const FlyString& ProxyObject::name() const
  511. {
  512. ASSERT(is_function());
  513. return static_cast<Function&>(m_target).name();
  514. }
  515. LexicalEnvironment* ProxyObject::create_environment()
  516. {
  517. ASSERT(is_function());
  518. return static_cast<Function&>(m_target).create_environment();
  519. }
  520. }