1 // Copyright 2017 The Chromium 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 THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
6 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
7 
8 #include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
9 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
10 #include "third_party/blink/renderer/core/core_export.h"
11 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
12 #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
13 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
14 #include "third_party/blink/renderer/platform/wtf/text/text_position.h"
15 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
16 #include "third_party/blink/renderer/platform/wtf/vector.h"
17 #include "v8/include/v8.h"
18 
19 namespace blink {
20 
21 class ExceptionState;
22 class KURL;
23 class ScriptFetchOptions;
24 class ScriptState;
25 class ScriptValue;
26 class ScriptPromise;
27 
28 // ModuleEvaluationResult encapsulates the result of a module evaluation.
29 // - Without top-level-await
30 //   - succeed and not return a value, or
31 //     (IsSuccess() == true), no return value is available.
32 //   - throw any object.
33 //     (IsException() == true && GetException()) returns the thrown exception
34 // - With top-level-await a module can either
35 //   - return a promise, or
36 //     (IsSuccess() == true && GetPromise()) returns a valid ScriptPromise())
37 //   - throw any object.
38 //     (IsException() == true && GetException()) returns the thrown exception
39 class CORE_EXPORT ModuleEvaluationResult final {
40   STACK_ALLOCATED();
41 
42  public:
43   ModuleEvaluationResult() = delete;
44   static ModuleEvaluationResult Empty();
45   static ModuleEvaluationResult FromResult(v8::Local<v8::Value> promise);
46   static ModuleEvaluationResult FromException(v8::Local<v8::Value> exception);
47 
48   ModuleEvaluationResult(const ModuleEvaluationResult& value) = default;
49   ModuleEvaluationResult& operator=(const ModuleEvaluationResult& value) =
50       default;
51   ~ModuleEvaluationResult() = default;
52 
53   ModuleEvaluationResult& Escape(ScriptState::EscapableScope* scope);
54 
IsSuccess()55   bool IsSuccess() const { return is_success_; }
IsException()56   bool IsException() const { return !is_success_; }
57 
58   v8::Local<v8::Value> GetException() const;
59   ScriptPromise GetPromise(ScriptState* script_state) const;
60 
61  private:
ModuleEvaluationResult(bool is_success,v8::Local<v8::Value> value)62   ModuleEvaluationResult(bool is_success, v8::Local<v8::Value> value)
63       : is_success_(is_success), value_(value) {}
64 
65   bool is_success_;
66   v8::Local<v8::Value> value_;
67 };
68 
69 // ModuleRecordProduceCacheData is a parameter object for
70 // ModuleRecord::ProduceCache().
71 class CORE_EXPORT ModuleRecordProduceCacheData final
72     : public GarbageCollected<ModuleRecordProduceCacheData> {
73  public:
74   ModuleRecordProduceCacheData(v8::Isolate*,
75                                SingleCachedMetadataHandler*,
76                                V8CodeCache::ProduceCacheOptions,
77                                v8::Local<v8::Module>);
78 
79   void Trace(Visitor*);
80 
CacheHandler()81   SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; }
GetProduceCacheOptions()82   V8CodeCache::ProduceCacheOptions GetProduceCacheOptions() const {
83     return produce_cache_options_;
84   }
UnboundScript(v8::Isolate * isolate)85   v8::Local<v8::UnboundModuleScript> UnboundScript(v8::Isolate* isolate) const {
86     return unbound_script_.NewLocal(isolate);
87   }
88 
89  private:
90   Member<SingleCachedMetadataHandler> cache_handler_;
91   V8CodeCache::ProduceCacheOptions produce_cache_options_;
92 
93   // TODO(keishi): Visitor only defines a trace method for v8::Value so this
94   // needs to be cast.
95   GC_PLUGIN_IGNORE("757708")
96   TraceWrapperV8Reference<v8::UnboundModuleScript> unbound_script_;
97 };
98 
99 // TODO(rikaf): Add a class level comment
100 class CORE_EXPORT ModuleRecord final {
101   STATIC_ONLY(ModuleRecord);
102 
103  public:
104   static v8::Local<v8::Module> Compile(
105       v8::Isolate*,
106       const String& source,
107       const KURL& source_url,
108       const KURL& base_url,
109       const ScriptFetchOptions&,
110       const TextPosition&,
111       ExceptionState&,
112       V8CacheOptions = kV8CacheOptionsDefault,
113       SingleCachedMetadataHandler* = nullptr,
114       ScriptSourceLocationType source_location_type =
115           ScriptSourceLocationType::kInternal,
116       ModuleRecordProduceCacheData** out_produce_cache_data = nullptr);
117 
118   // Returns exception, if any.
119   static ScriptValue Instantiate(ScriptState*,
120                                  v8::Local<v8::Module> record,
121                                  const KURL& source_url);
122 
123   // Returns exception, if any
124   static ScriptValue Evaluate(ScriptState*,
125                               v8::Local<v8::Module> record,
126                               const KURL& source_url);
127   static void ReportException(ScriptState*, v8::Local<v8::Value> exception);
128 
129   static Vector<String> ModuleRequests(ScriptState*,
130                                        v8::Local<v8::Module> record);
131   static Vector<TextPosition> ModuleRequestPositions(
132       ScriptState*,
133       v8::Local<v8::Module> record);
134 
135   static v8::Local<v8::Value> V8Namespace(v8::Local<v8::Module> record);
136 
137  private:
138   static v8::MaybeLocal<v8::Module> ResolveModuleCallback(
139       v8::Local<v8::Context>,
140       v8::Local<v8::String> specifier,
141       v8::Local<v8::Module> referrer);
142 };
143 
144 }  // namespace blink
145 
146 #endif  // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_
147