JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / runtime / FunctionConstructor.cpp
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 "FunctionPrototype.h"
25 #include "JSFunction.h"
26 #include "JSGlobalObject.h"
27 #include "JSString.h"
28 #include "Parser.h"
29 #include "Debugger.h"
30 #include "Lexer.h"
31 #include "Nodes.h"
32
33 namespace JSC {
34
35 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
36
37 FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
38     : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
39 {
40     putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
41
42     // Number of arguments for constructor
43     putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
44 }
45
46 static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)
47 {
48     return constructFunction(exec, args);
49 }
50
51 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
52 {
53     constructData.native.function = constructWithFunctionConstructor;
54     return ConstructTypeHost;
55 }
56
57 static JSValuePtr callFunctionConstructor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
58 {
59     return constructFunction(exec, args);
60 }
61
62 // ECMA 15.3.1 The Function Constructor Called as a Function
63 CallType FunctionConstructor::getCallData(CallData& callData)
64 {
65     callData.native.function = callFunctionConstructor;
66     return CallTypeHost;
67 }
68
69 FunctionBodyNode* extractFunctionBody(ProgramNode* program)
70 {
71     if (!program)
72         return 0;
73
74     StatementVector& children = program->children();
75     if (children.size() != 1)
76         return 0;
77
78     ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(children[0].get()); 
79     ASSERT(exprStatement->isExprStatement());
80     if (!exprStatement || !exprStatement->isExprStatement())
81         return 0;
82
83     FuncExprNode* funcExpr = static_cast<FuncExprNode*>(exprStatement->expr());
84     ASSERT(funcExpr->isFuncExprNode());
85     if (!funcExpr || !funcExpr->isFuncExprNode())
86         return 0;
87
88     FunctionBodyNode* body = funcExpr->body();
89     ASSERT(body);
90     return body;
91 }
92
93 // ECMA 15.3.2 The Function Constructor
94 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
95 {
96     UString program;
97     if (args.isEmpty())
98         program = "(function(){})";
99     else if (args.size() == 1)
100         program = "(function(){" + args.at(exec, 0).toString(exec) + "})";
101     else {
102         program = "(function(" + args.at(exec, 0).toString(exec);
103         for (size_t i = 1; i < args.size() - 1; i++)
104             program += "," + args.at(exec, i).toString(exec);
105         program += "){" + args.at(exec, args.size() - 1).toString(exec) + "})";
106     }
107
108     int errLine;
109     UString errMsg;
110     SourceCode source = makeSource(program, sourceURL, lineNumber);
111     RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
112
113     FunctionBodyNode* body = extractFunctionBody(programNode.get());
114     if (!body)
115         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
116
117     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
118     ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
119     return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
120 }
121
122 // ECMA 15.3.2 The Function Constructor
123 JSObject* constructFunction(ExecState* exec, const ArgList& args)
124 {
125     return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
126 }
127
128 } // namespace JSC