v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-wasm.h
Go to the documentation of this file.
1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef INCLUDE_V8_WASM_H_
6 #define INCLUDE_V8_WASM_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "v8-local-handle.h" // NOLINT(build/include_directory)
12 #include "v8-memory-span.h" // NOLINT(build/include_directory)
13 #include "v8-object.h" // NOLINT(build/include_directory)
14 #include "v8config.h" // NOLINT(build/include_directory)
15 
16 namespace v8 {
17 
18 class ArrayBuffer;
19 class Promise;
20 
21 namespace internal {
22 namespace wasm {
23 class NativeModule;
24 class StreamingDecoder;
25 } // namespace wasm
26 } // namespace internal
27 
28 /**
29  * An owned byte buffer with associated size.
30  */
31 struct OwnedBuffer {
32  std::unique_ptr<const uint8_t[]> buffer;
33  size_t size = 0;
34  OwnedBuffer(std::unique_ptr<const uint8_t[]> buffer, size_t size)
35  : buffer(std::move(buffer)), size(size) {}
36  OwnedBuffer() = default;
37 };
38 
39 // Wrapper around a compiled WebAssembly module, which is potentially shared by
40 // different WasmModuleObjects.
42  public:
43  /**
44  * Serialize the compiled module. The serialized data does not include the
45  * wire bytes.
46  */
48 
49  /**
50  * Get the (wasm-encoded) wire bytes that were used to compile this module.
51  */
52  MemorySpan<const uint8_t> GetWireBytesRef();
53 
54  const std::string& source_url() const { return source_url_; }
55 
56  private:
57  friend class WasmModuleObject;
58  friend class WasmStreaming;
59 
60  explicit CompiledWasmModule(std::shared_ptr<internal::wasm::NativeModule>,
61  const char* source_url, size_t url_length);
62 
63  const std::shared_ptr<internal::wasm::NativeModule> native_module_;
64  const std::string source_url_;
65 };
66 
67 // An instance of WebAssembly.Memory.
69  public:
70  WasmMemoryObject() = delete;
71 
72  /**
73  * Returns underlying ArrayBuffer.
74  */
76 
78 #ifdef V8_ENABLE_CHECKS
79  CheckCast(value);
80 #endif
81  return static_cast<WasmMemoryObject*>(value);
82  }
83 
84  private:
85  static void CheckCast(Value* object);
86 };
87 
88 // An instance of WebAssembly.Module.
90  public:
91  WasmModuleObject() = delete;
92 
93  /**
94  * Efficiently re-create a WasmModuleObject, without recompiling, from
95  * a CompiledWasmModule.
96  */
98  Isolate* isolate, const CompiledWasmModule&);
99 
100  /**
101  * Get the compiled module for this module object. The compiled module can be
102  * shared by several module objects.
103  */
105 
106  /**
107  * Compile a Wasm module from the provided uncompiled bytes.
108  */
110  Isolate* isolate, MemorySpan<const uint8_t> wire_bytes);
111 
113 #ifdef V8_ENABLE_CHECKS
114  CheckCast(value);
115 #endif
116  return static_cast<WasmModuleObject*>(value);
117  }
118 
119  private:
120  static void CheckCast(Value* obj);
121 };
122 
123 /**
124  * The V8 interface for WebAssembly streaming compilation. When streaming
125  * compilation is initiated, V8 passes a {WasmStreaming} object to the embedder
126  * such that the embedder can pass the input bytes for streaming compilation to
127  * V8.
128  */
129 class V8_EXPORT WasmStreaming final {
130  public:
131  class WasmStreamingImpl;
132 
133  /**
134  * Client to receive streaming event notifications.
135  */
136  class Client {
137  public:
138  virtual ~Client() = default;
139  /**
140  * Passes the fully compiled module to the client. This can be used to
141  * implement code caching.
142  */
143  virtual void OnModuleCompiled(CompiledWasmModule compiled_module) = 0;
144  };
145 
146  explicit WasmStreaming(std::unique_ptr<WasmStreamingImpl> impl);
147 
149 
150  /**
151  * Pass a new chunk of bytes to WebAssembly streaming compilation.
152  * The buffer passed into {OnBytesReceived} is owned by the caller.
153  */
154  void OnBytesReceived(const uint8_t* bytes, size_t size);
155 
156  /**
157  * {Finish} should be called after all received bytes where passed to
158  * {OnBytesReceived} to tell V8 that there will be no more bytes. {Finish}
159  * does not have to be called after {Abort} has been called already.
160  * If {can_use_compiled_module} is true and {SetCompiledModuleBytes} was
161  * previously called, the compiled module bytes can be used.
162  * If {can_use_compiled_module} is false, the compiled module bytes previously
163  * set by {SetCompiledModuleBytes} should not be used.
164  */
165  void Finish(bool can_use_compiled_module = true);
166 
167  /**
168  * Abort streaming compilation. If {exception} has a value, then the promise
169  * associated with streaming compilation is rejected with that value. If
170  * {exception} does not have value, the promise does not get rejected.
171  */
172  void Abort(MaybeLocal<Value> exception);
173 
174  /**
175  * Passes previously compiled module bytes. This must be called before
176  * {OnBytesReceived}, {Finish}, or {Abort}. Returns true if the module bytes
177  * can be used, false otherwise. The buffer passed via {bytes} and {size}
178  * is owned by the caller. If {SetCompiledModuleBytes} returns true, the
179  * buffer must remain valid until either {Finish} or {Abort} completes.
180  * The compiled module bytes should not be used until {Finish(true)} is
181  * called, because they can be invalidated later by {Finish(false)}.
182  */
183  bool SetCompiledModuleBytes(const uint8_t* bytes, size_t size);
184 
185  /**
186  * Sets the client object that will receive streaming event notifications.
187  * This must be called before {OnBytesReceived}, {Finish}, or {Abort}.
188  */
189  void SetClient(std::shared_ptr<Client> client);
190 
191  /*
192  * Sets the UTF-8 encoded source URL for the {Script} object. This must be
193  * called before {Finish}.
194  */
195  void SetUrl(const char* url, size_t length);
196 
197  /**
198  * Unpacks a {WasmStreaming} object wrapped in a {Managed} for the embedder.
199  * Since the embedder is on the other side of the API, it cannot unpack the
200  * {Managed} itself.
201  */
202  static std::shared_ptr<WasmStreaming> Unpack(Isolate* isolate,
203  Local<Value> value);
204 
205  private:
206  std::unique_ptr<WasmStreamingImpl> impl_;
207 };
208 
209 // TODO(mtrofin): when streaming compilation is done, we can rename this
210 // to simply WasmModuleObjectBuilder
211 class V8_EXPORT WasmModuleObjectBuilderStreaming final {
212  public:
214  /**
215  * The buffer passed into OnBytesReceived is owned by the caller.
216  */
217  void OnBytesReceived(const uint8_t*, size_t size);
218  void Finish();
219  /**
220  * Abort streaming compilation. If {exception} has a value, then the promise
221  * associated with streaming compilation is rejected with that value. If
222  * {exception} does not have value, the promise does not get rejected.
223  */
224  void Abort(MaybeLocal<Value> exception);
226 
228 
229  private:
230  WasmModuleObjectBuilderStreaming(const WasmModuleObjectBuilderStreaming&) =
231  delete;
232  WasmModuleObjectBuilderStreaming(WasmModuleObjectBuilderStreaming&&) =
233  default;
234  WasmModuleObjectBuilderStreaming& operator=(
235  const WasmModuleObjectBuilderStreaming&) = delete;
236  WasmModuleObjectBuilderStreaming& operator=(
237  WasmModuleObjectBuilderStreaming&&) = default;
238  Isolate* isolate_ = nullptr;
239 
240 #if V8_CC_MSVC
241  /**
242  * We don't need the static Copy API, so the default
243  * NonCopyablePersistentTraits would be sufficient, however,
244  * MSVC eagerly instantiates the Copy.
245  * We ensure we don't use Copy, however, by compiling with the
246  * defaults everywhere else.
247  */
248  Persistent<Promise, CopyablePersistentTraits<Promise>> promise_;
249 #else
250  Persistent<Promise> promise_;
251 #endif
252  std::shared_ptr<internal::wasm::StreamingDecoder> streaming_decoder_;
253 };
254 
255 } // namespace v8
256 
257 #endif // INCLUDE_V8_WASM_H_