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