Serenity Operating System
at master 111 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org> 3 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/TypeCasts.h> 9#include <LibJS/Contrib/Test262/$262Object.h> 10#include <LibJS/Contrib/Test262/AgentObject.h> 11#include <LibJS/Contrib/Test262/GlobalObject.h> 12#include <LibJS/Contrib/Test262/IsHTMLDDA.h> 13#include <LibJS/Heap/Cell.h> 14#include <LibJS/Interpreter.h> 15#include <LibJS/Runtime/ArrayBuffer.h> 16#include <LibJS/Runtime/GlobalObject.h> 17#include <LibJS/Runtime/Object.h> 18#include <LibJS/Script.h> 19 20namespace JS::Test262 { 21 22$262Object::$262Object(Realm& realm) 23 : Object(Object::ConstructWithoutPrototypeTag::Tag, realm) 24{ 25} 26 27ThrowCompletionOr<void> $262Object::initialize(Realm& realm) 28{ 29 MUST_OR_THROW_OOM(Base::initialize(realm)); 30 31 m_agent = MUST_OR_THROW_OOM(vm().heap().allocate<AgentObject>(realm, realm)); 32 m_is_htmldda = MUST_OR_THROW_OOM(vm().heap().allocate<IsHTMLDDA>(realm, realm)); 33 34 u8 attr = Attribute::Writable | Attribute::Configurable; 35 define_native_function(realm, "clearKeptObjects", clear_kept_objects, 0, attr); 36 define_native_function(realm, "createRealm", create_realm, 0, attr); 37 define_native_function(realm, "detachArrayBuffer", detach_array_buffer, 1, attr); 38 define_native_function(realm, "evalScript", eval_script, 1, attr); 39 40 define_direct_property("agent", m_agent, attr); 41 define_direct_property("gc", realm.global_object().get_without_side_effects("gc"), attr); 42 define_direct_property("global", &realm.global_object(), attr); 43 define_direct_property("IsHTMLDDA", m_is_htmldda, attr); 44 45 return {}; 46} 47 48void $262Object::visit_edges(Cell::Visitor& visitor) 49{ 50 Base::visit_edges(visitor); 51 visitor.visit(m_agent); 52 visitor.visit(m_is_htmldda); 53} 54 55JS_DEFINE_NATIVE_FUNCTION($262Object::clear_kept_objects) 56{ 57 vm.finish_execution_generation(); 58 return js_undefined(); 59} 60 61JS_DEFINE_NATIVE_FUNCTION($262Object::create_realm) 62{ 63 auto realm = MUST_OR_THROW_OOM(Realm::create(vm)); 64 auto realm_global_object = vm.heap().allocate_without_realm<GlobalObject>(*realm); 65 VERIFY(realm_global_object); 66 realm->set_global_object(realm_global_object, nullptr); 67 set_default_global_bindings(*realm); 68 MUST_OR_THROW_OOM(realm_global_object->initialize(*realm)); 69 return Value(realm_global_object->$262()); 70} 71 72JS_DEFINE_NATIVE_FUNCTION($262Object::detach_array_buffer) 73{ 74 auto array_buffer = vm.argument(0); 75 if (!array_buffer.is_object() || !is<ArrayBuffer>(array_buffer.as_object())) 76 return vm.throw_completion<TypeError>(); 77 78 auto& array_buffer_object = static_cast<ArrayBuffer&>(array_buffer.as_object()); 79 TRY(JS::detach_array_buffer(vm, array_buffer_object, vm.argument(1))); 80 return js_null(); 81} 82 83JS_DEFINE_NATIVE_FUNCTION($262Object::eval_script) 84{ 85 auto source_text = TRY(vm.argument(0).to_deprecated_string(vm)); 86 87 // 1. Let hostDefined be any host-defined values for the provided sourceText (obtained in an implementation dependent manner) 88 89 // 2. Let realm be the current Realm Record. 90 auto& realm = *vm.current_realm(); 91 92 // 3. Let s be ParseScript(sourceText, realm, hostDefined). 93 auto script_or_error = Script::parse(source_text, realm); 94 95 // 4. If s is a List of errors, then 96 if (script_or_error.is_error()) { 97 // a. Let error be the first element of s. 98 auto& error = script_or_error.error()[0]; 99 100 // b. Return Completion { [[Type]]: throw, [[Value]]: error, [[Target]]: empty }. 101 return vm.throw_completion<SyntaxError>(TRY_OR_THROW_OOM(vm, error.to_string())); 102 } 103 104 // 5. Let status be ScriptEvaluation(s). 105 auto status = vm.interpreter().run(script_or_error.value()); 106 107 // 6. Return Completion(status). 108 return status; 109} 110 111}