/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_ |