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 | } |
58 | |
59 | void FunctionPrototype::addFunctionProperties(VM& vm, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction, JSFunction** hasInstanceSymbolFunction) |
60 | { |
61 | JSFunction* toStringFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->toString.string(), functionProtoFuncToString); |
62 | putDirectWithoutTransition(vm, vm.propertyNames->toString, toStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum)); |
63 | |
64 | *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum)); |
65 | *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum)); |
66 | putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->bind, functionPrototypeBindCodeGenerator(vm), static_cast<unsigned>(PropertyAttribute::DontEnum)); |
67 | |
68 | *hasInstanceSymbolFunction = JSFunction::create(vm, functionPrototypeSymbolHasInstanceCodeGenerator(vm), globalObject); |
69 | putDirectWithoutTransition(vm, vm.propertyNames->hasInstanceSymbol, *hasInstanceSymbolFunction, PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum); |
70 | } |
71 | |
72 | void FunctionPrototype::initRestrictedProperties(VM& vm, JSGlobalObject* globalObject) |
73 | { |
74 | GetterSetter* errorGetterSetter = globalObject->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(); |
75 | putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->caller, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); |
76 | putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->arguments, errorGetterSetter, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); |
77 | } |
78 | |
79 | EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) |
80 | { |
81 | VM& vm = exec->vm(); |
82 | auto scope = DECLARE_THROW_SCOPE(vm); |
83 | |
84 | JSValue thisValue = exec->thisValue(); |
85 | if (thisValue.inherits<JSFunction>(vm)) { |
86 | JSFunction* function = jsCast<JSFunction*>(thisValue); |
87 | if (function->isHostOrBuiltinFunction()) |
88 | RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function " , function->name(vm), "() {\n [native code]\n}" ))); |
89 | |
90 | FunctionExecutable* executable = function->jsExecutable(); |
91 | if (executable->isClass()) |
92 | return JSValue::encode(jsString(exec, executable->classSource().view().toString())); |
93 | |
94 | String ; |
95 | switch (executable->parseMode()) { |
96 | case SourceParseMode::GeneratorWrapperFunctionMode: |
97 | case SourceParseMode::GeneratorWrapperMethodMode: |
98 | functionHeader = "function* " ; |
99 | break; |
100 | |
101 | case SourceParseMode::NormalFunctionMode: |
102 | case SourceParseMode::GetterMode: |
103 | case SourceParseMode::SetterMode: |
104 | case SourceParseMode::MethodMode: |
105 | case SourceParseMode::ProgramMode: |
106 | case SourceParseMode::ModuleAnalyzeMode: |
107 | case SourceParseMode::ModuleEvaluateMode: |
108 | case SourceParseMode::GeneratorBodyMode: |
109 | case SourceParseMode::AsyncGeneratorBodyMode: |
110 | case SourceParseMode::AsyncFunctionBodyMode: |
111 | case SourceParseMode::AsyncArrowFunctionBodyMode: |
112 | functionHeader = "function " ; |
113 | break; |
114 | |
115 | case SourceParseMode::ArrowFunctionMode: |
116 | functionHeader = "" ; |
117 | break; |
118 | |
119 | case SourceParseMode::AsyncFunctionMode: |
120 | case SourceParseMode::AsyncMethodMode: |
121 | functionHeader = "async function " ; |
122 | break; |
123 | |
124 | case SourceParseMode::AsyncArrowFunctionMode: |
125 | functionHeader = "async " ; |
126 | break; |
127 | |
128 | case SourceParseMode::AsyncGeneratorWrapperFunctionMode: |
129 | case SourceParseMode::AsyncGeneratorWrapperMethodMode: |
130 | functionHeader = "async function* " ; |
131 | break; |
132 | } |
133 | |
134 | StringView source = executable->source().provider()->getRange( |
135 | executable->parametersStartOffset(), |
136 | executable->parametersStartOffset() + executable->source().length()); |
137 | RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source))); |
138 | } |
139 | |
140 | if (thisValue.inherits<InternalFunction>(vm)) { |
141 | InternalFunction* function = jsCast<InternalFunction*>(thisValue); |
142 | RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function " , function->name(), "() {\n [native code]\n}" ))); |
143 | } |
144 | |
145 | if (thisValue.isObject()) { |
146 | JSObject* object = asObject(thisValue); |
147 | if (object->isFunction(vm)) |
148 | RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(exec, "function " , object->classInfo(vm)->className, "() {\n [native code]\n}" ))); |
149 | } |
150 | |
151 | return throwVMTypeError(exec, scope); |
152 | } |
153 | |
154 | } // namespace JSC |
155 | |