• 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