8a0d5c4af232f305c97f880d11288ceb77a4e302
[WebKit.git] / Source / JavaScriptCore / runtime / FunctionPrototype.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003-2009, 2015-2016 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 "FunctionPrototype.h"
23
24 #include "BuiltinExecutables.h"
25 #include "BuiltinNames.h"
26 #include "Error.h"
27 #include "GetterSetter.h"
28 #include "JSAsyncFunction.h"
29 #include "JSCInlines.h"
30 #include "JSFunction.h"
31 #include "JSStringInlines.h"
32 #include "Lexer.h"
33
34 namespace JSC {
35
36 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(FunctionPrototype);
37
38 const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(FunctionPrototype) };
39
40 static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
41
42 // ECMA 15.3.4
43 static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
44 {
45     return JSValue::encode(jsUndefined());
46 }
47
48 FunctionPrototype::FunctionPrototype(VM& vm, Structure* structure)
49     : InternalFunction(vm, structure, callFunctionPrototype, nullptr)
50 {
51 }
52
53 void FunctionPrototype::finishCreation(VM& vm, const String& name)
54 {
55     Base::finishCreation(vm, name, NameVisibility::Visible, NameAdditionMode::WithoutStructureTransition);
56     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
57     didBecomePrototype();
58 }
59
60 void FunctionPrototype::addFunctionProperties(VM& vm, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction, JSFunction** hasInstanceSymbolFunction)
61 {
62     JSFunction* toStringFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->toString.string(), functionProtoFuncToString);
63     putDirectWithoutTransition(vm, vm.propertyNames->toString, toStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
64
65     *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
66     *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
67     putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->bind, functionPrototypeBindCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
68
69     *hasInstanceSymbolFunction = JSFunction::create(vm, functionPrototypeSymbolHasInstanceCodeGenerator(vm), globalObject);
70     putDirectWithoutTransition(vm, vm.propertyNames->hasInstanceSymbol, *hasInstanceSymbolFunction, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
71 }
72     
73 void FunctionPrototype::initRestrictedProperties(VM& vm, JSGlobalObject* globalObject)
74 {
75     GetterSetter* errorGetterSetter = globalObject->throwTypeErrorArgumentsCalleeAndCallerGetterSetter();
76     putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->caller, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
77     putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->arguments, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
78 }
79
80 EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
81 {
82     VM& vm = exec->vm();
83     auto scope = DECLARE_THROW_SCOPE(vm);
84
85     JSValue thisValue = exec->thisValue();
86     if (thisValue.inherits<JSFunction>(vm)) {
87         JSFunction* function = jsCast<JSFunction*>(thisValue);
88         if (function->isHostOrBuiltinFunction())
89             RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n    [native code]\n}")));
90
91         FunctionExecutable* executable = function->jsExecutable();
92         if (executable->isClass())
93             return JSValue::encode(jsString(exec, executable->classSource().view().toString()));
94
95         String functionHeader;
96         switch (executable->parseMode()) {
97         case SourceParseMode::GeneratorWrapperFunctionMode:
98         case SourceParseMode::GeneratorWrapperMethodMode:
99             functionHeader = "function* ";
100             break;
101
102         case SourceParseMode::NormalFunctionMode:
103         case SourceParseMode::GetterMode:
104         case SourceParseMode::SetterMode:
105         case SourceParseMode::MethodMode:
106         case SourceParseMode::ProgramMode:
107         case SourceParseMode::ModuleAnalyzeMode:
108         case SourceParseMode::ModuleEvaluateMode:
109         case SourceParseMode::GeneratorBodyMode:
110         case SourceParseMode::AsyncGeneratorBodyMode:
111         case SourceParseMode::AsyncFunctionBodyMode:
112         case SourceParseMode::AsyncArrowFunctionBodyMode:
113             functionHeader = "function ";
114             break;
115
116         case SourceParseMode::ArrowFunctionMode:
117             functionHeader = "";
118             break;
119
120         case SourceParseMode::AsyncFunctionMode:
121         case SourceParseMode::AsyncMethodMode:
122             functionHeader = "async function ";
123             break;
124
125         case SourceParseMode::AsyncArrowFunctionMode:
126             functionHeader = "async ";
127             break;
128
129         case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
130         case SourceParseMode::AsyncGeneratorWrapperMethodMode:
131             functionHeader = "async function* ";
132             break;
133         }
134
135         StringView source = executable->source().provider()->getRange(
136             executable->parametersStartOffset(),
137             executable->parametersStartOffset() + executable->source().length());
138         RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)));
139     }
140
141     if (thisValue.inherits<InternalFunction>(vm)) {
142         InternalFunction* function = jsCast<InternalFunction*>(thisValue);
143         RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}")));
144     }
145
146     if (thisValue.isObject()) {
147         JSObject* object = asObject(thisValue);
148         if (object->isFunction(vm))
149             RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function ", object->classInfo(vm)->className, "() {\n    [native code]\n}")));
150     }
151
152     return throwVMTypeError(exec, scope);
153 }
154
155 } // namespace JSC