// Copyright 2021 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef INCLUDE_V8_TEMPLATE_H_ #define INCLUDE_V8_TEMPLATE_H_ #include <cstddef> #include <string_view> #include "v8-data.h" // NOLINT(build/include_directory) #include "v8-exception.h" // NOLINT(build/include_directory) #include "v8-function-callback.h" // NOLINT(build/include_directory) #include "v8-local-handle.h" // NOLINT(build/include_directory) #include "v8-memory-span.h" // NOLINT(build/include_directory) #include "v8-object.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory) namespace v8 { class CFunction; class FunctionTemplate; class ObjectTemplate; class Signature; // --- Templates --- #define V8_INTRINSICS_LIST(F) … enum Intrinsic { … }; /** * The superclass of object and function templates. */ class V8_EXPORT Template : public Data { … }; /** * Interceptor callbacks use this value to indicate whether the request was * intercepted or not. */ enum class Intercepted : uint8_t { … }; /** * Interceptor for get requests on an object. * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should * - (optionally) use info.GetReturnValue().Set()` to set the return value * (by default the result is set to v8::Undefined), * - return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \param info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * \code * Intercepted GetterCallback( * Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { * if (!IsKnownProperty(info.GetIsolate(), name)) return Intercepted::kNo; * info.GetReturnValue().Set(v8_num(42)); * return Intercepted::kYes; * } * * v8::Local<v8::FunctionTemplate> templ = * v8::FunctionTemplate::New(isolate); * templ->InstanceTemplate()->SetHandler( * v8::NamedPropertyHandlerConfiguration(GetterCallback)); * LocalContext env; * env->Global() * ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local()) * .ToLocalChecked() * ->NewInstance(env.local()) * .ToLocalChecked()) * .FromJust(); * v8::Local<v8::Value> result = CompileRun("obj.a = 17; obj.a"); * CHECK(v8_num(42)->Equals(env.local(), result).FromJust()); * \endcode * * See also `ObjectTemplate::SetHandler`. */ NamedPropertyGetterCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue().Set()` to set the return value of the // intercepted get request. If the property does not exist the callback should // not set the result and must not produce side effects. GenericNamedPropertyGetterCallback; /** * Interceptor for set requests on an object. * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \param value The value which the property will have if the request * is not intercepted. * \param info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * See also `ObjectTemplate::SetHandler.` */ NamedPropertySetterCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue()` to indicate whether the request was intercepted // or not. If the setter successfully intercepts the request, i.e., if the // request should not be further executed, call // `info.GetReturnValue().Set(value)`. If the setter did not intercept the // request, i.e., if the request should be handled as if no interceptor is // present, do not not call `Set()` and do not produce side effects. GenericNamedPropertySetterCallback; /** * Intercepts all requests that query the attributes of the * property, e.g., getOwnPropertyDescriptor(), propertyIsEnumerable(), and * defineProperty(). * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should * - (optionally) use `info.GetReturnValue().Set()` to set to an Integer * value encoding a `v8::PropertyAttribute` bits, * - return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \param info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * \note Some functions query the property attributes internally, even though * they do not return the attributes. For example, `hasOwnProperty()` can * trigger this interceptor depending on the state of the object. * * See also `ObjectTemplate::SetHandler.` */ NamedPropertyQueryCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue().Set(value)` to set the property attributes. The // value is an integer encoding a `v8::PropertyAttribute`. If the property does // not exist the callback should not set the result and must not produce side // effects. GenericNamedPropertyQueryCallback; /** * Interceptor for delete requests on an object. * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should * - (optionally) use `info.GetReturnValue().Set()` to set to a Boolean value * indicating whether the property deletion was successful or not, * - return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \param info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * \note If you need to mimic the behavior of `delete`, i.e., throw in strict * mode instead of returning false, use `info.ShouldThrowOnError()` to determine * if you are in strict mode. * * See also `ObjectTemplate::SetHandler.` */ NamedPropertyDeleterCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue()` to indicate whether the request was intercepted // or not. If the deleter successfully intercepts the request, i.e., if the // request should not be further executed, call // `info.GetReturnValue().Set(value)` with a boolean `value`. The `value` is // used as the return value of `delete`. If the deleter does not intercept the // request then it should not set the result and must not produce side effects. GenericNamedPropertyDeleterCallback; /** * Returns an array containing the names of the properties the named * property getter intercepts. * * Note: The values in the array must be of type v8::Name. */ NamedPropertyEnumeratorCallback; // This variant will be deprecated soon. // This is just a renaming of the typedef. GenericNamedPropertyEnumeratorCallback; /** * Interceptor for defineProperty requests on an object. * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \param desc The property descriptor which is used to define the * property if the request is not intercepted. * \param info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * See also `ObjectTemplate::SetHandler`. */ NamedPropertyDefinerCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue()` to indicate whether the request was intercepted // or not. If the definer successfully intercepts the request, i.e., if the // request should not be further executed, call // `info.GetReturnValue().Set(value)`. If the definer did not intercept the // request, i.e., if the request should be handled as if no interceptor is // present, do not not call `Set()` and do not produce side effects. GenericNamedPropertyDefinerCallback; /** * Interceptor for getOwnPropertyDescriptor requests on an object. * * If the interceptor handles the request (i.e. the property should not be * looked up beyond the interceptor or in case an exception was thrown) it * should * - (optionally) use `info.GetReturnValue().Set()` to set the return value * which must be object that can be converted to a PropertyDescriptor (for * example, a value returned by `v8::Object::getOwnPropertyDescriptor`), * - return `Intercepted::kYes`. * If the interceptor does not handle the request it must return * `Intercepted::kNo` and it must not produce side effects. * * \param property The name of the property for which the request was * intercepted. * \info Information about the intercepted request, such as * isolate, receiver, return value, or whether running in `'use strict'` mode. * See `PropertyCallbackInfo`. * * \note If GetOwnPropertyDescriptor is intercepted, it will * always return true, i.e., indicate that the property was found. * * See also `ObjectTemplate::SetHandler`. */ NamedPropertyDescriptorCallback; // This variant will be deprecated soon. // // Use `info.GetReturnValue().Set()` to set the return value of the // intercepted request. The return value must be an object that // can be converted to a PropertyDescriptor, e.g., a `v8::Value` returned from // `v8::Object::getOwnPropertyDescriptor`. GenericNamedPropertyDescriptorCallback; // TODO(ishell): Rename IndexedPropertyXxxCallbackV2 back to // IndexedPropertyXxxCallback once the old IndexedPropertyXxxCallback is // removed. /** * See `v8::NamedPropertyGetterCallback`. */ IndexedPropertyGetterCallbackV2; // This variant will be deprecated soon. IndexedPropertyGetterCallback; /** * See `v8::NamedPropertySetterCallback`. */ IndexedPropertySetterCallbackV2; // This variant will be deprecated soon. IndexedPropertySetterCallback; /** * See `v8::NamedPropertyQueryCallback`. */ IndexedPropertyQueryCallbackV2; // This variant will be deprecated soon. IndexedPropertyQueryCallback; /** * See `v8::NamedPropertyDeleterCallback`. */ IndexedPropertyDeleterCallbackV2; // This variant will be deprecated soon. IndexedPropertyDeleterCallback; /** * Returns an array containing the indices of the properties the indexed * property getter intercepts. * * Note: The values in the array must be uint32_t. */ IndexedPropertyEnumeratorCallback; /** * See `v8::NamedPropertyDefinerCallback`. */ IndexedPropertyDefinerCallbackV2; // This variant will be deprecated soon. IndexedPropertyDefinerCallback; /** * See `v8::NamedPropertyDescriptorCallback`. */ IndexedPropertyDescriptorCallbackV2; // This variant will be deprecated soon. IndexedPropertyDescriptorCallback; /** * Returns true if the given context should be allowed to access the given * object. */ AccessCheckCallback; enum class ConstructorBehavior { … }; /** * A FunctionTemplate is used to create functions at runtime. There * can only be one function created from a FunctionTemplate in a * context. The lifetime of the created function is equal to the * lifetime of the context. So in case the embedder needs to create * temporary functions that can be collected using Scripts is * preferred. * * Any modification of a FunctionTemplate after first instantiation will trigger * a crash. * * A FunctionTemplate can have properties, these properties are added to the * function object when it is created. * * A FunctionTemplate has a corresponding instance template which is * used to create object instances when the function is used as a * constructor. Properties added to the instance template are added to * each object instance. * * A FunctionTemplate can have a prototype template. The prototype template * is used to create the prototype object of the function. * * The following example shows how to use a FunctionTemplate: * * \code * v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate); * t->Set(isolate, "func_property", v8::Number::New(isolate, 1)); * * v8::Local<v8::Template> proto_t = t->PrototypeTemplate(); * proto_t->Set(isolate, * "proto_method", * v8::FunctionTemplate::New(isolate, InvokeCallback)); * proto_t->Set(isolate, "proto_const", v8::Number::New(isolate, 2)); * * v8::Local<v8::ObjectTemplate> instance_t = t->InstanceTemplate(); * instance_t->SetNativeDataProperty( * String::NewFromUtf8Literal(isolate, "instance_accessor"), * InstanceAccessorCallback); * instance_t->SetHandler( * NamedPropertyHandlerConfiguration(PropertyHandlerCallback)); * instance_t->Set(String::NewFromUtf8Literal(isolate, "instance_property"), * Number::New(isolate, 3)); * * v8::Local<v8::Function> function = t->GetFunction(); * v8::Local<v8::Object> instance = function->NewInstance(); * \endcode * * Let's use "function" as the JS variable name of the function object * and "instance" for the instance object created above. The function * and the instance will have the following properties: * * \code * func_property in function == true; * function.func_property == 1; * * function.prototype.proto_method() invokes 'InvokeCallback' * function.prototype.proto_const == 2; * * instance instanceof function == true; * instance.instance_accessor calls 'InstanceAccessorCallback' * instance.instance_property == 3; * \endcode * * A FunctionTemplate can inherit from another one by calling the * FunctionTemplate::Inherit method. The following graph illustrates * the semantics of inheritance: * * \code * FunctionTemplate Parent -> Parent() . prototype -> { } * ^ ^ * | Inherit(Parent) | .__proto__ * | | * FunctionTemplate Child -> Child() . prototype -> { } * \endcode * * A FunctionTemplate 'Child' inherits from 'Parent', the prototype * object of the Child() function has __proto__ pointing to the * Parent() function's prototype object. An instance of the Child * function has all properties on Parent's instance templates. * * Let Parent be the FunctionTemplate initialized in the previous * section and create a Child FunctionTemplate by: * * \code * Local<FunctionTemplate> parent = t; * Local<FunctionTemplate> child = FunctionTemplate::New(); * child->Inherit(parent); * * Local<Function> child_function = child->GetFunction(); * Local<Object> child_instance = child_function->NewInstance(); * \endcode * * The Child function and Child instance will have the following * properties: * * \code * child_func.prototype.__proto__ == function.prototype; * child_instance.instance_accessor calls 'InstanceAccessorCallback' * child_instance.instance_property == 3; * \endcode * * The additional 'c_function' parameter refers to a fast API call, which * must not trigger GC or JavaScript execution, or call into V8 in other * ways. For more information how to define them, see * include/v8-fast-api-calls.h. Please note that this feature is still * experimental. */ class V8_EXPORT FunctionTemplate : public Template { … }; /** * Configuration flags for v8::NamedPropertyHandlerConfiguration or * v8::IndexedPropertyHandlerConfiguration. */ enum class PropertyHandlerFlags { … }; struct NamedPropertyHandlerConfiguration { … }; struct IndexedPropertyHandlerConfiguration { … }; /** * An ObjectTemplate is used to create objects at runtime. * * Properties added to an ObjectTemplate are added to each object * created from the ObjectTemplate. */ class V8_EXPORT ObjectTemplate : public Template { … }; /** * A template to create dictionary objects at runtime. */ class V8_EXPORT DictionaryTemplate final { … }; /** * A Signature specifies which receiver is valid for a function. * * A receiver matches a given signature if the receiver (or any of its * hidden prototypes) was created from the signature's FunctionTemplate, or * from a FunctionTemplate that inherits directly or indirectly from the * signature's FunctionTemplate. */ class V8_EXPORT Signature : public Data { … }; // --- Implementation --- void Template::Set(Isolate* isolate, const char* name, Local<Data> value, PropertyAttribute attributes) { … } FunctionTemplate* FunctionTemplate::Cast(Data* data) { … } ObjectTemplate* ObjectTemplate::Cast(Data* data) { … } DictionaryTemplate* DictionaryTemplate::Cast(Data* data) { … } Signature* Signature::Cast(Data* data) { … } } // namespace v8 #endif // INCLUDE_V8_TEMPLATE_H_