blob: ba74eab585b1345232c78586473ab9511fa8e514 [file] [log] [blame]
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +00001/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
mark.lam@apple.com284f4562016-08-30 20:54:54 +00003 * Copyright (C) 2003-2008, 2013, 2016 Apple Inc. All rights reserved.
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +00004 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#include "config.h"
22#include "FunctionConstructor.h"
23
barraclough@apple.com9c099f92010-06-06 23:34:36 +000024#include "ExceptionHelpers.h"
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000025#include "FunctionPrototype.h"
caitp@igalia.com04d4f602016-10-28 16:37:38 +000026#include "JSAsyncFunction.h"
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000027#include "JSFunction.h"
utatane.tea@gmail.comfb175b32016-10-01 23:35:17 +000028#include "JSGeneratorFunction.h"
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000029#include "JSGlobalObject.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000030#include "JSCInlines.h"
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000031#include <wtf/text/StringBuilder.h>
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000032
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000033namespace JSC {
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000034
andersca@apple.com7de5aae2013-09-05 20:12:23 +000035STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(FunctionConstructor);
ggaren@apple.comfea43532008-08-17 20:23:49 +000036
akling@apple.com2de49b72014-07-30 22:26:22 +000037const ClassInfo FunctionConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(FunctionConstructor) };
mhahnenberg@apple.com77d198e2011-10-05 02:47:42 +000038
akling@apple.com59875522013-09-30 03:45:30 +000039FunctionConstructor::FunctionConstructor(VM& vm, Structure* structure)
40 : InternalFunction(vm, structure)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000041{
mhahnenberg@apple.com7317a7f2011-09-09 21:43:14 +000042}
43
akling@apple.com22558062013-09-26 21:43:49 +000044void FunctionConstructor::finishCreation(VM& vm, FunctionPrototype* functionPrototype)
mhahnenberg@apple.com7317a7f2011-09-09 21:43:14 +000045{
akling@apple.com22558062013-09-26 21:43:49 +000046 Base::finishCreation(vm, functionPrototype->classInfo()->className);
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +000047 putDirectWithoutTransition(vm, vm.propertyNames->prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
commit-queue@webkit.org8ff356d2017-04-11 16:38:43 +000048 putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum);
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000049}
50
barraclough@apple.com11d351a2010-06-04 21:38:38 +000051static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000052{
barraclough@apple.com11d351a2010-06-04 21:38:38 +000053 ArgList args(exec);
sbarati@apple.com9f55abf2016-12-02 02:38:23 +000054 return JSValue::encode(constructFunction(exec, asInternalFunction(exec->jsCallee())->globalObject(), args, FunctionConstructionMode::Function, exec->newTarget()));
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000055}
56
mhahnenberg@apple.com79c8e6e2011-10-08 23:26:41 +000057ConstructType FunctionConstructor::getConstructData(JSCell*, ConstructData& constructData)
58{
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000059 constructData.native.function = constructWithFunctionConstructor;
utatane.tea@gmail.comf76f1b42016-03-05 17:01:04 +000060 return ConstructType::Host;
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000061}
62
barraclough@apple.com99ff3432010-06-03 20:00:18 +000063static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000064{
ggaren@apple.comfea29f12010-05-29 06:33:05 +000065 ArgList args(exec);
sbarati@apple.com9f55abf2016-12-02 02:38:23 +000066 return JSValue::encode(constructFunction(exec, asInternalFunction(exec->jsCallee())->globalObject(), args));
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000067}
68
69// ECMA 15.3.1 The Function Constructor Called as a Function
mhahnenberg@apple.com2413eb82011-09-27 22:46:51 +000070CallType FunctionConstructor::getCallData(JSCell*, CallData& callData)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000071{
72 callData.native.function = callFunctionConstructor;
utatane.tea@gmail.comf76f1b42016-03-05 17:01:04 +000073 return CallType::Host;
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000074}
75
76// ECMA 15.3.2 The Function Constructor
utatane.tea@gmail.comc4ec8e22016-12-26 06:35:07 +000077JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const SourceOrigin& sourceOrigin, const String& sourceURL, const TextPosition& position, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000078{
mark.lam@apple.com284f4562016-08-30 20:54:54 +000079 VM& vm = exec->vm();
80 auto scope = DECLARE_THROW_SCOPE(vm);
81
yurys@chromium.orgaa17fdc2011-05-19 11:47:02 +000082 if (!globalObject->evalEnabled())
mark.lam@apple.com284f4562016-08-30 20:54:54 +000083 return throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));
mark.lam@apple.come029e1f2016-11-22 02:05:27 +000084 scope.release();
utatane.tea@gmail.comc4ec8e22016-12-26 06:35:07 +000085 return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceOrigin, sourceURL, position, -1, functionConstructionMode, newTarget);
abarth@webkit.org19733322011-05-09 23:05:54 +000086}
87
ggaren@apple.com7a6a0f62015-03-26 23:12:39 +000088JSObject* constructFunctionSkippingEvalEnabledCheck(
89 ExecState* exec, JSGlobalObject* globalObject, const ArgList& args,
utatane.tea@gmail.comc4ec8e22016-12-26 06:35:07 +000090 const Identifier& functionName, const SourceOrigin& sourceOrigin, const String& sourceURL,
keith_miller@apple.com02373132016-01-14 20:45:48 +000091 const TextPosition& position, int overrideLineNumber, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
abarth@webkit.org19733322011-05-09 23:05:54 +000092{
mark.lam@apple.com284f4562016-08-30 20:54:54 +000093 VM& vm = exec->vm();
94 auto scope = DECLARE_THROW_SCOPE(vm);
95
caitp@igalia.com04d4f602016-10-28 16:37:38 +000096 const char* prefix = nullptr;
97 Structure* structure = nullptr;
98 switch (functionConstructionMode) {
99 case FunctionConstructionMode::Function:
100 structure = globalObject->functionStructure();
101 prefix = "{function ";
102 break;
103 case FunctionConstructionMode::Generator:
104 structure = globalObject->generatorFunctionStructure();
105 prefix = "{function *";
106 break;
107 case FunctionConstructionMode::Async:
108 structure = globalObject->asyncFunctionStructure();
109 prefix = "{async function ";
110 break;
111 }
112
ggaren@apple.comddc6f102015-03-20 20:12:10 +0000113 // How we stringify functions is sometimes important for web compatibility.
114 // See https://bugs.webkit.org/show_bug.cgi?id=24350.
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000115 String program;
weinig@apple.com9b5bf062008-11-20 23:23:59 +0000116 if (args.isEmpty())
caitp@igalia.com04d4f602016-10-28 16:37:38 +0000117 program = makeString(prefix, functionName.string(), "() {\n\n}}");
mark.lam@apple.come029e1f2016-11-22 02:05:27 +0000118 else if (args.size() == 1) {
119 auto body = args.at(0).toWTFString(exec);
120 RETURN_IF_EXCEPTION(scope, nullptr);
121 program = makeString(prefix, functionName.string(), "() {\n", body, "\n}}");
122 } else {
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000123 StringBuilder builder;
caitp@igalia.com04d4f602016-10-28 16:37:38 +0000124 builder.append(prefix);
ggaren@apple.comddc6f102015-03-20 20:12:10 +0000125 builder.append(functionName.string());
ggaren@apple.com5ae06552015-03-26 23:41:16 +0000126 builder.append('(');
mark.lam@apple.com110cbbd2016-11-16 00:19:54 +0000127 auto viewWithString = args.at(0).toString(exec)->viewWithUnderlyingString(*exec);
128 RETURN_IF_EXCEPTION(scope, nullptr);
129 builder.append(viewWithString.view);
barraclough@apple.com1f0cbd22009-12-14 00:27:07 +0000130 for (size_t i = 1; i < args.size() - 1; i++) {
ggaren@apple.com5ae06552015-03-26 23:41:16 +0000131 builder.appendLiteral(", ");
mark.lam@apple.com110cbbd2016-11-16 00:19:54 +0000132 auto viewWithString = args.at(i).toString(exec)->viewWithUnderlyingString(*exec);
133 RETURN_IF_EXCEPTION(scope, nullptr);
134 builder.append(viewWithString.view);
barraclough@apple.com1f0cbd22009-12-14 00:27:07 +0000135 }
ggaren@apple.comddc6f102015-03-20 20:12:10 +0000136 builder.appendLiteral(") {\n");
mark.lam@apple.com110cbbd2016-11-16 00:19:54 +0000137 viewWithString = args.at(args.size() - 1).toString(exec)->viewWithUnderlyingString(*exec);
138 RETURN_IF_EXCEPTION(scope, nullptr);
139 builder.append(viewWithString.view);
ggaren@apple.comddc6f102015-03-20 20:12:10 +0000140 builder.appendLiteral("\n}}");
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000141 program = builder.toString();
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +0000142 }
143
utatane.tea@gmail.comc4ec8e22016-12-26 06:35:07 +0000144 SourceCode source = makeSource(program, sourceOrigin, sourceURL, position);
rniwa@webkit.org90bcb6c2015-03-07 17:38:40 +0000145 JSObject* exception = nullptr;
ggaren@apple.com8e8bac42015-03-26 23:35:47 +0000146 FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, *exec, source, exception, overrideLineNumber);
barraclough@apple.com40b4ad32010-07-14 00:27:13 +0000147 if (!function) {
148 ASSERT(exception);
mark.lam@apple.com284f4562016-08-30 20:54:54 +0000149 return throwException(exec, scope, exception);
barraclough@apple.com40b4ad32010-07-14 00:27:13 +0000150 }
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +0000151
caitp@igalia.com04d4f602016-10-28 16:37:38 +0000152 Structure* subclassStructure = InternalFunction::createSubclassStructure(exec, newTarget, structure);
mark.lam@apple.come1ab17c2016-09-26 19:11:17 +0000153 RETURN_IF_EXCEPTION(scope, nullptr);
keith_miller@apple.com02373132016-01-14 20:45:48 +0000154
caitp@igalia.com04d4f602016-10-28 16:37:38 +0000155 switch (functionConstructionMode) {
156 case FunctionConstructionMode::Function:
157 return JSFunction::create(vm, function, globalObject->globalScope(), subclassStructure);
158 case FunctionConstructionMode::Generator:
utatane.tea@gmail.comfb175b32016-10-01 23:35:17 +0000159 return JSGeneratorFunction::create(vm, function, globalObject->globalScope(), subclassStructure);
caitp@igalia.com04d4f602016-10-28 16:37:38 +0000160 case FunctionConstructionMode::Async:
161 return JSAsyncFunction::create(vm, function, globalObject->globalScope(), subclassStructure);
162 }
163
164 ASSERT_NOT_REACHED();
165 return nullptr;
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +0000166}
167
168// ECMA 15.3.2 The Function Constructor
keith_miller@apple.com02373132016-01-14 20:45:48 +0000169JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, FunctionConstructionMode functionConstructionMode, JSValue newTarget)
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +0000170{
utatane.tea@gmail.comc4ec8e22016-12-26 06:35:07 +0000171 return constructFunction(exec, globalObject, args, exec->propertyNames().anonymous, exec->callerSourceOrigin(), String(), TextPosition(), functionConstructionMode, newTarget);
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +0000172}
173
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000174} // namespace JSC