Coverage Report

Created: 2025-10-31 09:06

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