V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
api.h
1 // Copyright 2012 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 
5 #ifndef V8_API_H_
6 #define V8_API_H_
7 
8 #include "include/v8-testing.h"
9 #include "src/contexts.h"
10 #include "src/debug/debug-interface.h"
11 #include "src/detachable-vector.h"
12 #include "src/heap/factory.h"
13 #include "src/isolate.h"
14 #include "src/objects.h"
15 #include "src/objects/bigint.h"
16 #include "src/objects/js-collection.h"
17 #include "src/objects/js-generator.h"
18 #include "src/objects/js-promise.h"
19 #include "src/objects/js-proxy.h"
20 #include "src/objects/module.h"
21 #include "src/objects/shared-function-info.h"
22 
23 #include "src/objects/templates.h"
24 
25 namespace v8 {
26 
27 // Constants used in the implementation of the API. The most natural thing
28 // would usually be to place these with the classes that use them, but
29 // we want to keep them out of v8.h because it is an externally
30 // visible file.
31 class Consts {
32  public:
33  enum TemplateType {
34  FUNCTION_TEMPLATE = 0,
35  OBJECT_TEMPLATE = 1
36  };
37 };
38 
39 template <typename T>
40 inline T ToCData(v8::internal::Object* obj);
41 
42 template <>
43 inline v8::internal::Address ToCData(v8::internal::Object* obj);
44 
45 template <typename T>
47  v8::internal::Isolate* isolate, T obj);
48 
49 template <>
51  v8::internal::Isolate* isolate, v8::internal::Address obj);
52 
53 class ApiFunction {
54  public:
55  explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
56  v8::internal::Address address() { return addr_; }
57  private:
59 };
60 
61 
62 
64  public:
65  explicit RegisteredExtension(Extension* extension);
66  static void Register(RegisteredExtension* that);
67  static void UnregisterAll();
68  Extension* extension() { return extension_; }
69  RegisteredExtension* next() { return next_; }
70  static RegisteredExtension* first_extension() { return first_extension_; }
71  private:
72  Extension* extension_;
73  RegisteredExtension* next_;
74  static RegisteredExtension* first_extension_;
75 };
76 
77 #define OPEN_HANDLE_LIST(V) \
78  V(Template, TemplateInfo) \
79  V(FunctionTemplate, FunctionTemplateInfo) \
80  V(ObjectTemplate, ObjectTemplateInfo) \
81  V(Signature, FunctionTemplateInfo) \
82  V(AccessorSignature, FunctionTemplateInfo) \
83  V(Data, Object) \
84  V(RegExp, JSRegExp) \
85  V(Object, JSReceiver) \
86  V(Array, JSArray) \
87  V(Map, JSMap) \
88  V(Set, JSSet) \
89  V(ArrayBuffer, JSArrayBuffer) \
90  V(ArrayBufferView, JSArrayBufferView) \
91  V(TypedArray, JSTypedArray) \
92  V(Uint8Array, JSTypedArray) \
93  V(Uint8ClampedArray, JSTypedArray) \
94  V(Int8Array, JSTypedArray) \
95  V(Uint16Array, JSTypedArray) \
96  V(Int16Array, JSTypedArray) \
97  V(Uint32Array, JSTypedArray) \
98  V(Int32Array, JSTypedArray) \
99  V(Float32Array, JSTypedArray) \
100  V(Float64Array, JSTypedArray) \
101  V(DataView, JSDataView) \
102  V(SharedArrayBuffer, JSArrayBuffer) \
103  V(Name, Name) \
104  V(String, String) \
105  V(Symbol, Symbol) \
106  V(Script, JSFunction) \
107  V(UnboundModuleScript, SharedFunctionInfo) \
108  V(UnboundScript, SharedFunctionInfo) \
109  V(Module, Module) \
110  V(Function, JSReceiver) \
111  V(Message, JSMessageObject) \
112  V(Context, Context) \
113  V(External, Object) \
114  V(StackTrace, FixedArray) \
115  V(StackFrame, StackFrameInfo) \
116  V(Proxy, JSProxy) \
117  V(debug::GeneratorObject, JSGeneratorObject) \
118  V(debug::Script, Script) \
119  V(debug::WeakMap, JSWeakMap) \
120  V(Promise, JSPromise) \
121  V(Primitive, Object) \
122  V(PrimitiveArray, FixedArray) \
123  V(BigInt, BigInt) \
124  V(ScriptOrModule, Script)
125 
126 class Utils {
127  public:
128  static inline bool ApiCheck(bool condition,
129  const char* location,
130  const char* message) {
131  if (!condition) Utils::ReportApiFailure(location, message);
132  return condition;
133  }
134  static void ReportOOMFailure(v8::internal::Isolate* isolate,
135  const char* location, bool is_heap_oom);
136 
137  static inline Local<Context> ToLocal(
139  static inline Local<Value> ToLocal(
141  static inline Local<Module> ToLocal(
143  static inline Local<Name> ToLocal(
145  static inline Local<String> ToLocal(
147  static inline Local<Symbol> ToLocal(
149  static inline Local<RegExp> ToLocal(
151  static inline Local<Object> ToLocal(
153  static inline Local<Object> ToLocal(
155  static inline Local<Function> ToLocal(
157  static inline Local<Array> ToLocal(
159  static inline Local<Map> ToLocal(
161  static inline Local<Set> ToLocal(
163  static inline Local<Proxy> ToLocal(
165  static inline Local<ArrayBuffer> ToLocal(
167  static inline Local<ArrayBufferView> ToLocal(
169  static inline Local<DataView> ToLocal(
171  static inline Local<TypedArray> ToLocal(
173  static inline Local<Uint8Array> ToLocalUint8Array(
175  static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray(
177  static inline Local<Int8Array> ToLocalInt8Array(
179  static inline Local<Uint16Array> ToLocalUint16Array(
181  static inline Local<Int16Array> ToLocalInt16Array(
183  static inline Local<Uint32Array> ToLocalUint32Array(
185  static inline Local<Int32Array> ToLocalInt32Array(
187  static inline Local<Float32Array> ToLocalFloat32Array(
189  static inline Local<Float64Array> ToLocalFloat64Array(
191  static inline Local<BigInt64Array> ToLocalBigInt64Array(
193  static inline Local<BigUint64Array> ToLocalBigUint64Array(
195 
196  static inline Local<SharedArrayBuffer> ToLocalShared(
198 
199  static inline Local<Message> MessageToLocal(
201  static inline Local<Promise> PromiseToLocal(
203  static inline Local<StackTrace> StackTraceToLocal(
205  static inline Local<StackFrame> StackFrameToLocal(
207  static inline Local<Number> NumberToLocal(
209  static inline Local<Integer> IntegerToLocal(
211  static inline Local<Uint32> Uint32ToLocal(
213  static inline Local<BigInt> ToLocal(
215  static inline Local<FunctionTemplate> ToLocal(
217  static inline Local<ObjectTemplate> ToLocal(
219  static inline Local<Signature> SignatureToLocal(
221  static inline Local<AccessorSignature> AccessorSignatureToLocal(
223  static inline Local<External> ExternalToLocal(
225  static inline Local<Function> CallableToLocal(
227  static inline Local<Primitive> ToLocalPrimitive(
229  static inline Local<PrimitiveArray> ToLocal(
231  static inline Local<ScriptOrModule> ScriptOrModuleToLocal(
233 
234 #define DECLARE_OPEN_HANDLE(From, To) \
235  static inline v8::internal::Handle<v8::internal::To> \
236  OpenHandle(const From* that, bool allow_empty_handle = false);
237 
238 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
239 
240 #undef DECLARE_OPEN_HANDLE
241 
242 template <class From, class To>
243 static inline Local<To> Convert(v8::internal::Handle<From> obj);
244 
245 template <class T>
246 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
247  const v8::Persistent<T>& persistent) {
249  reinterpret_cast<v8::internal::Address*>(persistent.val_));
250  }
251 
252  template <class T>
253  static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
254  v8::Persistent<T>* persistent) {
255  return OpenPersistent(*persistent);
256  }
257 
258  template <class From, class To>
259  static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
260  return OpenHandle(*handle);
261  }
262 
263  private:
264  static void ReportApiFailure(const char* location, const char* message);
265 };
266 
267 
268 template <class T>
270  return reinterpret_cast<T*>(obj.location());
271 }
272 
273 template <class T>
274 inline v8::Local<T> ToApiHandle(
276  return Utils::Convert<v8::internal::Object, T>(obj);
277 }
278 
279 
280 template <class T>
281 inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,
282  Local<T>* local) {
284  if (maybe.ToHandle(&handle)) {
285  *local = Utils::Convert<v8::internal::Object, T>(handle);
286  return true;
287  }
288  return false;
289 }
290 
291 namespace internal {
292 
293 class V8_EXPORT_PRIVATE DeferredHandles {
294  public:
295  ~DeferredHandles();
296 
297  private:
298  DeferredHandles(Address* first_block_limit, Isolate* isolate)
299  : next_(nullptr),
300  previous_(nullptr),
301  first_block_limit_(first_block_limit),
302  isolate_(isolate) {
303  isolate->LinkDeferredHandles(this);
304  }
305 
306  void Iterate(RootVisitor* v);
307 
308  std::vector<Address*> blocks_;
309  DeferredHandles* next_;
310  DeferredHandles* previous_;
311  Address* first_block_limit_;
312  Isolate* isolate_;
313 
314  friend class HandleScopeImplementer;
315  friend class Isolate;
316 };
317 
318 
319 // This class is here in order to be able to declare it a friend of
320 // HandleScope. Moving these methods to be members of HandleScope would be
321 // neat in some ways, but it would expose internal implementation details in
322 // our public header file, which is undesirable.
323 //
324 // An isolate has a single instance of this class to hold the current thread's
325 // data. In multithreaded V8 programs this data is copied in and out of storage
326 // so that the currently executing thread always has its own copy of this
327 // data.
329  public:
330  explicit HandleScopeImplementer(Isolate* isolate)
331  : isolate_(isolate),
332  spare_(nullptr),
333  call_depth_(0),
334  microtasks_depth_(0),
335  microtasks_suppressions_(0),
336  entered_contexts_count_(0),
337  entered_context_count_during_microtasks_(0),
338 #ifdef DEBUG
339  debug_microtasks_depth_(0),
340 #endif
341  microtasks_policy_(v8::MicrotasksPolicy::kAuto),
342  last_handle_before_deferred_block_(nullptr) {
343  }
344 
346  DeleteArray(spare_);
347  }
348 
349  // Threading support for handle data.
350  static int ArchiveSpacePerThread();
351  char* RestoreThread(char* from);
352  char* ArchiveThread(char* to);
353  void FreeThreadResources();
354 
355  // Garbage collection support.
356  void Iterate(v8::internal::RootVisitor* v);
357  static char* Iterate(v8::internal::RootVisitor* v, char* data);
358 
359  inline internal::Address* GetSpareOrNewBlock();
360  inline void DeleteExtensions(internal::Address* prev_limit);
361 
362  // Call depth represents nested v8 api calls.
363  inline void IncrementCallDepth() {call_depth_++;}
364  inline void DecrementCallDepth() {call_depth_--;}
365  inline bool CallDepthIsZero() { return call_depth_ == 0; }
366 
367  // Microtasks scope depth represents nested scopes controlling microtasks
368  // invocation, which happens when depth reaches zero.
369  inline void IncrementMicrotasksScopeDepth() {microtasks_depth_++;}
370  inline void DecrementMicrotasksScopeDepth() {microtasks_depth_--;}
371  inline int GetMicrotasksScopeDepth() { return microtasks_depth_; }
372 
373  // Possibly nested microtasks suppression scopes prevent microtasks
374  // from running.
375  inline void IncrementMicrotasksSuppressions() {microtasks_suppressions_++;}
376  inline void DecrementMicrotasksSuppressions() {microtasks_suppressions_--;}
377  inline bool HasMicrotasksSuppressions() { return !!microtasks_suppressions_; }
378 
379 #ifdef DEBUG
380  // In debug we check that calls not intended to invoke microtasks are
381  // still correctly wrapped with microtask scopes.
382  inline void IncrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_++;}
383  inline void DecrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_--;}
384  inline bool DebugMicrotasksScopeDepthIsZero() {
385  return debug_microtasks_depth_ == 0;
386  }
387 #endif
388 
389  inline void set_microtasks_policy(v8::MicrotasksPolicy policy);
390  inline v8::MicrotasksPolicy microtasks_policy() const;
391 
392  inline void EnterContext(Handle<Context> context);
393  inline void LeaveContext();
394  inline bool LastEnteredContextWas(Handle<Context> context);
395 
396  // Returns the last entered context or an empty handle if no
397  // contexts have been entered.
398  inline Handle<Context> LastEnteredContext();
399  inline Handle<Context> LastEnteredOrMicrotaskContext();
400 
401  inline void EnterMicrotaskContext(Handle<Context> context);
402  inline void LeaveMicrotaskContext();
403  inline Handle<Context> MicrotaskContext();
404  inline bool MicrotaskContextIsLastEnteredContext() const {
405  return !microtask_context_.is_null() &&
406  entered_context_count_during_microtasks_ == entered_contexts_.size();
407  }
408 
409  inline void SaveContext(Context context);
410  inline Context RestoreContext();
411  inline bool HasSavedContexts();
412 
413  inline DetachableVector<Address*>* blocks() { return &blocks_; }
414  Isolate* isolate() const { return isolate_; }
415 
416  void ReturnBlock(Address* block) {
417  DCHECK_NOT_NULL(block);
418  if (spare_ != nullptr) DeleteArray(spare_);
419  spare_ = block;
420  }
421 
422  private:
423  void ResetAfterArchive() {
424  blocks_.detach();
425  entered_contexts_.detach();
426  saved_contexts_.detach();
427  microtask_context_ = Context();
428  entered_context_count_during_microtasks_ = 0;
429  spare_ = nullptr;
430  last_handle_before_deferred_block_ = nullptr;
431  call_depth_ = 0;
432  }
433 
434  void Free() {
435  DCHECK(blocks_.empty());
436  DCHECK(entered_contexts_.empty());
437  DCHECK(saved_contexts_.empty());
438  DCHECK(microtask_context_.is_null());
439 
440  blocks_.free();
441  entered_contexts_.free();
442  saved_contexts_.free();
443  if (spare_ != nullptr) {
444  DeleteArray(spare_);
445  spare_ = nullptr;
446  }
447  DCHECK_EQ(call_depth_, 0);
448  }
449 
450  void BeginDeferredScope();
451  DeferredHandles* Detach(Address* prev_limit);
452 
453  Isolate* isolate_;
455  // Used as a stack to keep track of entered contexts.
456  DetachableVector<Context> entered_contexts_;
457  // Used as a stack to keep track of saved contexts.
458  DetachableVector<Context> saved_contexts_;
459  Context microtask_context_;
460  Address* spare_;
461  int call_depth_;
462  int microtasks_depth_;
463  int microtasks_suppressions_;
464  size_t entered_contexts_count_;
465  size_t entered_context_count_during_microtasks_;
466 #ifdef DEBUG
467  int debug_microtasks_depth_;
468 #endif
469  v8::MicrotasksPolicy microtasks_policy_;
470  Address* last_handle_before_deferred_block_;
471  // This is only used for threading support.
472  HandleScopeData handle_scope_data_;
473 
474  void IterateThis(RootVisitor* v);
475  char* RestoreThreadHelper(char* from);
476  char* ArchiveThreadHelper(char* to);
477 
478  friend class DeferredHandles;
479  friend class DeferredHandleScope;
480  friend class HandleScopeImplementerOffsets;
481 
482  DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
483 };
484 
486  public:
487  enum Offsets {
488  kMicrotaskContext = offsetof(HandleScopeImplementer, microtask_context_),
489  kEnteredContexts = offsetof(HandleScopeImplementer, entered_contexts_),
490  kEnteredContextsCount =
491  offsetof(HandleScopeImplementer, entered_contexts_count_),
492  kEnteredContextCountDuringMicrotasks = offsetof(
493  HandleScopeImplementer, entered_context_count_during_microtasks_)
494  };
495 
496  private:
497  DISALLOW_IMPLICIT_CONSTRUCTORS(HandleScopeImplementerOffsets);
498 };
499 
500 const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page
501 
502 
503 void HandleScopeImplementer::set_microtasks_policy(
504  v8::MicrotasksPolicy policy) {
505  microtasks_policy_ = policy;
506 }
507 
508 
509 v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const {
510  return microtasks_policy_;
511 }
512 
513 void HandleScopeImplementer::SaveContext(Context context) {
514  saved_contexts_.push_back(context);
515 }
516 
517 Context HandleScopeImplementer::RestoreContext() {
518  Context last_context = saved_contexts_.back();
519  saved_contexts_.pop_back();
520  return last_context;
521 }
522 
523 
524 bool HandleScopeImplementer::HasSavedContexts() {
525  return !saved_contexts_.empty();
526 }
527 
528 
529 void HandleScopeImplementer::EnterContext(Handle<Context> context) {
530  entered_contexts_.push_back(*context);
531  entered_contexts_count_ = entered_contexts_.size();
532 }
533 
534 void HandleScopeImplementer::LeaveContext() {
535  entered_contexts_.pop_back();
536  entered_contexts_count_ = entered_contexts_.size();
537 }
538 
539 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
540  return !entered_contexts_.empty() && entered_contexts_.back() == *context;
541 }
542 
543 void HandleScopeImplementer::EnterMicrotaskContext(Handle<Context> context) {
544  DCHECK(microtask_context_.is_null());
545  microtask_context_ = *context;
546  entered_context_count_during_microtasks_ = entered_contexts_.size();
547 }
548 
549 void HandleScopeImplementer::LeaveMicrotaskContext() {
550  microtask_context_ = Context();
551  entered_context_count_during_microtasks_ = 0;
552 }
553 
554 // If there's a spare block, use it for growing the current scope.
555 internal::Address* HandleScopeImplementer::GetSpareOrNewBlock() {
556  internal::Address* block =
557  (spare_ != nullptr) ? spare_
558  : NewArray<internal::Address>(kHandleBlockSize);
559  spare_ = nullptr;
560  return block;
561 }
562 
563 void HandleScopeImplementer::DeleteExtensions(internal::Address* prev_limit) {
564  while (!blocks_.empty()) {
565  internal::Address* block_start = blocks_.back();
566  internal::Address* block_limit = block_start + kHandleBlockSize;
567 
568  // SealHandleScope may make the prev_limit to point inside the block.
569  // Cast possibly-unrelated pointers to plain Addres before comparing them
570  // to avoid undefined behavior.
571  if (reinterpret_cast<Address>(block_start) <=
572  reinterpret_cast<Address>(prev_limit) &&
573  reinterpret_cast<Address>(prev_limit) <=
574  reinterpret_cast<Address>(block_limit)) {
575 #ifdef ENABLE_HANDLE_ZAPPING
576  internal::HandleScope::ZapRange(prev_limit, block_limit);
577 #endif
578  break;
579  }
580 
581  blocks_.pop_back();
582 #ifdef ENABLE_HANDLE_ZAPPING
583  internal::HandleScope::ZapRange(block_start, block_limit);
584 #endif
585  if (spare_ != nullptr) {
586  DeleteArray(spare_);
587  }
588  spare_ = block_start;
589  }
590  DCHECK((blocks_.empty() && prev_limit == nullptr) ||
591  (!blocks_.empty() && prev_limit != nullptr));
592 }
593 
594 // Interceptor functions called from generated inline caches to notify
595 // CPU profiler that external callbacks are invoked.
596 void InvokeAccessorGetterCallback(
597  v8::Local<v8::Name> property,
599  v8::AccessorNameGetterCallback getter);
600 
601 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
602  v8::FunctionCallback callback);
603 
604 class Testing {
605  public:
606  static v8::Testing::StressType stress_type() { return stress_type_; }
607  static void set_stress_type(v8::Testing::StressType stress_type) {
608  stress_type_ = stress_type;
609  }
610 
611  private:
612  static v8::Testing::StressType stress_type_;
613 };
614 
615 } // namespace internal
616 } // namespace v8
617 
618 #endif // V8_API_H_
Definition: libplatform.h:13
Definition: api.h:126
Definition: api.h:31