Serenity Operating System
at master 284 lines 13 kB view raw
1/* 2 * Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibJS/Lexer.h> 8#include <LibJS/Parser.h> 9#include <LibJS/Runtime/AbstractOperations.h> 10#include <LibJS/Runtime/ECMAScriptFunctionObject.h> 11#include <LibJS/Runtime/Error.h> 12#include <LibJS/Runtime/FunctionConstructor.h> 13#include <LibJS/Runtime/FunctionObject.h> 14#include <LibJS/Runtime/GeneratorPrototype.h> 15#include <LibJS/Runtime/GlobalEnvironment.h> 16#include <LibJS/Runtime/GlobalObject.h> 17#include <LibJS/Runtime/Realm.h> 18 19namespace JS { 20 21FunctionConstructor::FunctionConstructor(Realm& realm) 22 : NativeFunction(realm.vm().names.Function.as_string(), *realm.intrinsics().function_prototype()) 23{ 24} 25 26ThrowCompletionOr<void> FunctionConstructor::initialize(Realm& realm) 27{ 28 auto& vm = this->vm(); 29 MUST_OR_THROW_OOM(NativeFunction::initialize(realm)); 30 31 // 20.2.2.2 Function.prototype, https://tc39.es/ecma262/#sec-function.prototype 32 define_direct_property(vm.names.prototype, realm.intrinsics().function_prototype(), 0); 33 34 define_direct_property(vm.names.length, Value(1), Attribute::Configurable); 35 36 return {}; 37} 38 39// 20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, args ), https://tc39.es/ecma262/#sec-createdynamicfunction 40ThrowCompletionOr<ECMAScriptFunctionObject*> FunctionConstructor::create_dynamic_function(VM& vm, FunctionObject& constructor, FunctionObject* new_target, FunctionKind kind, MarkedVector<Value> const& args) 41{ 42 // 1. Let currentRealm be the current Realm Record. 43 auto& current_realm = *vm.current_realm(); 44 45 // 2. Perform ? HostEnsureCanCompileStrings(currentRealm). 46 TRY(vm.host_ensure_can_compile_strings(current_realm)); 47 48 // 3. If newTarget is undefined, set newTarget to constructor. 49 if (new_target == nullptr) 50 new_target = &constructor; 51 52 StringView prefix; 53 Object* (Intrinsics::*fallback_prototype)() = nullptr; 54 55 switch (kind) { 56 // 4. If kind is normal, then 57 case FunctionKind::Normal: 58 // a. Let prefix be "function". 59 prefix = "function"sv; 60 61 // b. Let exprSym be the grammar symbol FunctionExpression. 62 // c. Let bodySym be the grammar symbol FunctionBody[~Yield, ~Await]. 63 // d. Let parameterSym be the grammar symbol FormalParameters[~Yield, ~Await]. 64 65 // e. Let fallbackProto be "%Function.prototype%". 66 fallback_prototype = &Intrinsics::function_prototype; 67 break; 68 69 // 5. Else if kind is generator, then 70 case FunctionKind::Generator: 71 // a. Let prefix be "function*". 72 prefix = "function*"sv; 73 74 // b. Let exprSym be the grammar symbol GeneratorExpression. 75 // c. Let bodySym be the grammar symbol GeneratorBody. 76 // d. Let parameterSym be the grammar symbol FormalParameters[+Yield, ~Await]. 77 78 // e. Let fallbackProto be "%GeneratorFunction.prototype%". 79 fallback_prototype = &Intrinsics::generator_function_prototype; 80 break; 81 82 // 6. Else if kind is async, then 83 case FunctionKind::Async: 84 // a. Let prefix be "async function". 85 prefix = "async function"sv; 86 87 // b. Let exprSym be the grammar symbol AsyncFunctionExpression. 88 // c. Let bodySym be the grammar symbol AsyncFunctionBody. 89 // d. Let parameterSym be the grammar symbol FormalParameters[~Yield, +Await]. 90 91 // e. Let fallbackProto be "%AsyncFunction.prototype%". 92 fallback_prototype = &Intrinsics::async_function_prototype; 93 break; 94 95 // 7. Else, 96 case FunctionKind::AsyncGenerator: 97 // a. Assert: kind is asyncGenerator. 98 99 // b. Let prefix be "async function*". 100 prefix = "async function*"sv; 101 102 // c. Let exprSym be the grammar symbol AsyncGeneratorExpression. 103 // d. Let bodySym be the grammar symbol AsyncGeneratorBody. 104 // e. Let parameterSym be the grammar symbol FormalParameters[+Yield, +Await]. 105 106 // f. Let fallbackProto be "%AsyncGeneratorFunction.prototype%". 107 fallback_prototype = &Intrinsics::async_generator_function_prototype; 108 break; 109 110 default: 111 VERIFY_NOT_REACHED(); 112 } 113 114 // 8. Let argCount be the number of elements in args. 115 auto arg_count = args.size(); 116 117 // 9. Let P be the empty String. 118 DeprecatedString parameters_string = ""; 119 120 Optional<Value> body_arg; 121 122 // 10. If argCount = 0, let bodyArg be the empty String. 123 if (arg_count == 0) { 124 // Optimization: Instead of creating a PrimitiveString here, we just check if body_arg is empty in step 16. 125 } 126 // 11. Else if argCount = 1, let bodyArg be args[0]. 127 else if (arg_count == 1) { 128 body_arg = args[0]; 129 } 130 // 12. Else, 131 else { 132 // a. Assert: argCount > 1. 133 VERIFY(arg_count > 1); 134 135 // b. Let firstArg be args[0]. 136 // c. Set P to ? ToString(firstArg). 137 // NOTE: Also done in the loop. We start at 0 instead and then join() with a comma. 138 139 // d. Let k be 1. 140 size_t k = 0; 141 142 // e. Repeat, while k < argCount - 1, 143 Vector<DeprecatedString> parameters; 144 for (; k < arg_count - 1; ++k) { 145 // i. Let nextArg be args[k]. 146 auto next_arg = args[k]; 147 148 // ii. Let nextArgString be ? ToString(nextArg). 149 // iii. Set P to the string-concatenation of P, "," (a comma), and nextArgString. 150 parameters.append(TRY(next_arg.to_deprecated_string(vm))); 151 152 // iv. Set k to k + 1. 153 } 154 parameters_string = DeprecatedString::join(',', parameters); 155 156 // f. Let bodyArg be args[k]. 157 body_arg = args[k]; 158 } 159 160 // 13. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED). 161 auto body_string = DeprecatedString::formatted("\n{}\n", body_arg.has_value() ? TRY(body_arg->to_deprecated_string(vm)) : ""); 162 163 // 14. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}". 164 // 15. Let sourceText be StringToCodePoints(sourceString). 165 auto source_text = DeprecatedString::formatted("{} anonymous({}\n) {{{}}}", prefix, parameters_string, body_string); 166 167 u8 parse_options = FunctionNodeParseOptions::CheckForFunctionAndName; 168 if (kind == FunctionKind::Async || kind == FunctionKind::AsyncGenerator) 169 parse_options |= FunctionNodeParseOptions::IsAsyncFunction; 170 if (kind == FunctionKind::Generator || kind == FunctionKind::AsyncGenerator) 171 parse_options |= FunctionNodeParseOptions::IsGeneratorFunction; 172 173 // 16. Let parameters be ParseText(StringToCodePoints(P), parameterSym). 174 i32 function_length = 0; 175 auto parameters_parser = Parser { Lexer { parameters_string } }; 176 auto parameters = parameters_parser.parse_formal_parameters(function_length, parse_options); 177 178 // 17. If parameters is a List of errors, throw a SyntaxError exception. 179 if (parameters_parser.has_errors()) { 180 auto error = parameters_parser.errors()[0]; 181 return vm.throw_completion<SyntaxError>(TRY_OR_THROW_OOM(vm, error.to_string())); 182 } 183 184 // 18. Let body be ParseText(StringToCodePoints(bodyString), bodySym). 185 bool contains_direct_call_to_eval = false; 186 auto body_parser = Parser { Lexer { body_string } }; 187 // Set up some parser state to accept things like return await, and yield in the plain function body. 188 body_parser.m_state.in_function_context = true; 189 if ((parse_options & FunctionNodeParseOptions::IsAsyncFunction) != 0) 190 body_parser.m_state.await_expression_is_valid = true; 191 if ((parse_options & FunctionNodeParseOptions::IsGeneratorFunction) != 0) 192 body_parser.m_state.in_generator_function_context = true; 193 (void)body_parser.parse_function_body(parameters, kind, contains_direct_call_to_eval); 194 195 // 19. If body is a List of errors, throw a SyntaxError exception. 196 if (body_parser.has_errors()) { 197 auto error = body_parser.errors()[0]; 198 return vm.throw_completion<SyntaxError>(TRY_OR_THROW_OOM(vm, error.to_string())); 199 } 200 201 // 20. NOTE: The parameters and body are parsed separately to ensure that each is valid alone. For example, new Function("/*", "*/ ) {") is not legal. 202 // 21. NOTE: If this step is reached, sourceText must have the syntax of exprSym (although the reverse implication does not hold). The purpose of the next two steps is to enforce any Early Error rules which apply to exprSym directly. 203 204 // 22. Let expr be ParseText(sourceText, exprSym). 205 auto source_parser = Parser { Lexer { source_text } }; 206 // This doesn't need any parse_options, it determines those & the function type based on the tokens that were found. 207 auto expr = source_parser.parse_function_node<FunctionExpression>(); 208 209 // 23. If expr is a List of errors, throw a SyntaxError exception. 210 if (source_parser.has_errors()) { 211 auto error = source_parser.errors()[0]; 212 return vm.throw_completion<SyntaxError>(TRY_OR_THROW_OOM(vm, error.to_string())); 213 } 214 215 // 24. Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto). 216 auto* prototype = TRY(get_prototype_from_constructor(vm, *new_target, fallback_prototype)); 217 218 // 25. Let realmF be the current Realm Record. 219 auto& realm = *vm.current_realm(); 220 221 // 26. Let env be realmF.[[GlobalEnv]]. 222 auto& environment = realm.global_environment(); 223 224 // 27. Let privateEnv be null. 225 PrivateEnvironment* private_environment = nullptr; 226 227 // 28. Let F be OrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv). 228 auto function = ECMAScriptFunctionObject::create(realm, "anonymous", *prototype, move(source_text), expr->body(), expr->parameters(), expr->function_length(), &environment, private_environment, expr->kind(), expr->is_strict_mode(), expr->might_need_arguments_object(), contains_direct_call_to_eval); 229 230 // FIXME: Remove the name argument from create() and do this instead. 231 // 29. Perform SetFunctionName(F, "anonymous"). 232 233 // 30. If kind is generator, then 234 if (kind == FunctionKind::Generator) { 235 // a. Let prototype be OrdinaryObjectCreate(%GeneratorFunction.prototype.prototype%). 236 prototype = Object::create(realm, realm.intrinsics().generator_function_prototype_prototype()); 237 238 // b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 239 function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable); 240 } 241 // 31. Else if kind is asyncGenerator, then 242 else if (kind == FunctionKind::AsyncGenerator) { 243 // a. Let prototype be OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%). 244 prototype = Object::create(realm, realm.intrinsics().async_generator_function_prototype_prototype()); 245 246 // b. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }). 247 function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable); 248 } 249 // 32. Else if kind is normal, perform MakeConstructor(F). 250 else if (kind == FunctionKind::Normal) { 251 // FIXME: Implement MakeConstructor 252 prototype = Object::create(realm, realm.intrinsics().object_prototype()); 253 prototype->define_direct_property(vm.names.constructor, function, Attribute::Writable | Attribute::Configurable); 254 function->define_direct_property(vm.names.prototype, prototype, Attribute::Writable); 255 } 256 257 // 33. NOTE: Functions whose kind is async are not constructible and do not have a [[Construct]] internal method or a "prototype" property. 258 259 // 34. Return F. 260 return function.ptr(); 261} 262 263// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body 264ThrowCompletionOr<Value> FunctionConstructor::call() 265{ 266 return TRY(construct(*this)); 267} 268 269// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body 270ThrowCompletionOr<NonnullGCPtr<Object>> FunctionConstructor::construct(FunctionObject& new_target) 271{ 272 auto& vm = this->vm(); 273 274 // 1. Let C be the active function object. 275 auto* constructor = vm.active_function_object(); 276 277 // 2. Let args be the argumentsList that was passed to this function by [[Call]] or [[Construct]]. 278 auto& args = vm.running_execution_context().arguments; 279 280 // 3. Return ? CreateDynamicFunction(C, NewTarget, normal, args). 281 return *TRY(create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Normal, args)); 282} 283 284}