v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-script.h
Go to the documentation of this file.
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 
5 #ifndef INCLUDE_V8_SCRIPT_H_
6 #define INCLUDE_V8_SCRIPT_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <memory>
12 #include <vector>
13 
14 #include "v8-data.h" // NOLINT(build/include_directory)
15 #include "v8-local-handle.h" // NOLINT(build/include_directory)
16 #include "v8-maybe.h" // NOLINT(build/include_directory)
17 #include "v8-message.h" // NOLINT(build/include_directory)
18 #include "v8config.h" // NOLINT(build/include_directory)
19 
20 namespace v8 {
21 
22 class Function;
23 class Object;
24 class PrimitiveArray;
25 class Script;
26 
27 namespace internal {
28 class BackgroundDeserializeTask;
29 struct ScriptStreamingData;
30 } // namespace internal
31 
32 /**
33  * A container type that holds relevant metadata for module loading.
34  *
35  * This is passed back to the embedder as part of
36  * HostImportModuleDynamicallyCallback for module loading.
37  */
39  public:
40  /**
41  * The name that was passed by the embedder as ResourceName to the
42  * ScriptOrigin. This can be either a v8::String or v8::Undefined.
43  */
45 
46  /**
47  * The options that were passed by the embedder as HostDefinedOptions to
48  * the ScriptOrigin.
49  */
50  V8_DEPRECATED("Use HostDefinedOptions")
53 };
54 
55 /**
56  * A compiled JavaScript script, not yet tied to a Context.
57  */
59  public:
60  /**
61  * Binds the script to the currently entered context.
62  */
64 
65  int GetId() const;
67 
68  /**
69  * Data read from magic sourceURL comments.
70  */
72  /**
73  * Data read from magic sourceMappingURL comments.
74  */
76 
77  /**
78  * Returns zero based line number of the code_pos location in the script.
79  * -1 will be returned if no information available.
80  */
81  int GetLineNumber(int code_pos);
82 
83  static const int kNoScriptId = 0;
84 };
85 
86 /**
87  * A compiled JavaScript module, not yet tied to a Context.
88  */
90  // Only used as a container for code caching.
91 };
92 
93 /**
94  * A location in JavaScript source.
95  */
97  public:
98  int GetLineNumber() { return line_number_; }
99  int GetColumnNumber() { return column_number_; }
100 
101  Location(int line_number, int column_number)
102  : line_number_(line_number), column_number_(column_number) {}
103 
104  private:
105  int line_number_;
106  int column_number_;
107 };
108 
109 class V8_EXPORT ModuleRequest : public Data {
110  public:
111  /**
112  * Returns the module specifier for this ModuleRequest.
113  */
115 
116  /**
117  * Returns the source code offset of this module request.
118  * Use Module::SourceOffsetToLocation to convert this to line/column numbers.
119  */
120  int GetSourceOffset() const;
121 
122  /**
123  * Contains the import assertions for this request in the form:
124  * [key1, value1, source_offset1, key2, value2, source_offset2, ...].
125  * The keys and values are of type v8::String, and the source offsets are of
126  * type Int32. Use Module::SourceOffsetToLocation to convert the source
127  * offsets to Locations with line/column numbers.
128  *
129  * All assertions present in the module request will be supplied in this
130  * list, regardless of whether they are supported by the host. Per
131  * https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions,
132  * hosts are expected to ignore assertions that they do not support (as
133  * opposed to, for example, triggering an error if an unsupported assertion is
134  * present).
135  */
137 
138  V8_INLINE static ModuleRequest* Cast(Data* data);
139 
140  private:
141  static void CheckCast(Data* obj);
142 };
143 
144 /**
145  * A compiled JavaScript module.
146  */
147 class V8_EXPORT Module : public Data {
148  public:
149  /**
150  * The different states a module can be in.
151  *
152  * This corresponds to the states used in ECMAScript except that "evaluated"
153  * is split into kEvaluated and kErrored, indicating success and failure,
154  * respectively.
155  */
156  enum Status {
162  kErrored
163  };
164 
165  /**
166  * Returns the module's current status.
167  */
168  Status GetStatus() const;
169 
170  /**
171  * For a module in kErrored status, this returns the corresponding exception.
172  */
174 
175  /**
176  * Returns the ModuleRequests for this module.
177  */
179 
180  /**
181  * For the given source text offset in this module, returns the corresponding
182  * Location with line and column numbers.
183  */
184  Location SourceOffsetToLocation(int offset) const;
185 
186  /**
187  * Returns the identity hash for this object.
188  */
189  int GetIdentityHash() const;
190 
191  using ResolveModuleCallback = MaybeLocal<Module> (*)(
192  Local<Context> context, Local<String> specifier,
193  Local<FixedArray> import_assertions, Local<Module> referrer);
194 
195  /**
196  * Instantiates the module and its dependencies.
197  *
198  * Returns an empty Maybe<bool> if an exception occurred during
199  * instantiation. (In the case where the callback throws an exception, that
200  * exception is propagated.)
201  */
203  Local<Context> context, ResolveModuleCallback callback);
204 
205  /**
206  * Evaluates the module and its dependencies.
207  *
208  * If status is kInstantiated, run the module's code and return a Promise
209  * object. On success, set status to kEvaluated and resolve the Promise with
210  * the completion value; on failure, set status to kErrored and reject the
211  * Promise with the error.
212  *
213  * If IsGraphAsync() is false, the returned Promise is settled.
214  */
216 
217  /**
218  * Returns the namespace object of this module.
219  *
220  * The module's status must be at least kInstantiated.
221  */
223 
224  /**
225  * Returns the corresponding context-unbound module script.
226  *
227  * The module must be unevaluated, i.e. its status must not be kEvaluating,
228  * kEvaluated or kErrored.
229  */
231 
232  /**
233  * Returns the underlying script's id.
234  *
235  * The module must be a SourceTextModule and must not have a kErrored status.
236  */
237  int ScriptId() const;
238 
239  /**
240  * Returns whether this module or any of its requested modules is async,
241  * i.e. contains top-level await.
242  *
243  * The module's status must be at least kInstantiated.
244  */
245  bool IsGraphAsync() const;
246 
247  /**
248  * Returns whether the module is a SourceTextModule.
249  */
250  bool IsSourceTextModule() const;
251 
252  /**
253  * Returns whether the module is a SyntheticModule.
254  */
255  bool IsSyntheticModule() const;
256 
257  /*
258  * Callback defined in the embedder. This is responsible for setting
259  * the module's exported values with calls to SetSyntheticModuleExport().
260  * The callback must return a resolved Promise to indicate success (where no
261  * exception was thrown) and return an empy MaybeLocal to indicate falure
262  * (where an exception was thrown).
263  */
264  using SyntheticModuleEvaluationSteps =
265  MaybeLocal<Value> (*)(Local<Context> context, Local<Module> module);
266 
267  /**
268  * Creates a new SyntheticModule with the specified export names, where
269  * evaluation_steps will be executed upon module evaluation.
270  * export_names must not contain duplicates.
271  * module_name is used solely for logging/debugging and doesn't affect module
272  * behavior.
273  */
275  Isolate* isolate, Local<String> module_name,
276  const std::vector<Local<String>>& export_names,
277  SyntheticModuleEvaluationSteps evaluation_steps);
278 
279  /**
280  * Set this module's exported value for the name export_name to the specified
281  * export_value. This method must be called only on Modules created via
282  * CreateSyntheticModule. An error will be thrown if export_name is not one
283  * of the export_names that were passed in that CreateSyntheticModule call.
284  * Returns Just(true) on success, Nothing<bool>() if an error was thrown.
285  */
287  Isolate* isolate, Local<String> export_name, Local<Value> export_value);
288 
289  V8_INLINE static Module* Cast(Data* data);
290 
291  private:
292  static void CheckCast(Data* obj);
293 };
294 
295 /**
296  * A compiled JavaScript script, tied to a Context which was active when the
297  * script was compiled.
298  */
300  public:
301  /**
302  * A shorthand for ScriptCompiler::Compile().
303  */
305  Local<Context> context, Local<String> source,
306  ScriptOrigin* origin = nullptr);
307 
308  /**
309  * Runs the script returning the resulting value. It will be run in the
310  * context in which it was created (ScriptCompiler::CompileBound or
311  * UnboundScript::BindToCurrentContext()).
312  */
315  Local<Data> host_defined_options);
316 
317  /**
318  * Returns the corresponding context-unbound script.
319  */
321 
322  /**
323  * The name that was passed by the embedder as ResourceName to the
324  * ScriptOrigin. This can be either a v8::String or v8::Undefined.
325  */
327 };
328 
329 enum class ScriptType { kClassic, kModule };
330 
331 /**
332  * For compiling scripts.
333  */
335  public:
336  class ConsumeCodeCacheTask;
337 
338  /**
339  * Compilation data that the embedder can cache and pass back to speed up
340  * future compilations. The data is produced if the CompilerOptions passed to
341  * the compilation functions in ScriptCompiler contains produce_data_to_cache
342  * = true. The data to cache can then can be retrieved from
343  * UnboundScript.
344  */
347 
349  : data(nullptr),
350  length(0),
351  rejected(false),
353 
354  // If buffer_policy is BufferNotOwned, the caller keeps the ownership of
355  // data and guarantees that it stays alive until the CachedData object is
356  // destroyed. If the policy is BufferOwned, the given data will be deleted
357  // (with delete[]) when the CachedData object is destroyed.
358  CachedData(const uint8_t* data, int length,
359  BufferPolicy buffer_policy = BufferNotOwned);
361  // TODO(marja): Async compilation; add constructors which take a callback
362  // which will be called when V8 no longer needs the data.
363  const uint8_t* data;
364  int length;
365  bool rejected;
367 
368  // Prevent copying.
369  CachedData(const CachedData&) = delete;
370  CachedData& operator=(const CachedData&) = delete;
371  };
372 
373  /**
374  * Source code which can be then compiled to a UnboundScript or Script.
375  */
376  class Source {
377  public:
378  // Source takes ownership of both CachedData and CodeCacheConsumeTask.
379  // The caller *must* ensure that the cached data is from a trusted source.
380  V8_INLINE Source(Local<String> source_string, const ScriptOrigin& origin,
381  CachedData* cached_data = nullptr,
382  ConsumeCodeCacheTask* consume_cache_task = nullptr);
383  // Source takes ownership of both CachedData and CodeCacheConsumeTask.
384  V8_INLINE explicit Source(
385  Local<String> source_string, CachedData* cached_data = nullptr,
386  ConsumeCodeCacheTask* consume_cache_task = nullptr);
387  V8_INLINE ~Source() = default;
388 
389  // Ownership of the CachedData or its buffers is *not* transferred to the
390  // caller. The CachedData object is alive as long as the Source object is
391  // alive.
392  V8_INLINE const CachedData* GetCachedData() const;
393 
395 
396  private:
397  friend class ScriptCompiler;
398 
399  Local<String> source_string;
400 
401  // Origin information
402  Local<Value> resource_name;
403  int resource_line_offset;
404  int resource_column_offset;
405  ScriptOriginOptions resource_options;
406  Local<Value> source_map_url;
407  Local<Data> host_defined_options;
408 
409  // Cached data from previous compilation (if a kConsume*Cache flag is
410  // set), or hold newly generated cache data (kProduce*Cache flags) are
411  // set when calling a compile method.
412  std::unique_ptr<CachedData> cached_data;
413  std::unique_ptr<ConsumeCodeCacheTask> consume_cache_task;
414  };
415 
416  /**
417  * For streaming incomplete script data to V8. The embedder should implement a
418  * subclass of this class.
419  */
421  public:
422  virtual ~ExternalSourceStream() = default;
423 
424  /**
425  * V8 calls this to request the next chunk of data from the embedder. This
426  * function will be called on a background thread, so it's OK to block and
427  * wait for the data, if the embedder doesn't have data yet. Returns the
428  * length of the data returned. When the data ends, GetMoreData should
429  * return 0. Caller takes ownership of the data.
430  *
431  * When streaming UTF-8 data, V8 handles multi-byte characters split between
432  * two data chunks, but doesn't handle multi-byte characters split between
433  * more than two data chunks. The embedder can avoid this problem by always
434  * returning at least 2 bytes of data.
435  *
436  * When streaming UTF-16 data, V8 does not handle characters split between
437  * two data chunks. The embedder has to make sure that chunks have an even
438  * length.
439  *
440  * If the embedder wants to cancel the streaming, they should make the next
441  * GetMoreData call return 0. V8 will interpret it as end of data (and most
442  * probably, parsing will fail). The streaming task will return as soon as
443  * V8 has parsed the data it received so far.
444  */
445  virtual size_t GetMoreData(const uint8_t** src) = 0;
446  };
447 
448  /**
449  * Source code which can be streamed into V8 in pieces. It will be parsed
450  * while streaming and compiled after parsing has completed. StreamedSource
451  * must be kept alive while the streaming task is run (see ScriptStreamingTask
452  * below).
453  */
455  public:
457 
458  StreamedSource(std::unique_ptr<ExternalSourceStream> source_stream,
459  Encoding encoding);
461 
462  internal::ScriptStreamingData* impl() const { return impl_.get(); }
463 
464  // Prevent copying.
465  StreamedSource(const StreamedSource&) = delete;
467 
468  private:
469  std::unique_ptr<internal::ScriptStreamingData> impl_;
470  };
471 
472  /**
473  * A streaming task which the embedder must run on a background thread to
474  * stream scripts into V8. Returned by ScriptCompiler::StartStreaming.
475  */
476  class V8_EXPORT ScriptStreamingTask final {
477  public:
478  void Run();
479 
480  private:
481  friend class ScriptCompiler;
482 
483  explicit ScriptStreamingTask(internal::ScriptStreamingData* data)
484  : data_(data) {}
485 
486  internal::ScriptStreamingData* data_;
487  };
488 
489  /**
490  * A task which the embedder must run on a background thread to
491  * consume a V8 code cache. Returned by
492  * ScriptCompiler::StarConsumingCodeCache.
493  */
494  class V8_EXPORT ConsumeCodeCacheTask final {
495  public:
497 
498  void Run();
499 
500  private:
501  friend class ScriptCompiler;
502 
503  explicit ConsumeCodeCacheTask(
504  std::unique_ptr<internal::BackgroundDeserializeTask> impl);
505 
506  std::unique_ptr<internal::BackgroundDeserializeTask> impl_;
507  };
508 
513  };
514 
515  /**
516  * The reason for which we are not requesting or providing a code cache.
517  */
534  };
535 
536  /**
537  * Compiles the specified script (context-independent).
538  * Cached data as part of the source object can be optionally produced to be
539  * consumed later to speed up compilation of identical source scripts.
540  *
541  * Note that when producing cached data, the source must point to NULL for
542  * cached data. When consuming cached data, the cached data must have been
543  * produced by the same version of V8, and the embedder needs to ensure the
544  * cached data is the correct one for the given script.
545  *
546  * \param source Script source code.
547  * \return Compiled script object (context independent; for running it must be
548  * bound to a context).
549  */
551  Isolate* isolate, Source* source,
553  NoCacheReason no_cache_reason = kNoCacheNoReason);
554 
555  /**
556  * Compiles the specified script (bound to current context).
557  *
558  * \param source Script source code.
559  * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
560  * using pre_data speeds compilation if it's done multiple times.
561  * Owned by caller, no references are kept when this function returns.
562  * \return Compiled script object, bound to the context that was active
563  * when this function was called. When run it will always use this
564  * context.
565  */
567  Local<Context> context, Source* source,
569  NoCacheReason no_cache_reason = kNoCacheNoReason);
570 
571  /**
572  * Returns a task which streams script data into V8, or NULL if the script
573  * cannot be streamed. The user is responsible for running the task on a
574  * background thread and deleting it. When ran, the task starts parsing the
575  * script, and it will request data from the StreamedSource as needed. When
576  * ScriptStreamingTask::Run exits, all data has been streamed and the script
577  * can be compiled (see Compile below).
578  *
579  * This API allows to start the streaming with as little data as possible, and
580  * the remaining data (for example, the ScriptOrigin) is passed to Compile.
581  */
582  static ScriptStreamingTask* StartStreaming(
583  Isolate* isolate, StreamedSource* source,
585 
586  static ConsumeCodeCacheTask* StartConsumingCodeCache(
587  Isolate* isolate, std::unique_ptr<CachedData> source);
588 
589  /**
590  * Compiles a streamed script (bound to current context).
591  *
592  * This can only be called after the streaming has finished
593  * (ScriptStreamingTask has been run). V8 doesn't construct the source string
594  * during streaming, so the embedder needs to pass the full source here.
595  */
597  Local<Context> context, StreamedSource* source,
598  Local<String> full_source_string, const ScriptOrigin& origin);
599 
600  /**
601  * Return a version tag for CachedData for the current V8 version & flags.
602  *
603  * This value is meant only for determining whether a previously generated
604  * CachedData instance is still valid; the tag has no other meaing.
605  *
606  * Background: The data carried by CachedData may depend on the exact
607  * V8 version number or current compiler flags. This means that when
608  * persisting CachedData, the embedder must take care to not pass in
609  * data from another V8 version, or the same version with different
610  * features enabled.
611  *
612  * The easiest way to do so is to clear the embedder's cache on any
613  * such change.
614  *
615  * Alternatively, this tag can be stored alongside the cached data and
616  * compared when it is being used.
617  */
618  static uint32_t CachedDataVersionTag();
619 
620  /**
621  * Compile an ES module, returning a Module that encapsulates
622  * the compiled code.
623  *
624  * Corresponds to the ParseModule abstract operation in the
625  * ECMAScript specification.
626  */
628  Isolate* isolate, Source* source,
630  NoCacheReason no_cache_reason = kNoCacheNoReason);
631 
632  /**
633  * Compiles a streamed module script.
634  *
635  * This can only be called after the streaming has finished
636  * (ScriptStreamingTask has been run). V8 doesn't construct the source string
637  * during streaming, so the embedder needs to pass the full source here.
638  */
640  Local<Context> context, StreamedSource* v8_source,
641  Local<String> full_source_string, const ScriptOrigin& origin);
642 
643  /**
644  * Compile a function for a given context. This is equivalent to running
645  *
646  * with (obj) {
647  * return function(args) { ... }
648  * }
649  *
650  * It is possible to specify multiple context extensions (obj in the above
651  * example).
652  */
653  V8_DEPRECATED("Use CompileFunction")
655  Local<Context> context, Source* source, size_t arguments_count,
656  Local<String> arguments[], size_t context_extension_count,
657  Local<Object> context_extensions[],
659  NoCacheReason no_cache_reason = kNoCacheNoReason,
660  Local<ScriptOrModule>* script_or_module_out = nullptr);
662  Local<Context> context, Source* source, size_t arguments_count = 0,
663  Local<String> arguments[] = nullptr, size_t context_extension_count = 0,
664  Local<Object> context_extensions[] = nullptr,
666  NoCacheReason no_cache_reason = kNoCacheNoReason);
667 
668  /**
669  * Creates and returns code cache for the specified unbound_script.
670  * This will return nullptr if the script cannot be serialized. The
671  * CachedData returned by this function should be owned by the caller.
672  */
673  static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script);
674 
675  /**
676  * Creates and returns code cache for the specified unbound_module_script.
677  * This will return nullptr if the script cannot be serialized. The
678  * CachedData returned by this function should be owned by the caller.
679  */
681  Local<UnboundModuleScript> unbound_module_script);
682 
683  /**
684  * Creates and returns code cache for the specified function that was
685  * previously produced by CompileFunction.
686  * This will return nullptr if the script cannot be serialized. The
687  * CachedData returned by this function should be owned by the caller.
688  */
690 
691  private:
692  static V8_WARN_UNUSED_RESULT MaybeLocal<UnboundScript> CompileUnboundInternal(
693  Isolate* isolate, Source* source, CompileOptions options,
694  NoCacheReason no_cache_reason);
695 
696  static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunctionInternal(
697  Local<Context> context, Source* source, size_t arguments_count,
698  Local<String> arguments[], size_t context_extension_count,
699  Local<Object> context_extensions[], CompileOptions options,
700  NoCacheReason no_cache_reason,
701  Local<ScriptOrModule>* script_or_module_out);
702 };
703 
705  CachedData* data,
706  ConsumeCodeCacheTask* consume_cache_task)
707  : source_string(string),
708  resource_name(origin.ResourceName()),
709  resource_line_offset(origin.LineOffset()),
710  resource_column_offset(origin.ColumnOffset()),
711  resource_options(origin.Options()),
712  source_map_url(origin.SourceMapUrl()),
713  host_defined_options(origin.GetHostDefinedOptions()),
714  cached_data(data),
715  consume_cache_task(consume_cache_task) {}
716 
718  ConsumeCodeCacheTask* consume_cache_task)
719  : source_string(string),
720  cached_data(data),
721  consume_cache_task(consume_cache_task) {}
722 
724  const {
725  return cached_data.get();
726 }
727 
729  return resource_options;
730 }
731 
733 #ifdef V8_ENABLE_CHECKS
734  CheckCast(data);
735 #endif
736  return reinterpret_cast<ModuleRequest*>(data);
737 }
738 
739 Module* Module::Cast(Data* data) {
740 #ifdef V8_ENABLE_CHECKS
741  CheckCast(data);
742 #endif
743  return reinterpret_cast<Module*>(data);
744 }
745 
746 } // namespace v8
747 
748 #endif // INCLUDE_V8_SCRIPT_H_