1 | /* |
2 | * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) |
3 | * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
4 | * |
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 | |
24 | #include "Debugger.h" |
25 | #include "FunctionPrototype.h" |
26 | #include "JSFunction.h" |
27 | #include "JSGlobalObject.h" |
28 | #include "JSString.h" |
29 | #include "Lexer.h" |
30 | #include "Nodes.h" |
31 | #include "Parser.h" |
32 | #include "StringBuilder.h" |
33 | |
34 | namespace JSC { |
35 | |
36 | ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor); |
37 | |
38 | FunctionConstructor::FunctionConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) |
39 | : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className)) |
40 | { |
41 | putDirectWithoutTransition(propertyName: exec->propertyNames().prototype, value: functionPrototype, attributes: DontEnum | DontDelete | ReadOnly); |
42 | |
43 | // Number of arguments for constructor |
44 | putDirectWithoutTransition(propertyName: exec->propertyNames().length, value: jsNumber(exec, i: 1), attributes: ReadOnly | DontDelete | DontEnum); |
45 | } |
46 | |
47 | static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args) |
48 | { |
49 | return constructFunction(exec, args); |
50 | } |
51 | |
52 | ConstructType FunctionConstructor::getConstructData(ConstructData& constructData) |
53 | { |
54 | constructData.native.function = constructWithFunctionConstructor; |
55 | return ConstructTypeHost; |
56 | } |
57 | |
58 | static JSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args) |
59 | { |
60 | return constructFunction(exec, args); |
61 | } |
62 | |
63 | // ECMA 15.3.1 The Function Constructor Called as a Function |
64 | CallType FunctionConstructor::getCallData(CallData& callData) |
65 | { |
66 | callData.native.function = callFunctionConstructor; |
67 | return CallTypeHost; |
68 | } |
69 | |
70 | // ECMA 15.3.2 The Function Constructor |
71 | JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) |
72 | { |
73 | // Functions need to have a space following the opening { due to for web compatibility |
74 | // see https://bugs.webkit.org/show_bug.cgi?id=24350 |
75 | // We also need \n before the closing } to handle // comments at the end of the last line |
76 | UString program; |
77 | if (args.isEmpty()) |
78 | program = "(function() { \n})" ; |
79 | else if (args.size() == 1) |
80 | program = makeString(string1: "(function() { " , string2: args.at(idx: 0).toString(exec), string3: "\n})" ); |
81 | else { |
82 | StringBuilder builder; |
83 | builder.append(str: "(function(" ); |
84 | builder.append(str: args.at(idx: 0).toString(exec)); |
85 | for (size_t i = 1; i < args.size() - 1; i++) { |
86 | builder.append(str: "," ); |
87 | builder.append(str: args.at(idx: i).toString(exec)); |
88 | } |
89 | builder.append(str: ") { " ); |
90 | builder.append(str: args.at(idx: args.size() - 1).toString(exec)); |
91 | builder.append(str: "\n})" ); |
92 | program = builder.release(); |
93 | } |
94 | |
95 | int errLine; |
96 | UString errMsg; |
97 | SourceCode source = makeSource(source: program, url: sourceURL, firstLine: lineNumber); |
98 | RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, errLine: &errLine, errMsg: &errMsg); |
99 | if (!function) |
100 | return throwError(exec, SyntaxError, message: errMsg, lineNumber: errLine, sourceID: source.provider()->asID(), sourceURL: source.provider()->url()); |
101 | |
102 | JSGlobalObject* globalObject = exec->lexicalGlobalObject(); |
103 | ScopeChain scopeChain(globalObject, globalObject->globalData(), globalObject, exec->globalThisValue()); |
104 | return new (exec) JSFunction(exec, function, scopeChain.node()); |
105 | } |
106 | |
107 | // ECMA 15.3.2 The Function Constructor |
108 | JSObject* constructFunction(ExecState* exec, const ArgList& args) |
109 | { |
110 | return constructFunction(exec, args, functionName: Identifier(exec, "anonymous" ), sourceURL: UString(), lineNumber: 1); |
111 | } |
112 | |
113 | } // namespace JSC |
114 | |