• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FunctionConstructor(ExecState * exec,PassRefPtr<Structure> structure,FunctionPrototype * functionPrototype)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 
constructWithFunctionConstructor(ExecState * exec,JSObject *,const ArgList & args)46 static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)
47 {
48     return constructFunction(exec, args);
49 }
50 
getConstructData(ConstructData & constructData)51 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
52 {
53     constructData.native.function = constructWithFunctionConstructor;
54     return ConstructTypeHost;
55 }
56 
callFunctionConstructor(ExecState * exec,JSObject *,JSValuePtr,const ArgList & args)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
getCallData(CallData & callData)63 CallType FunctionConstructor::getCallData(CallData& callData)
64 {
65     callData.native.function = callFunctionConstructor;
66     return CallTypeHost;
67 }
68 
extractFunctionBody(ProgramNode * program)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
constructFunction(ExecState * exec,const ArgList & args,const Identifier & functionName,const UString & sourceURL,int lineNumber)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
constructFunction(ExecState * exec,const ArgList & args)123 JSObject* constructFunction(ExecState* exec, const ArgList& args)
124 {
125     return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
126 }
127 
128 } // namespace JSC
129