Coverage Report

Created: 2025-07-04 09:33

/src/node/deps/v8/include/v8-script.h
Line
Count
Source (jump to first uncovered line)
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 <tuple>
13
#include <vector>
14
15
#include "v8-callbacks.h"     // NOLINT(build/include_directory)
16
#include "v8-data.h"          // NOLINT(build/include_directory)
17
#include "v8-local-handle.h"  // NOLINT(build/include_directory)
18
#include "v8-maybe.h"         // NOLINT(build/include_directory)
19
#include "v8-memory-span.h"   // NOLINT(build/include_directory)
20
#include "v8-message.h"       // NOLINT(build/include_directory)
21
#include "v8config.h"         // NOLINT(build/include_directory)
22
23
namespace v8 {
24
25
class Function;
26
class Message;
27
class Object;
28
class PrimitiveArray;
29
class Script;
30
31
namespace internal {
32
class BackgroundDeserializeTask;
33
struct ScriptStreamingData;
34
}  // namespace internal
35
36
/**
37
 * A container type that holds relevant metadata for module loading.
38
 *
39
 * This is passed back to the embedder as part of
40
 * HostImportModuleDynamicallyCallback for module loading.
41
 */
42
class V8_EXPORT ScriptOrModule {
43
 public:
44
  /**
45
   * The name that was passed by the embedder as ResourceName to the
46
   * ScriptOrigin. This can be either a v8::String or v8::Undefined.
47
   */
48
  Local<Value> GetResourceName();
49
50
  /**
51
   * The options that were passed by the embedder as HostDefinedOptions to
52
   * the ScriptOrigin.
53
   */
54
  Local<Data> HostDefinedOptions();
55
};
56
57
/**
58
 * A compiled JavaScript script, not yet tied to a Context.
59
 */
60
class V8_EXPORT UnboundScript : public Data {
61
 public:
62
  /**
63
   * Binds the script to the currently entered context.
64
   */
65
  Local<Script> BindToCurrentContext();
66
67
  int GetId() const;
68
  Local<Value> GetScriptName();
69
70
  /**
71
   * Data read from magic sourceURL comments.
72
   */
73
  Local<Value> GetSourceURL();
74
  /**
75
   * Data read from magic sourceMappingURL comments.
76
   */
77
  Local<Value> GetSourceMappingURL();
78
79
  /**
80
   * Returns zero based line number of the code_pos location in the script.
81
   * -1 will be returned if no information available.
82
   */
83
  int GetLineNumber(int code_pos = 0);
84
85
  /**
86
   * Returns zero based column number of the code_pos location in the script.
87
   * -1 will be returned if no information available.
88
   */
89
  int GetColumnNumber(int code_pos = 0);
90
91
  static const int kNoScriptId = 0;
92
};
93
94
/**
95
 * A compiled JavaScript module, not yet tied to a Context.
96
 */
97
class V8_EXPORT UnboundModuleScript : public Data {
98
 public:
99
  /**
100
   * Data read from magic sourceURL comments.
101
   */
102
  Local<Value> GetSourceURL();
103
  /**
104
   * Data read from magic sourceMappingURL comments.
105
   */
106
  Local<Value> GetSourceMappingURL();
107
};
108
109
/**
110
 * A location in JavaScript source.
111
 */
112
class V8_EXPORT Location {
113
 public:
114
0
  int GetLineNumber() { return line_number_; }
115
0
  int GetColumnNumber() { return column_number_; }
116
117
  Location(int line_number, int column_number)
118
0
      : line_number_(line_number), column_number_(column_number) {}
119
120
 private:
121
  int line_number_;
122
  int column_number_;
123
};
124
125
class V8_EXPORT ModuleRequest : public Data {
126
 public:
127
  /**
128
   * Returns the module specifier for this ModuleRequest.
129
   */
130
  Local<String> GetSpecifier() const;
131
132
  /**
133
   * Returns the source code offset of this module request.
134
   * Use Module::SourceOffsetToLocation to convert this to line/column numbers.
135
   */
136
  int GetSourceOffset() const;
137
138
  /**
139
   * Contains the import assertions for this request in the form:
140
   * [key1, value1, source_offset1, key2, value2, source_offset2, ...].
141
   * The keys and values are of type v8::String, and the source offsets are of
142
   * type Int32. Use Module::SourceOffsetToLocation to convert the source
143
   * offsets to Locations with line/column numbers.
144
   *
145
   * All assertions present in the module request will be supplied in this
146
   * list, regardless of whether they are supported by the host. Per
147
   * https://tc39.es/proposal-import-attributes/#sec-hostgetsupportedimportattributes,
148
   * hosts are expected to throw for assertions that they do not support (as
149
   * opposed to, for example, ignoring them).
150
   */
151
  Local<FixedArray> GetImportAssertions() const;
152
153
  V8_INLINE static ModuleRequest* Cast(Data* data);
154
155
 private:
156
  static void CheckCast(Data* obj);
157
};
158
159
/**
160
 * A compiled JavaScript module.
161
 */
162
class V8_EXPORT Module : public Data {
163
 public:
164
  /**
165
   * The different states a module can be in.
166
   *
167
   * This corresponds to the states used in ECMAScript except that "evaluated"
168
   * is split into kEvaluated and kErrored, indicating success and failure,
169
   * respectively.
170
   */
171
  enum Status {
172
    kUninstantiated,
173
    kInstantiating,
174
    kInstantiated,
175
    kEvaluating,
176
    kEvaluated,
177
    kErrored
178
  };
179
180
  /**
181
   * Returns the module's current status.
182
   */
183
  Status GetStatus() const;
184
185
  /**
186
   * For a module in kErrored status, this returns the corresponding exception.
187
   */
188
  Local<Value> GetException() const;
189
190
  /**
191
   * Returns the ModuleRequests for this module.
192
   */
193
  Local<FixedArray> GetModuleRequests() const;
194
195
  /**
196
   * For the given source text offset in this module, returns the corresponding
197
   * Location with line and column numbers.
198
   */
199
  Location SourceOffsetToLocation(int offset) const;
200
201
  /**
202
   * Returns the identity hash for this object.
203
   */
204
  int GetIdentityHash() const;
205
206
  using ResolveModuleCallback = MaybeLocal<Module> (*)(
207
      Local<Context> context, Local<String> specifier,
208
      Local<FixedArray> import_assertions, Local<Module> referrer);
209
210
  /**
211
   * Instantiates the module and its dependencies.
212
   *
213
   * Returns an empty Maybe<bool> if an exception occurred during
214
   * instantiation. (In the case where the callback throws an exception, that
215
   * exception is propagated.)
216
   */
217
  V8_WARN_UNUSED_RESULT Maybe<bool> InstantiateModule(
218
      Local<Context> context, ResolveModuleCallback callback);
219
220
  /**
221
   * Evaluates the module and its dependencies.
222
   *
223
   * If status is kInstantiated, run the module's code and return a Promise
224
   * object. On success, set status to kEvaluated and resolve the Promise with
225
   * the completion value; on failure, set status to kErrored and reject the
226
   * Promise with the error.
227
   *
228
   * If IsGraphAsync() is false, the returned Promise is settled.
229
   */
230
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Evaluate(Local<Context> context);
231
232
  /**
233
   * Returns the namespace object of this module.
234
   *
235
   * The module's status must be at least kInstantiated.
236
   */
237
  Local<Value> GetModuleNamespace();
238
239
  /**
240
   * Returns the corresponding context-unbound module script.
241
   *
242
   * The module must be unevaluated, i.e. its status must not be kEvaluating,
243
   * kEvaluated or kErrored.
244
   */
245
  Local<UnboundModuleScript> GetUnboundModuleScript();
246
247
  /**
248
   * Returns the underlying script's id.
249
   *
250
   * The module must be a SourceTextModule and must not have a kErrored status.
251
   */
252
  int ScriptId() const;
253
254
  /**
255
   * Returns whether this module or any of its requested modules is async,
256
   * i.e. contains top-level await.
257
   *
258
   * The module's status must be at least kInstantiated.
259
   */
260
  bool IsGraphAsync() const;
261
262
  /**
263
   * Returns whether the module is a SourceTextModule.
264
   */
265
  bool IsSourceTextModule() const;
266
267
  /**
268
   * Returns whether the module is a SyntheticModule.
269
   */
270
  bool IsSyntheticModule() const;
271
272
  /*
273
   * Callback defined in the embedder.  This is responsible for setting
274
   * the module's exported values with calls to SetSyntheticModuleExport().
275
   * The callback must return a resolved Promise to indicate success (where no
276
   * exception was thrown) and return an empy MaybeLocal to indicate falure
277
   * (where an exception was thrown).
278
   */
279
  using SyntheticModuleEvaluationSteps =
280
      MaybeLocal<Value> (*)(Local<Context> context, Local<Module> module);
281
282
  /**
283
   * Creates a new SyntheticModule with the specified export names, where
284
   * evaluation_steps will be executed upon module evaluation.
285
   * export_names must not contain duplicates.
286
   * module_name is used solely for logging/debugging and doesn't affect module
287
   * behavior.
288
   */
289
  V8_DEPRECATED("Please use the version that takes a MemorySpan")
290
  static Local<Module> CreateSyntheticModule(
291
      Isolate* isolate, Local<String> module_name,
292
      const std::vector<Local<String>>& export_names,
293
      SyntheticModuleEvaluationSteps evaluation_steps);
294
  static Local<Module> CreateSyntheticModule(
295
      Isolate* isolate, Local<String> module_name,
296
      const MemorySpan<const Local<String>>& export_names,
297
      SyntheticModuleEvaluationSteps evaluation_steps);
298
299
  /**
300
   * Set this module's exported value for the name export_name to the specified
301
   * export_value. This method must be called only on Modules created via
302
   * CreateSyntheticModule.  An error will be thrown if export_name is not one
303
   * of the export_names that were passed in that CreateSyntheticModule call.
304
   * Returns Just(true) on success, Nothing<bool>() if an error was thrown.
305
   */
306
  V8_WARN_UNUSED_RESULT Maybe<bool> SetSyntheticModuleExport(
307
      Isolate* isolate, Local<String> export_name, Local<Value> export_value);
308
309
  /**
310
   * Search the modules requested directly or indirectly by the module for
311
   * any top-level await that has not yet resolved. If there is any, the
312
   * returned vector contains a tuple of the unresolved module and a message
313
   * with the pending top-level await.
314
   * An embedder may call this before exiting to improve error messages.
315
   */
316
  V8_DEPRECATED("Please use GetStalledTopLevelAwaitMessages")
317
  std::vector<std::tuple<Local<Module>, Local<Message>>>
318
  GetStalledTopLevelAwaitMessage(Isolate* isolate);
319
320
  /**
321
   * Search the modules requested directly or indirectly by the module for
322
   * any top-level await that has not yet resolved. If there is any, the
323
   * returned pair of vectors (of equal size) contain the unresolved module
324
   * and corresponding message with the pending top-level await.
325
   * An embedder may call this before exiting to improve error messages.
326
   */
327
  std::pair<LocalVector<Module>, LocalVector<Message>>
328
  GetStalledTopLevelAwaitMessages(Isolate* isolate);
329
330
  V8_INLINE static Module* Cast(Data* data);
331
332
 private:
333
  static void CheckCast(Data* obj);
334
};
335
336
/**
337
 * A compiled JavaScript script, tied to a Context which was active when the
338
 * script was compiled.
339
 */
340
class V8_EXPORT Script : public Data {
341
 public:
342
  /**
343
   * A shorthand for ScriptCompiler::Compile().
344
   */
345
  static V8_WARN_UNUSED_RESULT MaybeLocal<Script> Compile(
346
      Local<Context> context, Local<String> source,
347
      ScriptOrigin* origin = nullptr);
348
349
  /**
350
   * Runs the script returning the resulting value. It will be run in the
351
   * context in which it was created (ScriptCompiler::CompileBound or
352
   * UnboundScript::BindToCurrentContext()).
353
   */
354
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Run(Local<Context> context);
355
  V8_WARN_UNUSED_RESULT MaybeLocal<Value> Run(Local<Context> context,
356
                                              Local<Data> host_defined_options);
357
358
  /**
359
   * Returns the corresponding context-unbound script.
360
   */
361
  Local<UnboundScript> GetUnboundScript();
362
363
  /**
364
   * The name that was passed by the embedder as ResourceName to the
365
   * ScriptOrigin. This can be either a v8::String or v8::Undefined.
366
   */
367
  Local<Value> GetResourceName();
368
369
  /**
370
   * If the script was compiled, returns the positions of lazy functions which
371
   * were eventually compiled and executed.
372
   */
373
  std::vector<int> GetProducedCompileHints() const;
374
};
375
376
enum class ScriptType { kClassic, kModule };
377
378
/**
379
 * For compiling scripts.
380
 */
381
class V8_EXPORT ScriptCompiler {
382
 public:
383
  class ConsumeCodeCacheTask;
384
385
  /**
386
   * Compilation data that the embedder can cache and pass back to speed up
387
   * future compilations. The data is produced if the CompilerOptions passed to
388
   * the compilation functions in ScriptCompiler contains produce_data_to_cache
389
   * = true. The data to cache can then can be retrieved from
390
   * UnboundScript.
391
   */
392
  struct V8_EXPORT CachedData {
393
    enum BufferPolicy { BufferNotOwned, BufferOwned };
394
395
    CachedData()
396
        : data(nullptr),
397
          length(0),
398
          rejected(false),
399
0
          buffer_policy(BufferNotOwned) {}
400
401
    // If buffer_policy is BufferNotOwned, the caller keeps the ownership of
402
    // data and guarantees that it stays alive until the CachedData object is
403
    // destroyed. If the policy is BufferOwned, the given data will be deleted
404
    // (with delete[]) when the CachedData object is destroyed.
405
    CachedData(const uint8_t* data, int length,
406
               BufferPolicy buffer_policy = BufferNotOwned);
407
    ~CachedData();
408
409
    enum CompatibilityCheckResult {
410
      // Don't change order/existing values of this enum since it keys into the
411
      // `code_cache_reject_reason` histogram. Append-only!
412
      kSuccess = 0,
413
      kMagicNumberMismatch = 1,
414
      kVersionMismatch = 2,
415
      kSourceMismatch = 3,
416
      kFlagsMismatch = 5,
417
      kChecksumMismatch = 6,
418
      kInvalidHeader = 7,
419
      kLengthMismatch = 8,
420
      kReadOnlySnapshotChecksumMismatch = 9,
421
422
      // This should always point at the last real enum value.
423
      kLast = kReadOnlySnapshotChecksumMismatch
424
    };
425
426
    // Check if the CachedData can be loaded in the given isolate.
427
    CompatibilityCheckResult CompatibilityCheck(Isolate* isolate);
428
429
    // TODO(marja): Async compilation; add constructors which take a callback
430
    // which will be called when V8 no longer needs the data.
431
    const uint8_t* data;
432
    int length;
433
    bool rejected;
434
    BufferPolicy buffer_policy;
435
436
    // Prevent copying.
437
    CachedData(const CachedData&) = delete;
438
    CachedData& operator=(const CachedData&) = delete;
439
  };
440
441
  enum class InMemoryCacheResult {
442
    // V8 did not attempt to find this script in its in-memory cache.
443
    kNotAttempted,
444
445
    // V8 found a previously compiled copy of this script in its in-memory
446
    // cache. Any data generated by a streaming compilation or background
447
    // deserialization was abandoned.
448
    kHit,
449
450
    // V8 didn't have any previously compiled data for this script.
451
    kMiss,
452
453
    // V8 had some previously compiled data for an identical script, but the
454
    // data was incomplete.
455
    kPartial,
456
  };
457
458
  // Details about what happened during a compilation.
459
  struct CompilationDetails {
460
    InMemoryCacheResult in_memory_cache_result =
461
        InMemoryCacheResult::kNotAttempted;
462
463
    static constexpr int64_t kTimeNotMeasured = -1;
464
    int64_t foreground_time_in_microseconds = kTimeNotMeasured;
465
    int64_t background_time_in_microseconds = kTimeNotMeasured;
466
  };
467
468
  /**
469
   * Source code which can be then compiled to a UnboundScript or Script.
470
   */
471
  class Source {
472
   public:
473
    // Source takes ownership of both CachedData and CodeCacheConsumeTask.
474
    // The caller *must* ensure that the cached data is from a trusted source.
475
    V8_INLINE Source(Local<String> source_string, const ScriptOrigin& origin,
476
                     CachedData* cached_data = nullptr,
477
                     ConsumeCodeCacheTask* consume_cache_task = nullptr);
478
    // Source takes ownership of both CachedData and CodeCacheConsumeTask.
479
    V8_INLINE explicit Source(
480
        Local<String> source_string, CachedData* cached_data = nullptr,
481
        ConsumeCodeCacheTask* consume_cache_task = nullptr);
482
    V8_INLINE Source(Local<String> source_string, const ScriptOrigin& origin,
483
                     CompileHintCallback callback, void* callback_data);
484
12.8M
    V8_INLINE ~Source() = default;
485
486
    // Ownership of the CachedData or its buffers is *not* transferred to the
487
    // caller. The CachedData object is alive as long as the Source object is
488
    // alive.
489
    V8_INLINE const CachedData* GetCachedData() const;
490
491
    V8_INLINE const ScriptOriginOptions& GetResourceOptions() const;
492
493
    V8_INLINE const CompilationDetails& GetCompilationDetails() const;
494
495
   private:
496
    friend class ScriptCompiler;
497
498
    Local<String> source_string;
499
500
    // Origin information
501
    Local<Value> resource_name;
502
    int resource_line_offset = -1;
503
    int resource_column_offset = -1;
504
    ScriptOriginOptions resource_options;
505
    Local<Value> source_map_url;
506
    Local<Data> host_defined_options;
507
508
    // Cached data from previous compilation (if a kConsume*Cache flag is
509
    // set), or hold newly generated cache data (kProduce*Cache flags) are
510
    // set when calling a compile method.
511
    std::unique_ptr<CachedData> cached_data;
512
    std::unique_ptr<ConsumeCodeCacheTask> consume_cache_task;
513
514
    // For requesting compile hints from the embedder.
515
    CompileHintCallback compile_hint_callback = nullptr;
516
    void* compile_hint_callback_data = nullptr;
517
518
    // V8 writes this data and never reads it. It exists only to be informative
519
    // to the embedder.
520
    CompilationDetails compilation_details;
521
  };
522
523
  /**
524
   * For streaming incomplete script data to V8. The embedder should implement a
525
   * subclass of this class.
526
   */
527
  class V8_EXPORT ExternalSourceStream {
528
   public:
529
    virtual ~ExternalSourceStream() = default;
530
531
    /**
532
     * V8 calls this to request the next chunk of data from the embedder. This
533
     * function will be called on a background thread, so it's OK to block and
534
     * wait for the data, if the embedder doesn't have data yet. Returns the
535
     * length of the data returned. When the data ends, GetMoreData should
536
     * return 0. Caller takes ownership of the data.
537
     *
538
     * When streaming UTF-8 data, V8 handles multi-byte characters split between
539
     * two data chunks, but doesn't handle multi-byte characters split between
540
     * more than two data chunks. The embedder can avoid this problem by always
541
     * returning at least 2 bytes of data.
542
     *
543
     * When streaming UTF-16 data, V8 does not handle characters split between
544
     * two data chunks. The embedder has to make sure that chunks have an even
545
     * length.
546
     *
547
     * If the embedder wants to cancel the streaming, they should make the next
548
     * GetMoreData call return 0. V8 will interpret it as end of data (and most
549
     * probably, parsing will fail). The streaming task will return as soon as
550
     * V8 has parsed the data it received so far.
551
     */
552
    virtual size_t GetMoreData(const uint8_t** src) = 0;
553
  };
554
555
  /**
556
   * Source code which can be streamed into V8 in pieces. It will be parsed
557
   * while streaming and compiled after parsing has completed. StreamedSource
558
   * must be kept alive while the streaming task is run (see ScriptStreamingTask
559
   * below).
560
   */
561
  class V8_EXPORT StreamedSource {
562
   public:
563
    enum Encoding { ONE_BYTE, TWO_BYTE, UTF8, WINDOWS_1252 };
564
565
    StreamedSource(std::unique_ptr<ExternalSourceStream> source_stream,
566
                   Encoding encoding);
567
    ~StreamedSource();
568
569
0
    internal::ScriptStreamingData* impl() const { return impl_.get(); }
570
571
    // Prevent copying.
572
    StreamedSource(const StreamedSource&) = delete;
573
    StreamedSource& operator=(const StreamedSource&) = delete;
574
575
0
    CompilationDetails& compilation_details() { return compilation_details_; }
576
577
   private:
578
    std::unique_ptr<internal::ScriptStreamingData> impl_;
579
580
    // V8 writes this data and never reads it. It exists only to be informative
581
    // to the embedder.
582
    CompilationDetails compilation_details_;
583
  };
584
585
  /**
586
   * A streaming task which the embedder must run on a background thread to
587
   * stream scripts into V8. Returned by ScriptCompiler::StartStreaming.
588
   */
589
  class V8_EXPORT ScriptStreamingTask final {
590
   public:
591
    void Run();
592
593
   private:
594
    friend class ScriptCompiler;
595
596
    explicit ScriptStreamingTask(internal::ScriptStreamingData* data)
597
0
        : data_(data) {}
598
599
    internal::ScriptStreamingData* data_;
600
  };
601
602
  /**
603
   * A task which the embedder must run on a background thread to
604
   * consume a V8 code cache. Returned by
605
   * ScriptCompiler::StartConsumingCodeCache.
606
   */
607
  class V8_EXPORT ConsumeCodeCacheTask final {
608
   public:
609
    ~ConsumeCodeCacheTask();
610
611
    void Run();
612
613
    /**
614
     * Provides the source text string and origin information to the consumption
615
     * task. May be called before, during, or after Run(). This step checks
616
     * whether the script matches an existing script in the Isolate's
617
     * compilation cache. To check whether such a script was found, call
618
     * ShouldMergeWithExistingScript.
619
     *
620
     * The Isolate provided must be the same one used during
621
     * StartConsumingCodeCache and must be currently entered on the thread that
622
     * calls this function. The source text and origin provided in this step
623
     * must precisely match those used later in the ScriptCompiler::Source that
624
     * will contain this ConsumeCodeCacheTask.
625
     */
626
    void SourceTextAvailable(Isolate* isolate, Local<String> source_text,
627
                             const ScriptOrigin& origin);
628
629
    /**
630
     * Returns whether the embedder should call MergeWithExistingScript. This
631
     * function may be called from any thread, any number of times, but its
632
     * return value is only meaningful after SourceTextAvailable has completed.
633
     */
634
    bool ShouldMergeWithExistingScript() const;
635
636
    /**
637
     * Merges newly deserialized data into an existing script which was found
638
     * during SourceTextAvailable. May be called only after Run() has completed.
639
     * Can execute on any thread, like Run().
640
     */
641
    void MergeWithExistingScript();
642
643
   private:
644
    friend class ScriptCompiler;
645
646
    explicit ConsumeCodeCacheTask(
647
        std::unique_ptr<internal::BackgroundDeserializeTask> impl);
648
649
    std::unique_ptr<internal::BackgroundDeserializeTask> impl_;
650
  };
651
652
  enum CompileOptions {
653
    kNoCompileOptions = 0,
654
    kConsumeCodeCache,
655
    kEagerCompile,
656
    kProduceCompileHints,
657
    kConsumeCompileHints
658
  };
659
660
  /**
661
   * The reason for which we are not requesting or providing a code cache.
662
   */
663
  enum NoCacheReason {
664
    kNoCacheNoReason = 0,
665
    kNoCacheBecauseCachingDisabled,
666
    kNoCacheBecauseNoResource,
667
    kNoCacheBecauseInlineScript,
668
    kNoCacheBecauseModule,
669
    kNoCacheBecauseStreamingSource,
670
    kNoCacheBecauseInspector,
671
    kNoCacheBecauseScriptTooSmall,
672
    kNoCacheBecauseCacheTooCold,
673
    kNoCacheBecauseV8Extension,
674
    kNoCacheBecauseExtensionModule,
675
    kNoCacheBecausePacScript,
676
    kNoCacheBecauseInDocumentWrite,
677
    kNoCacheBecauseResourceWithNoCacheHandler,
678
    kNoCacheBecauseDeferredProduceCodeCache
679
  };
680
681
  /**
682
   * Compiles the specified script (context-independent).
683
   * Cached data as part of the source object can be optionally produced to be
684
   * consumed later to speed up compilation of identical source scripts.
685
   *
686
   * Note that when producing cached data, the source must point to NULL for
687
   * cached data. When consuming cached data, the cached data must have been
688
   * produced by the same version of V8, and the embedder needs to ensure the
689
   * cached data is the correct one for the given script.
690
   *
691
   * \param source Script source code.
692
   * \return Compiled script object (context independent; for running it must be
693
   *   bound to a context).
694
   */
695
  static V8_WARN_UNUSED_RESULT MaybeLocal<UnboundScript> CompileUnboundScript(
696
      Isolate* isolate, Source* source,
697
      CompileOptions options = kNoCompileOptions,
698
      NoCacheReason no_cache_reason = kNoCacheNoReason);
699
700
  /**
701
   * Compiles the specified script (bound to current context).
702
   *
703
   * \param source Script source code.
704
   * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
705
   *   using pre_data speeds compilation if it's done multiple times.
706
   *   Owned by caller, no references are kept when this function returns.
707
   * \return Compiled script object, bound to the context that was active
708
   *   when this function was called. When run it will always use this
709
   *   context.
710
   */
711
  static V8_WARN_UNUSED_RESULT MaybeLocal<Script> Compile(
712
      Local<Context> context, Source* source,
713
      CompileOptions options = kNoCompileOptions,
714
      NoCacheReason no_cache_reason = kNoCacheNoReason);
715
716
  /**
717
   * Returns a task which streams script data into V8, or NULL if the script
718
   * cannot be streamed. The user is responsible for running the task on a
719
   * background thread and deleting it. When ran, the task starts parsing the
720
   * script, and it will request data from the StreamedSource as needed. When
721
   * ScriptStreamingTask::Run exits, all data has been streamed and the script
722
   * can be compiled (see Compile below).
723
   *
724
   * This API allows to start the streaming with as little data as possible, and
725
   * the remaining data (for example, the ScriptOrigin) is passed to Compile.
726
   */
727
  static ScriptStreamingTask* StartStreaming(
728
      Isolate* isolate, StreamedSource* source,
729
      ScriptType type = ScriptType::kClassic,
730
      CompileOptions options = kNoCompileOptions,
731
      CompileHintCallback compile_hint_callback = nullptr,
732
      void* compile_hint_callback_data = nullptr);
733
734
  static ConsumeCodeCacheTask* StartConsumingCodeCache(
735
      Isolate* isolate, std::unique_ptr<CachedData> source);
736
737
  /**
738
   * Compiles a streamed script (bound to current context).
739
   *
740
   * This can only be called after the streaming has finished
741
   * (ScriptStreamingTask has been run). V8 doesn't construct the source string
742
   * during streaming, so the embedder needs to pass the full source here.
743
   */
744
  static V8_WARN_UNUSED_RESULT MaybeLocal<Script> Compile(
745
      Local<Context> context, StreamedSource* source,
746
      Local<String> full_source_string, const ScriptOrigin& origin);
747
748
  /**
749
   * Return a version tag for CachedData for the current V8 version & flags.
750
   *
751
   * This value is meant only for determining whether a previously generated
752
   * CachedData instance is still valid; the tag has no other meaing.
753
   *
754
   * Background: The data carried by CachedData may depend on the exact
755
   *   V8 version number or current compiler flags. This means that when
756
   *   persisting CachedData, the embedder must take care to not pass in
757
   *   data from another V8 version, or the same version with different
758
   *   features enabled.
759
   *
760
   *   The easiest way to do so is to clear the embedder's cache on any
761
   *   such change.
762
   *
763
   *   Alternatively, this tag can be stored alongside the cached data and
764
   *   compared when it is being used.
765
   */
766
  static uint32_t CachedDataVersionTag();
767
768
  /**
769
   * Compile an ES module, returning a Module that encapsulates
770
   * the compiled code.
771
   *
772
   * Corresponds to the ParseModule abstract operation in the
773
   * ECMAScript specification.
774
   */
775
  static V8_WARN_UNUSED_RESULT MaybeLocal<Module> CompileModule(
776
      Isolate* isolate, Source* source,
777
      CompileOptions options = kNoCompileOptions,
778
      NoCacheReason no_cache_reason = kNoCacheNoReason);
779
780
  /**
781
   * Compiles a streamed module script.
782
   *
783
   * This can only be called after the streaming has finished
784
   * (ScriptStreamingTask has been run). V8 doesn't construct the source string
785
   * during streaming, so the embedder needs to pass the full source here.
786
   */
787
  static V8_WARN_UNUSED_RESULT MaybeLocal<Module> CompileModule(
788
      Local<Context> context, StreamedSource* v8_source,
789
      Local<String> full_source_string, const ScriptOrigin& origin);
790
791
  /**
792
   * Compile a function for a given context. This is equivalent to running
793
   *
794
   * with (obj) {
795
   *   return function(args) { ... }
796
   * }
797
   *
798
   * It is possible to specify multiple context extensions (obj in the above
799
   * example).
800
   */
801
  V8_DEPRECATED("Use CompileFunction")
802
  static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunctionInContext(
803
      Local<Context> context, Source* source, size_t arguments_count,
804
      Local<String> arguments[], size_t context_extension_count,
805
      Local<Object> context_extensions[],
806
      CompileOptions options = kNoCompileOptions,
807
      NoCacheReason no_cache_reason = kNoCacheNoReason,
808
      Local<ScriptOrModule>* script_or_module_out = nullptr);
809
810
  static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunction(
811
      Local<Context> context, Source* source, size_t arguments_count = 0,
812
      Local<String> arguments[] = nullptr, size_t context_extension_count = 0,
813
      Local<Object> context_extensions[] = nullptr,
814
      CompileOptions options = kNoCompileOptions,
815
      NoCacheReason no_cache_reason = kNoCacheNoReason);
816
817
  /**
818
   * Creates and returns code cache for the specified unbound_script.
819
   * This will return nullptr if the script cannot be serialized. The
820
   * CachedData returned by this function should be owned by the caller.
821
   */
822
  static CachedData* CreateCodeCache(Local<UnboundScript> unbound_script);
823
824
  /**
825
   * Creates and returns code cache for the specified unbound_module_script.
826
   * This will return nullptr if the script cannot be serialized. The
827
   * CachedData returned by this function should be owned by the caller.
828
   */
829
  static CachedData* CreateCodeCache(
830
      Local<UnboundModuleScript> unbound_module_script);
831
832
  /**
833
   * Creates and returns code cache for the specified function that was
834
   * previously produced by CompileFunction.
835
   * This will return nullptr if the script cannot be serialized. The
836
   * CachedData returned by this function should be owned by the caller.
837
   */
838
  static CachedData* CreateCodeCacheForFunction(Local<Function> function);
839
840
 private:
841
  static V8_WARN_UNUSED_RESULT MaybeLocal<UnboundScript> CompileUnboundInternal(
842
      Isolate* isolate, Source* source, CompileOptions options,
843
      NoCacheReason no_cache_reason);
844
845
  static V8_WARN_UNUSED_RESULT MaybeLocal<Function> CompileFunctionInternal(
846
      Local<Context> context, Source* source, size_t arguments_count,
847
      Local<String> arguments[], size_t context_extension_count,
848
      Local<Object> context_extensions[], CompileOptions options,
849
      NoCacheReason no_cache_reason,
850
      Local<ScriptOrModule>* script_or_module_out);
851
};
852
853
ScriptCompiler::Source::Source(Local<String> string, const ScriptOrigin& origin,
854
                               CachedData* data,
855
                               ConsumeCodeCacheTask* consume_cache_task)
856
12.8M
    : source_string(string),
857
12.8M
      resource_name(origin.ResourceName()),
858
12.8M
      resource_line_offset(origin.LineOffset()),
859
12.8M
      resource_column_offset(origin.ColumnOffset()),
860
12.8M
      resource_options(origin.Options()),
861
12.8M
      source_map_url(origin.SourceMapUrl()),
862
12.8M
      host_defined_options(origin.GetHostDefinedOptions()),
863
12.8M
      cached_data(data),
864
12.8M
      consume_cache_task(consume_cache_task) {}
865
866
ScriptCompiler::Source::Source(Local<String> string, CachedData* data,
867
                               ConsumeCodeCacheTask* consume_cache_task)
868
    : source_string(string),
869
      cached_data(data),
870
      consume_cache_task(consume_cache_task) {}
871
872
ScriptCompiler::Source::Source(Local<String> string, const ScriptOrigin& origin,
873
                               CompileHintCallback callback,
874
                               void* callback_data)
875
    : source_string(string),
876
      resource_name(origin.ResourceName()),
877
      resource_line_offset(origin.LineOffset()),
878
      resource_column_offset(origin.ColumnOffset()),
879
      resource_options(origin.Options()),
880
      source_map_url(origin.SourceMapUrl()),
881
      host_defined_options(origin.GetHostDefinedOptions()),
882
      compile_hint_callback(callback),
883
      compile_hint_callback_data(callback_data) {}
884
885
const ScriptCompiler::CachedData* ScriptCompiler::Source::GetCachedData()
886
77.3k
    const {
887
77.3k
  return cached_data.get();
888
77.3k
}
889
890
0
const ScriptOriginOptions& ScriptCompiler::Source::GetResourceOptions() const {
891
0
  return resource_options;
892
0
}
893
894
const ScriptCompiler::CompilationDetails&
895
0
ScriptCompiler::Source::GetCompilationDetails() const {
896
0
  return compilation_details;
897
0
}
898
899
0
ModuleRequest* ModuleRequest::Cast(Data* data) {
900
0
#ifdef V8_ENABLE_CHECKS
901
0
  CheckCast(data);
902
0
#endif
903
0
  return reinterpret_cast<ModuleRequest*>(data);
904
0
}
905
906
0
Module* Module::Cast(Data* data) {
907
0
#ifdef V8_ENABLE_CHECKS
908
0
  CheckCast(data);
909
0
#endif
910
0
  return reinterpret_cast<Module*>(data);
911
0
}
912
913
}  // namespace v8
914
915
#endif  // INCLUDE_V8_SCRIPT_H_