1/* 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 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 "JSCInlines.h" 33#include "Parser.h" 34#include <wtf/text/StringBuilder.h> 35 36namespace JSC { 37 38STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(FunctionConstructor); 39 40const ClassInfo FunctionConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionConstructor) }; 41 42FunctionConstructor::FunctionConstructor(VM& vm, Structure* structure) 43 : InternalFunction(vm, structure) 44{ 45} 46 47void FunctionConstructor::finishCreation(VM& vm, FunctionPrototype* functionPrototype) 48{ 49 Base::finishCreation(vm, functionPrototype->classInfo()->className); 50 putDirectWithoutTransition(vm, vm.propertyNames->prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); 51 52 // Number of arguments for constructor 53 putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum); 54} 55 56static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec) 57{ 58 ArgList args(exec); 59 return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); 60} 61 62ConstructType FunctionConstructor::getConstructData(JSCell*, ConstructData& constructData) 63{ 64 constructData.native.function = constructWithFunctionConstructor; 65 return ConstructTypeHost; 66} 67 68static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec) 69{ 70 ArgList args(exec); 71 return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); 72} 73 74// ECMA 15.3.1 The Function Constructor Called as a Function 75CallType FunctionConstructor::getCallData(JSCell*, CallData& callData) 76{ 77 callData.native.function = callFunctionConstructor; 78 return CallTypeHost; 79} 80 81// ECMA 15.3.2 The Function Constructor 82JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position) 83{ 84 if (!globalObject->evalEnabled()) 85 return exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage())); 86 return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position); 87} 88 89JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position) 90{ 91 // Functions need to have a space following the opening { due to for web compatibility 92 // see https://bugs.webkit.org/show_bug.cgi?id=24350 93 // We also need \n before the closing } to handle // comments at the end of the last line 94 String program; 95 if (args.isEmpty()) 96 program = ASCIILiteral("(function() {\n})"); 97 else if (args.size() == 1) 98 program = makeString("(function() {", args.at(0).toString(exec)->value(exec), "\n})"); 99 else { 100 StringBuilder builder; 101 builder.appendLiteral("(function("); 102 builder.append(args.at(0).toString(exec)->value(exec)); 103 for (size_t i = 1; i < args.size() - 1; i++) { 104 builder.append(','); 105 builder.append(args.at(i).toString(exec)->value(exec)); 106 } 107 builder.appendLiteral(") {"); 108 builder.append(args.at(args.size() - 1).toString(exec)->value(exec)); 109 builder.appendLiteral("\n})"); 110 program = builder.toString(); 111 } 112 113 SourceCode source = makeSource(program, sourceURL, position); 114 JSObject* exception = 0; 115 FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->vmEntryGlobalObject()->debugger(), source, &exception); 116 if (!function) { 117 ASSERT(exception); 118 return exec->vm().throwException(exec, exception); 119 } 120 121 return JSFunction::create(exec->vm(), function, globalObject); 122} 123 124// ECMA 15.3.2 The Function Constructor 125JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) 126{ 127 return constructFunction(exec, globalObject, args, exec->propertyNames().anonymous, String(), TextPosition::minimumPosition()); 128} 129 130} // namespace JSC 131