• 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 *,JSValue,const ArgList & args)57 static JSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec, JSObject*, JSValue, 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     StatementNode* exprStatement = children[0];
79     ASSERT(exprStatement);
80     ASSERT(exprStatement->isExprStatement());
81     if (!exprStatement || !exprStatement->isExprStatement())
82         return 0;
83 
84     ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
85     ASSERT(funcExpr);
86     ASSERT(funcExpr->isFuncExprNode());
87     if (!funcExpr || !funcExpr->isFuncExprNode())
88         return 0;
89 
90     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
91     ASSERT(body);
92     return body;
93 }
94 
95 // ECMA 15.3.2 The Function Constructor
constructFunction(ExecState * exec,const ArgList & args,const Identifier & functionName,const UString & sourceURL,int lineNumber)96 JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
97 {
98     // Functions need to have a space following the opening { due to for web compatibility
99     // see https://bugs.webkit.org/show_bug.cgi?id=24350
100     // We also need \n before the closing } to handle // comments at the end of the last line
101     UString program;
102     if (args.isEmpty())
103         program = "(function() { \n})";
104     else if (args.size() == 1)
105         program = "(function() { " + args.at(0).toString(exec) + "\n})";
106     else {
107         program = "(function(" + args.at(0).toString(exec);
108         for (size_t i = 1; i < args.size() - 1; i++)
109             program += "," + args.at(i).toString(exec);
110         program += ") { " + args.at(args.size() - 1).toString(exec) + "\n})";
111     }
112 
113     int errLine;
114     UString errMsg;
115     SourceCode source = makeSource(program, sourceURL, lineNumber);
116     RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
117 
118     FunctionBodyNode* body = extractFunctionBody(programNode.get());
119     if (!body)
120         return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
121 
122     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
123     ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
124     return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
125 }
126 
127 // ECMA 15.3.2 The Function Constructor
constructFunction(ExecState * exec,const ArgList & args)128 JSObject* constructFunction(ExecState* exec, const ArgList& args)
129 {
130     return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
131 }
132 
133 } // namespace JSC
134