chromium/v8/include/v8-template.h

// 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_