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