Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) 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 "Debugger.h"
     25 #include "ExceptionHelpers.h"
     26 #include "FunctionPrototype.h"
     27 #include "JSFunction.h"
     28 #include "JSGlobalObject.h"
     29 #include "JSString.h"
     30 #include "Lexer.h"
     31 #include "Nodes.h"
     32 #include "Parser.h"
     33 #include "UStringBuilder.h"
     34 #include "UStringConcatenate.h"
     35 
     36 namespace JSC {
     37 
     38 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
     39 
     40 FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype)
     41     : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className))
     42 {
     43     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
     44 
     45     // Number of arguments for constructor
     46     putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
     47 }
     48 
     49 static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec)
     50 {
     51     ArgList args(exec);
     52     return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
     53 }
     54 
     55 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
     56 {
     57     constructData.native.function = constructWithFunctionConstructor;
     58     return ConstructTypeHost;
     59 }
     60 
     61 static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec)
     62 {
     63     ArgList args(exec);
     64     return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
     65 }
     66 
     67 // ECMA 15.3.1 The Function Constructor Called as a Function
     68 CallType FunctionConstructor::getCallData(CallData& callData)
     69 {
     70     callData.native.function = callFunctionConstructor;
     71     return CallTypeHost;
     72 }
     73 
     74 // ECMA 15.3.2 The Function Constructor
     75 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
     76 {
     77     // Functions need to have a space following the opening { due to for web compatibility
     78     // see https://bugs.webkit.org/show_bug.cgi?id=24350
     79     // We also need \n before the closing } to handle // comments at the end of the last line
     80     UString program;
     81     if (args.isEmpty())
     82         program = "(function() { \n})";
     83     else if (args.size() == 1)
     84         program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
     85     else {
     86         UStringBuilder builder;
     87         builder.append("(function(");
     88         builder.append(args.at(0).toString(exec));
     89         for (size_t i = 1; i < args.size() - 1; i++) {
     90             builder.append(",");
     91             builder.append(args.at(i).toString(exec));
     92         }
     93         builder.append(") { ");
     94         builder.append(args.at(args.size() - 1).toString(exec));
     95         builder.append("\n})");
     96         program = builder.toUString();
     97     }
     98 
     99     JSGlobalData& globalData = globalObject->globalData();
    100     SourceCode source = makeSource(program, sourceURL, lineNumber);
    101     JSObject* exception = 0;
    102     FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
    103     if (!function) {
    104         ASSERT(exception);
    105         return throwError(exec, exception);
    106     }
    107 
    108     ScopeChainNode* scopeChain = new (exec) ScopeChainNode(0, globalObject, &globalData, globalObject, exec->globalThisValue());
    109     return new (exec) JSFunction(exec, function, scopeChain);
    110 }
    111 
    112 // ECMA 15.3.2 The Function Constructor
    113 JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
    114 {
    115     return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1);
    116 }
    117 
    118 } // namespace JSC
    119