/ runtime / FunctionPrototype.cpp
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