V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
wasm-result.h
1 // Copyright 2015 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 V8_WASM_WASM_RESULT_H_
6 #define V8_WASM_WASM_RESULT_H_
7 
8 #include <cstdarg>
9 #include <memory>
10 
11 #include "src/base/compiler-specific.h"
12 #include "src/utils.h"
13 
14 #include "src/globals.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 class Isolate;
20 template <typename T>
21 class Handle;
22 
23 namespace wasm {
24 
25 // Base class for Result<T>.
26 class V8_EXPORT_PRIVATE ResultBase {
27  protected:
28  ResultBase() = default;
29 
30  ResultBase& operator=(ResultBase&& other) V8_NOEXCEPT = default;
31 
32  public:
33  ResultBase(ResultBase&& other) V8_NOEXCEPT
34  : error_offset_(other.error_offset_),
35  error_msg_(std::move(other.error_msg_)) {}
36 
37  bool ok() const { return error_msg_.empty(); }
38  bool failed() const { return !ok(); }
39 
40  uint32_t error_offset() const { return error_offset_; }
41  const std::string& error_msg() const & { return error_msg_; }
42  std::string&& error_msg() && { return std::move(error_msg_); }
43 
44  protected:
45  ResultBase(uint32_t error_offset, std::string error_msg)
46  : error_offset_(error_offset), error_msg_(std::move(error_msg)) {
47  // The error message must not be empty, otherwise {failed()} will be false.
48  DCHECK(!error_msg_.empty());
49  }
50 
51  static std::string FormatError(const char* format, va_list args);
52 
53  private:
54  uint32_t error_offset_ = 0;
55  std::string error_msg_;
56 };
57 
58 // The overall result of decoding a function or a module.
59 template <typename T>
60 class Result : public ResultBase {
61  public:
62  Result() = default;
63 
64  template <typename S>
65  explicit Result(S&& value) : value_(std::forward<S>(value)) {}
66 
67  template <typename S>
68  Result(Result<S>&& other) V8_NOEXCEPT : ResultBase(std::move(other)),
69  value_(std::move(other).value()) {}
70 
71  Result& operator=(Result&& other) V8_NOEXCEPT = default;
72 
73  static Result<T> PRINTF_FORMAT(2, 3)
74  Error(uint32_t offset, const char* format, ...) {
75  va_list args;
76  va_start(args, format);
77  Result<T> error_result{offset, FormatError(format, args)};
78  va_end(args);
79  return error_result;
80  }
81 
82  static Result<T> Error(uint32_t error_offset, std::string error_msg) {
83  // Call private constructor.
84  return Result<T>{error_offset, std::move(error_msg)};
85  }
86 
87  static Result<T> ErrorFrom(ResultBase&& error_result) {
88  return Error(error_result.error_offset(),
89  std::move(error_result).error_msg());
90  }
91 
92  static Result<T> ErrorFrom(const ResultBase& error_result) {
93  return Error(error_result.error_offset(), error_result.error_msg());
94  }
95 
96  // Accessor for the value. Returns const reference if {this} is l-value or
97  // const, and returns r-value reference if {this} is r-value. This allows to
98  // extract non-copyable values like {std::unique_ptr} by using
99  // {std::move(result).value()}.
100  const T& value() const & {
101  DCHECK(ok());
102  return value_;
103  }
104  T&& value() && {
105  DCHECK(ok());
106  return std::move(value_);
107  }
108 
109  private:
110  T value_ = T{};
111 
112  Result(uint32_t error_offset, std::string error_msg)
113  : ResultBase(error_offset, std::move(error_msg)) {}
114 
115  DISALLOW_COPY_AND_ASSIGN(Result);
116 };
117 
118 // A helper for generating error messages that bubble up to JS exceptions.
119 class V8_EXPORT_PRIVATE ErrorThrower {
120  public:
121  ErrorThrower(Isolate* isolate, const char* context)
122  : isolate_(isolate), context_(context) {}
123  // Explicitly allow move-construction. Disallow copy (below).
124  ErrorThrower(ErrorThrower&& other) V8_NOEXCEPT;
125  ~ErrorThrower();
126 
127  PRINTF_FORMAT(2, 3) void TypeError(const char* fmt, ...);
128  PRINTF_FORMAT(2, 3) void RangeError(const char* fmt, ...);
129  PRINTF_FORMAT(2, 3) void CompileError(const char* fmt, ...);
130  PRINTF_FORMAT(2, 3) void LinkError(const char* fmt, ...);
131  PRINTF_FORMAT(2, 3) void RuntimeError(const char* fmt, ...);
132 
133  void CompileFailed(const char* error, const ResultBase& result) {
134  DCHECK(result.failed());
135  CompileError("%s: %s @+%u", error, result.error_msg().c_str(),
136  result.error_offset());
137  }
138 
139  void CompileFailed(const ResultBase& result) {
140  DCHECK(result.failed());
141  CompileError("%s @+%u", result.error_msg().c_str(), result.error_offset());
142  }
143 
144  // Create and return exception object.
145  V8_WARN_UNUSED_RESULT Handle<Object> Reify();
146 
147  // Reset any error which was set on this thrower.
148  void Reset();
149 
150  bool error() const { return error_type_ != kNone; }
151  bool wasm_error() { return error_type_ >= kFirstWasmError; }
152  const char* error_msg() { return error_msg_.c_str(); }
153 
154  Isolate* isolate() const { return isolate_; }
155 
156  private:
157  enum ErrorType {
158  kNone,
159  // General errors.
160  kTypeError,
161  kRangeError,
162  // Wasm errors.
163  kCompileError,
164  kLinkError,
165  kRuntimeError,
166 
167  // Marker.
168  kFirstWasmError = kCompileError
169  };
170 
171  void Format(ErrorType error_type_, const char* fmt, va_list);
172 
173  Isolate* isolate_;
174  const char* context_;
175  ErrorType error_type_ = kNone;
176  std::string error_msg_;
177 
178  DISALLOW_COPY_AND_ASSIGN(ErrorThrower);
179  // ErrorThrower should always be stack-allocated, since it constitutes a scope
180  // (things happen in the destructor).
181  DISALLOW_NEW_AND_DELETE();
182 };
183 
184 // Use {nullptr_t} as data value to indicate that this only stores the error,
185 // but no result value (the only valid value is {nullptr}).
186 // [Storing {void} would require template specialization.]
188 
189 } // namespace wasm
190 } // namespace internal
191 } // namespace v8
192 
193 #endif // V8_WASM_WASM_RESULT_H_
Definition: libplatform.h:13