v8-function-callback.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. // Copyright 2021 the V8 project authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef INCLUDE_V8_FUNCTION_CALLBACK_H_
  5. #define INCLUDE_V8_FUNCTION_CALLBACK_H_
  6. #include "v8-local-handle.h" // NOLINT(build/include_directory)
  7. #include "v8-primitive.h" // NOLINT(build/include_directory)
  8. #include "v8config.h" // NOLINT(build/include_directory)
  9. namespace v8 {
  10. template <typename T>
  11. class BasicTracedReference;
  12. template <typename T>
  13. class Global;
  14. class Object;
  15. class Value;
  16. namespace internal {
  17. class FunctionCallbackArguments;
  18. class PropertyCallbackArguments;
  19. } // namespace internal
  20. namespace debug {
  21. class ConsoleCallArguments;
  22. } // namespace debug
  23. template <typename T>
  24. class ReturnValue {
  25. public:
  26. template <class S>
  27. V8_INLINE ReturnValue(const ReturnValue<S>& that) : value_(that.value_) {
  28. static_assert(std::is_base_of<T, S>::value, "type check");
  29. }
  30. // Local setters
  31. template <typename S>
  32. V8_INLINE void Set(const Global<S>& handle);
  33. template <typename S>
  34. V8_INLINE void Set(const BasicTracedReference<S>& handle);
  35. template <typename S>
  36. V8_INLINE void Set(const Local<S> handle);
  37. // Fast primitive setters
  38. V8_INLINE void Set(bool value);
  39. V8_INLINE void Set(double i);
  40. V8_INLINE void Set(int32_t i);
  41. V8_INLINE void Set(uint32_t i);
  42. // Fast JS primitive setters
  43. V8_INLINE void SetNull();
  44. V8_INLINE void SetUndefined();
  45. V8_INLINE void SetEmptyString();
  46. // Convenience getter for Isolate
  47. V8_INLINE Isolate* GetIsolate() const;
  48. // Pointer setter: Uncompilable to prevent inadvertent misuse.
  49. template <typename S>
  50. V8_INLINE void Set(S* whatever);
  51. // Getter. Creates a new Local<> so it comes with a certain performance
  52. // hit. If the ReturnValue was not yet set, this will return the undefined
  53. // value.
  54. V8_INLINE Local<Value> Get() const;
  55. private:
  56. template <class F>
  57. friend class ReturnValue;
  58. template <class F>
  59. friend class FunctionCallbackInfo;
  60. template <class F>
  61. friend class PropertyCallbackInfo;
  62. template <class F, class G, class H>
  63. friend class PersistentValueMapBase;
  64. V8_INLINE void SetInternal(internal::Address value) { *value_ = value; }
  65. V8_INLINE internal::Address GetDefaultValue();
  66. V8_INLINE explicit ReturnValue(internal::Address* slot);
  67. internal::Address* value_;
  68. };
  69. /**
  70. * The argument information given to function call callbacks. This
  71. * class provides access to information about the context of the call,
  72. * including the receiver, the number and values of arguments, and
  73. * the holder of the function.
  74. */
  75. template <typename T>
  76. class FunctionCallbackInfo {
  77. public:
  78. /** The number of available arguments. */
  79. V8_INLINE int Length() const;
  80. /**
  81. * Accessor for the available arguments. Returns `undefined` if the index
  82. * is out of bounds.
  83. */
  84. V8_INLINE Local<Value> operator[](int i) const;
  85. /** Returns the receiver. This corresponds to the "this" value. */
  86. V8_INLINE Local<Object> This() const;
  87. /**
  88. * If the callback was created without a Signature, this is the same
  89. * value as This(). If there is a signature, and the signature didn't match
  90. * This() but one of its hidden prototypes, this will be the respective
  91. * hidden prototype.
  92. *
  93. * Note that this is not the prototype of This() on which the accessor
  94. * referencing this callback was found (which in V8 internally is often
  95. * referred to as holder [sic]).
  96. */
  97. V8_INLINE Local<Object> Holder() const;
  98. /** For construct calls, this returns the "new.target" value. */
  99. V8_INLINE Local<Value> NewTarget() const;
  100. /** Indicates whether this is a regular call or a construct call. */
  101. V8_INLINE bool IsConstructCall() const;
  102. /** The data argument specified when creating the callback. */
  103. V8_INLINE Local<Value> Data() const;
  104. /** The current Isolate. */
  105. V8_INLINE Isolate* GetIsolate() const;
  106. /** The ReturnValue for the call. */
  107. V8_INLINE ReturnValue<T> GetReturnValue() const;
  108. // This shouldn't be public, but the arm compiler needs it.
  109. static const int kArgsLength = 6;
  110. protected:
  111. friend class internal::FunctionCallbackArguments;
  112. friend class internal::CustomArguments<FunctionCallbackInfo>;
  113. friend class debug::ConsoleCallArguments;
  114. static const int kHolderIndex = 0;
  115. static const int kIsolateIndex = 1;
  116. static const int kReturnValueDefaultValueIndex = 2;
  117. static const int kReturnValueIndex = 3;
  118. static const int kDataIndex = 4;
  119. static const int kNewTargetIndex = 5;
  120. V8_INLINE FunctionCallbackInfo(internal::Address* implicit_args,
  121. internal::Address* values, int length);
  122. internal::Address* implicit_args_;
  123. internal::Address* values_;
  124. int length_;
  125. };
  126. /**
  127. * The information passed to a property callback about the context
  128. * of the property access.
  129. */
  130. template <typename T>
  131. class PropertyCallbackInfo {
  132. public:
  133. /**
  134. * \return The isolate of the property access.
  135. */
  136. V8_INLINE Isolate* GetIsolate() const;
  137. /**
  138. * \return The data set in the configuration, i.e., in
  139. * `NamedPropertyHandlerConfiguration` or
  140. * `IndexedPropertyHandlerConfiguration.`
  141. */
  142. V8_INLINE Local<Value> Data() const;
  143. /**
  144. * \return The receiver. In many cases, this is the object on which the
  145. * property access was intercepted. When using
  146. * `Reflect.get`, `Function.prototype.call`, or similar functions, it is the
  147. * object passed in as receiver or thisArg.
  148. *
  149. * \code
  150. * void GetterCallback(Local<Name> name,
  151. * const v8::PropertyCallbackInfo<v8::Value>& info) {
  152. * auto context = info.GetIsolate()->GetCurrentContext();
  153. *
  154. * v8::Local<v8::Value> a_this =
  155. * info.This()
  156. * ->GetRealNamedProperty(context, v8_str("a"))
  157. * .ToLocalChecked();
  158. * v8::Local<v8::Value> a_holder =
  159. * info.Holder()
  160. * ->GetRealNamedProperty(context, v8_str("a"))
  161. * .ToLocalChecked();
  162. *
  163. * CHECK(v8_str("r")->Equals(context, a_this).FromJust());
  164. * CHECK(v8_str("obj")->Equals(context, a_holder).FromJust());
  165. *
  166. * info.GetReturnValue().Set(name);
  167. * }
  168. *
  169. * v8::Local<v8::FunctionTemplate> templ =
  170. * v8::FunctionTemplate::New(isolate);
  171. * templ->InstanceTemplate()->SetHandler(
  172. * v8::NamedPropertyHandlerConfiguration(GetterCallback));
  173. * LocalContext env;
  174. * env->Global()
  175. * ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local())
  176. * .ToLocalChecked()
  177. * ->NewInstance(env.local())
  178. * .ToLocalChecked())
  179. * .FromJust();
  180. *
  181. * CompileRun("obj.a = 'obj'; var r = {a: 'r'}; Reflect.get(obj, 'x', r)");
  182. * \endcode
  183. */
  184. V8_INLINE Local<Object> This() const;
  185. /**
  186. * \return The object in the prototype chain of the receiver that has the
  187. * interceptor. Suppose you have `x` and its prototype is `y`, and `y`
  188. * has an interceptor. Then `info.This()` is `x` and `info.Holder()` is `y`.
  189. * The Holder() could be a hidden object (the global object, rather
  190. * than the global proxy).
  191. *
  192. * \note For security reasons, do not pass the object back into the runtime.
  193. */
  194. V8_INLINE Local<Object> Holder() const;
  195. /**
  196. * \return The return value of the callback.
  197. * Can be changed by calling Set().
  198. * \code
  199. * info.GetReturnValue().Set(...)
  200. * \endcode
  201. *
  202. */
  203. V8_INLINE ReturnValue<T> GetReturnValue() const;
  204. /**
  205. * \return True if the intercepted function should throw if an error occurs.
  206. * Usually, `true` corresponds to `'use strict'`.
  207. *
  208. * \note Always `false` when intercepting `Reflect.set()`
  209. * independent of the language mode.
  210. */
  211. V8_INLINE bool ShouldThrowOnError() const;
  212. // This shouldn't be public, but the arm compiler needs it.
  213. static const int kArgsLength = 7;
  214. protected:
  215. friend class MacroAssembler;
  216. friend class internal::PropertyCallbackArguments;
  217. friend class internal::CustomArguments<PropertyCallbackInfo>;
  218. static const int kShouldThrowOnErrorIndex = 0;
  219. static const int kHolderIndex = 1;
  220. static const int kIsolateIndex = 2;
  221. static const int kReturnValueDefaultValueIndex = 3;
  222. static const int kReturnValueIndex = 4;
  223. static const int kDataIndex = 5;
  224. static const int kThisIndex = 6;
  225. V8_INLINE PropertyCallbackInfo(internal::Address* args) : args_(args) {}
  226. internal::Address* args_;
  227. };
  228. using FunctionCallback = void (*)(const FunctionCallbackInfo<Value>& info);
  229. // --- Implementation ---
  230. template <typename T>
  231. ReturnValue<T>::ReturnValue(internal::Address* slot) : value_(slot) {}
  232. template <typename T>
  233. template <typename S>
  234. void ReturnValue<T>::Set(const Global<S>& handle) {
  235. static_assert(std::is_base_of<T, S>::value, "type check");
  236. if (V8_UNLIKELY(handle.IsEmpty())) {
  237. *value_ = GetDefaultValue();
  238. } else {
  239. *value_ = *reinterpret_cast<internal::Address*>(*handle);
  240. }
  241. }
  242. template <typename T>
  243. template <typename S>
  244. void ReturnValue<T>::Set(const BasicTracedReference<S>& handle) {
  245. static_assert(std::is_base_of<T, S>::value, "type check");
  246. if (V8_UNLIKELY(handle.IsEmpty())) {
  247. *value_ = GetDefaultValue();
  248. } else {
  249. *value_ = *reinterpret_cast<internal::Address*>(handle.val_);
  250. }
  251. }
  252. template <typename T>
  253. template <typename S>
  254. void ReturnValue<T>::Set(const Local<S> handle) {
  255. static_assert(std::is_void<T>::value || std::is_base_of<T, S>::value,
  256. "type check");
  257. if (V8_UNLIKELY(handle.IsEmpty())) {
  258. *value_ = GetDefaultValue();
  259. } else {
  260. *value_ = *reinterpret_cast<internal::Address*>(*handle);
  261. }
  262. }
  263. template <typename T>
  264. void ReturnValue<T>::Set(double i) {
  265. static_assert(std::is_base_of<T, Number>::value, "type check");
  266. Set(Number::New(GetIsolate(), i));
  267. }
  268. template <typename T>
  269. void ReturnValue<T>::Set(int32_t i) {
  270. static_assert(std::is_base_of<T, Integer>::value, "type check");
  271. using I = internal::Internals;
  272. if (V8_LIKELY(I::IsValidSmi(i))) {
  273. *value_ = I::IntToSmi(i);
  274. return;
  275. }
  276. Set(Integer::New(GetIsolate(), i));
  277. }
  278. template <typename T>
  279. void ReturnValue<T>::Set(uint32_t i) {
  280. static_assert(std::is_base_of<T, Integer>::value, "type check");
  281. // Can't simply use INT32_MAX here for whatever reason.
  282. bool fits_into_int32_t = (i & (1U << 31)) == 0;
  283. if (V8_LIKELY(fits_into_int32_t)) {
  284. Set(static_cast<int32_t>(i));
  285. return;
  286. }
  287. Set(Integer::NewFromUnsigned(GetIsolate(), i));
  288. }
  289. template <typename T>
  290. void ReturnValue<T>::Set(bool value) {
  291. static_assert(std::is_base_of<T, Boolean>::value, "type check");
  292. using I = internal::Internals;
  293. int root_index;
  294. if (value) {
  295. root_index = I::kTrueValueRootIndex;
  296. } else {
  297. root_index = I::kFalseValueRootIndex;
  298. }
  299. *value_ = *I::GetRoot(GetIsolate(), root_index);
  300. }
  301. template <typename T>
  302. void ReturnValue<T>::SetNull() {
  303. static_assert(std::is_base_of<T, Primitive>::value, "type check");
  304. using I = internal::Internals;
  305. *value_ = *I::GetRoot(GetIsolate(), I::kNullValueRootIndex);
  306. }
  307. template <typename T>
  308. void ReturnValue<T>::SetUndefined() {
  309. static_assert(std::is_base_of<T, Primitive>::value, "type check");
  310. using I = internal::Internals;
  311. *value_ = *I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex);
  312. }
  313. template <typename T>
  314. void ReturnValue<T>::SetEmptyString() {
  315. static_assert(std::is_base_of<T, String>::value, "type check");
  316. using I = internal::Internals;
  317. *value_ = *I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex);
  318. }
  319. template <typename T>
  320. Isolate* ReturnValue<T>::GetIsolate() const {
  321. // Isolate is always the pointer below the default value on the stack.
  322. return *reinterpret_cast<Isolate**>(&value_[-2]);
  323. }
  324. template <typename T>
  325. Local<Value> ReturnValue<T>::Get() const {
  326. using I = internal::Internals;
  327. if (*value_ == *I::GetRoot(GetIsolate(), I::kTheHoleValueRootIndex))
  328. return Local<Value>(*Undefined(GetIsolate()));
  329. return Local<Value>::New(GetIsolate(), reinterpret_cast<Value*>(value_));
  330. }
  331. template <typename T>
  332. template <typename S>
  333. void ReturnValue<T>::Set(S* whatever) {
  334. static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse");
  335. }
  336. template <typename T>
  337. internal::Address ReturnValue<T>::GetDefaultValue() {
  338. // Default value is always the pointer below value_ on the stack.
  339. return value_[-1];
  340. }
  341. template <typename T>
  342. FunctionCallbackInfo<T>::FunctionCallbackInfo(internal::Address* implicit_args,
  343. internal::Address* values,
  344. int length)
  345. : implicit_args_(implicit_args), values_(values), length_(length) {}
  346. template <typename T>
  347. Local<Value> FunctionCallbackInfo<T>::operator[](int i) const {
  348. // values_ points to the first argument (not the receiver).
  349. if (i < 0 || length_ <= i) return Local<Value>(*Undefined(GetIsolate()));
  350. return Local<Value>(reinterpret_cast<Value*>(values_ + i));
  351. }
  352. template <typename T>
  353. Local<Object> FunctionCallbackInfo<T>::This() const {
  354. // values_ points to the first argument (not the receiver).
  355. return Local<Object>(reinterpret_cast<Object*>(values_ - 1));
  356. }
  357. template <typename T>
  358. Local<Object> FunctionCallbackInfo<T>::Holder() const {
  359. return Local<Object>(
  360. reinterpret_cast<Object*>(&implicit_args_[kHolderIndex]));
  361. }
  362. template <typename T>
  363. Local<Value> FunctionCallbackInfo<T>::NewTarget() const {
  364. return Local<Value>(
  365. reinterpret_cast<Value*>(&implicit_args_[kNewTargetIndex]));
  366. }
  367. template <typename T>
  368. Local<Value> FunctionCallbackInfo<T>::Data() const {
  369. return Local<Value>(reinterpret_cast<Value*>(&implicit_args_[kDataIndex]));
  370. }
  371. template <typename T>
  372. Isolate* FunctionCallbackInfo<T>::GetIsolate() const {
  373. return *reinterpret_cast<Isolate**>(&implicit_args_[kIsolateIndex]);
  374. }
  375. template <typename T>
  376. ReturnValue<T> FunctionCallbackInfo<T>::GetReturnValue() const {
  377. return ReturnValue<T>(&implicit_args_[kReturnValueIndex]);
  378. }
  379. template <typename T>
  380. bool FunctionCallbackInfo<T>::IsConstructCall() const {
  381. return !NewTarget()->IsUndefined();
  382. }
  383. template <typename T>
  384. int FunctionCallbackInfo<T>::Length() const {
  385. return length_;
  386. }
  387. template <typename T>
  388. Isolate* PropertyCallbackInfo<T>::GetIsolate() const {
  389. return *reinterpret_cast<Isolate**>(&args_[kIsolateIndex]);
  390. }
  391. template <typename T>
  392. Local<Value> PropertyCallbackInfo<T>::Data() const {
  393. return Local<Value>(reinterpret_cast<Value*>(&args_[kDataIndex]));
  394. }
  395. template <typename T>
  396. Local<Object> PropertyCallbackInfo<T>::This() const {
  397. return Local<Object>(reinterpret_cast<Object*>(&args_[kThisIndex]));
  398. }
  399. template <typename T>
  400. Local<Object> PropertyCallbackInfo<T>::Holder() const {
  401. return Local<Object>(reinterpret_cast<Object*>(&args_[kHolderIndex]));
  402. }
  403. template <typename T>
  404. ReturnValue<T> PropertyCallbackInfo<T>::GetReturnValue() const {
  405. return ReturnValue<T>(&args_[kReturnValueIndex]);
  406. }
  407. template <typename T>
  408. bool PropertyCallbackInfo<T>::ShouldThrowOnError() const {
  409. using I = internal::Internals;
  410. if (args_[kShouldThrowOnErrorIndex] !=
  411. I::IntToSmi(I::kInferShouldThrowMode)) {
  412. return args_[kShouldThrowOnErrorIndex] != I::IntToSmi(I::kDontThrow);
  413. }
  414. return v8::internal::ShouldThrowOnError(
  415. reinterpret_cast<v8::internal::Isolate*>(GetIsolate()));
  416. }
  417. } // namespace v8
  418. #endif // INCLUDE_V8_FUNCTION_CALLBACK_H_