Commit b4d64979 authored by Emanuel Ziegler's avatar Emanuel Ziegler Committed by Commit Bot

[wasm][wpt] Adjust error handling for null response bodies

Since a Response object with a null body is valid, we should throw a
WebAssembly.CompileError instead of a TypeError for
WebAssembly.compileStreaming and WebAssembly.instantiateStreaming.

This allows us to remove the expected results from the corresponding WPT test
because it passes now.

R=ahaas@chromium.org

Depends-On: I238288de73283a06c5075d0060977b366c0fbe09
Change-Id: I19568e6c0906de518fd6e5b417ef7e045e9d43c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2142212Reviewed-by: default avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Emanuel Ziegler <ecmziegler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760475}
parent 65d961fb
...@@ -347,7 +347,9 @@ void StreamFromResponseCallback( ...@@ -347,7 +347,9 @@ void StreamFromResponseCallback(
return; return;
if (!response->BodyBuffer()) { if (!response->BodyBuffer()) {
exception_state.ThrowTypeError("Response object has a null body."); // Since the status is 2xx (ok), this must be status 204 (No Content),
// status 205 (Reset Content) or a malformed status 200 (OK).
exception_state.ThrowWasmCompileError("Empty WebAssembly module");
return; return;
} }
......
...@@ -118,7 +118,9 @@ inline bool IsDOMExceptionCode(ExceptionCode exception_code) { ...@@ -118,7 +118,9 @@ inline bool IsDOMExceptionCode(ExceptionCode exception_code) {
static_cast<ExceptionCode>(DOMExceptionCode::kNumOfCodes); static_cast<ExceptionCode>(DOMExceptionCode::kNumOfCodes);
} }
// Exception codes that correspond to ECMAScript Error objects. // Exception codes that correspond to ECMAScript Error objects and
// other errors derived from ECMAScript's NativeError class like
// WebAssembly errors.
// https://tc39.github.io/ecma262/#sec-error-objects // https://tc39.github.io/ecma262/#sec-error-objects
enum class ESErrorType : ExceptionCode { enum class ESErrorType : ExceptionCode {
kError = 1000, // ECMAScript Error object kError = 1000, // ECMAScript Error object
...@@ -126,8 +128,11 @@ enum class ESErrorType : ExceptionCode { ...@@ -126,8 +128,11 @@ enum class ESErrorType : ExceptionCode {
kReferenceError, // ECMAScript ReferenceError object kReferenceError, // ECMAScript ReferenceError object
// Note that ECMAScript SyntaxError object is different from DOMException's // Note that ECMAScript SyntaxError object is different from DOMException's
// SyntaxError. See also the comment at |DOMExceptionCode::kSyntaxError|. // SyntaxError. See also the comment at |DOMExceptionCode::kSyntaxError|.
kSyntaxError, // ECMAScript SyntaxError object kSyntaxError, // ECMAScript SyntaxError object
kTypeError, // ECMAScript TypeError object kTypeError, // ECMAScript TypeError object
kWasmCompileError, // WebAssembly.CompileError object
kWasmLinkError, // WebAssembly.LinkError object
kWasmRuntimeError, // WebAssembly.RuntimeError object
}; };
// Exception codes used only inside ExceptionState implementation. // Exception codes used only inside ExceptionState implementation.
......
...@@ -125,6 +125,12 @@ void ExceptionState::ThrowTypeError(const String& message) { ...@@ -125,6 +125,12 @@ void ExceptionState::ThrowTypeError(const String& message) {
AddExceptionContext(message))); AddExceptionContext(message)));
} }
void ExceptionState::ThrowWasmCompileError(const String& message) {
SetException(ToExceptionCode(ESErrorType::kWasmCompileError), message,
V8ThrowException::CreateWasmCompileError(
isolate_, AddExceptionContext(message)));
}
void ExceptionState::ThrowDOMException(DOMExceptionCode exception_code, void ExceptionState::ThrowDOMException(DOMExceptionCode exception_code,
const char* message) { const char* message) {
ThrowDOMException(exception_code, String(message)); ThrowDOMException(exception_code, String(message));
...@@ -143,6 +149,10 @@ void ExceptionState::ThrowTypeError(const char* message) { ...@@ -143,6 +149,10 @@ void ExceptionState::ThrowTypeError(const char* message) {
ThrowTypeError(String(message)); ThrowTypeError(String(message));
} }
void ExceptionState::ThrowWasmCompileError(const char* message) {
ThrowWasmCompileError(String(message));
}
void ExceptionState::RethrowV8Exception(v8::Local<v8::Value> value) { void ExceptionState::RethrowV8Exception(v8::Local<v8::Value> value) {
SetException( SetException(
static_cast<ExceptionCode>(InternalExceptionType::kRethrownException), static_cast<ExceptionCode>(InternalExceptionType::kRethrownException),
...@@ -245,6 +255,11 @@ void NonThrowableExceptionState::ThrowTypeError(const String& message) { ...@@ -245,6 +255,11 @@ void NonThrowableExceptionState::ThrowTypeError(const String& message) {
DCHECK_AT(false, file_, line_) << "TypeError should not be thrown."; DCHECK_AT(false, file_, line_) << "TypeError should not be thrown.";
} }
void NonThrowableExceptionState::ThrowWasmCompileError(const String& message) {
DCHECK_AT(false, file_, line_)
<< "WebAssembly.CompileError should not be thrown.";
}
void NonThrowableExceptionState::RethrowV8Exception(v8::Local<v8::Value>) { void NonThrowableExceptionState::RethrowV8Exception(v8::Local<v8::Value>) {
DCHECK_AT(false, file_, line_) << "An exception should not be rethrown."; DCHECK_AT(false, file_, line_) << "An exception should not be rethrown.";
} }
...@@ -273,6 +288,12 @@ void DummyExceptionStateForTesting::ThrowTypeError(const String& message) { ...@@ -273,6 +288,12 @@ void DummyExceptionStateForTesting::ThrowTypeError(const String& message) {
v8::Local<v8::Value>()); v8::Local<v8::Value>());
} }
void DummyExceptionStateForTesting::ThrowWasmCompileError(
const String& message) {
SetException(ToExceptionCode(ESErrorType::kWasmCompileError), message,
v8::Local<v8::Value>());
}
void DummyExceptionStateForTesting::RethrowV8Exception(v8::Local<v8::Value>) { void DummyExceptionStateForTesting::RethrowV8Exception(v8::Local<v8::Value>) {
SetException( SetException(
static_cast<ExceptionCode>(InternalExceptionType::kRethrownException), static_cast<ExceptionCode>(InternalExceptionType::kRethrownException),
......
...@@ -122,6 +122,9 @@ class PLATFORM_EXPORT ExceptionState { ...@@ -122,6 +122,9 @@ class PLATFORM_EXPORT ExceptionState {
virtual void ThrowRangeError(const String& message); virtual void ThrowRangeError(const String& message);
virtual void ThrowTypeError(const String& message); virtual void ThrowTypeError(const String& message);
// Throws WebAssembly Error object.
virtual void ThrowWasmCompileError(const String& message);
// These overloads reduce the binary code size because the call sites do not // These overloads reduce the binary code size because the call sites do not
// need the conversion by String::String(const char*) that is inlined at each // need the conversion by String::String(const char*) that is inlined at each
// call site. As there are many call sites that pass in a const char*, this // call site. As there are many call sites that pass in a const char*, this
...@@ -132,6 +135,7 @@ class PLATFORM_EXPORT ExceptionState { ...@@ -132,6 +135,7 @@ class PLATFORM_EXPORT ExceptionState {
const char* unsanitized_message = nullptr); const char* unsanitized_message = nullptr);
void ThrowRangeError(const char* message); void ThrowRangeError(const char* message);
void ThrowTypeError(const char* message); void ThrowTypeError(const char* message);
void ThrowWasmCompileError(const char* message);
// Rethrows a v8::Value as an exception. // Rethrows a v8::Value as an exception.
virtual void RethrowV8Exception(v8::Local<v8::Value>); virtual void RethrowV8Exception(v8::Local<v8::Value>);
...@@ -197,6 +201,7 @@ class PLATFORM_EXPORT NonThrowableExceptionState final : public ExceptionState { ...@@ -197,6 +201,7 @@ class PLATFORM_EXPORT NonThrowableExceptionState final : public ExceptionState {
void ThrowSecurityError(const String& sanitized_message, void ThrowSecurityError(const String& sanitized_message,
const String& unsanitized_message) override; const String& unsanitized_message) override;
void ThrowRangeError(const String& message) override; void ThrowRangeError(const String& message) override;
void ThrowWasmCompileError(const String& message) override;
void RethrowV8Exception(v8::Local<v8::Value>) override; void RethrowV8Exception(v8::Local<v8::Value>) override;
ExceptionState& ReturnThis() { return *this; } ExceptionState& ReturnThis() { return *this; }
...@@ -240,6 +245,7 @@ class PLATFORM_EXPORT DummyExceptionStateForTesting final ...@@ -240,6 +245,7 @@ class PLATFORM_EXPORT DummyExceptionStateForTesting final
void ThrowSecurityError(const String& sanitized_message, void ThrowSecurityError(const String& sanitized_message,
const String& unsanitized_message) override; const String& unsanitized_message) override;
void ThrowRangeError(const String& message) override; void ThrowRangeError(const String& message) override;
void ThrowWasmCompileError(const String& message) override;
void RethrowV8Exception(v8::Local<v8::Value>) override; void RethrowV8Exception(v8::Local<v8::Value>) override;
ExceptionState& ReturnThis() { return *this; } ExceptionState& ReturnThis() { return *this; }
}; };
......
...@@ -48,6 +48,13 @@ DEFINE_CREATE_AND_THROW_ERROR_FUNC(ReferenceError, ...@@ -48,6 +48,13 @@ DEFINE_CREATE_AND_THROW_ERROR_FUNC(ReferenceError,
"Reference error") "Reference error")
DEFINE_CREATE_AND_THROW_ERROR_FUNC(SyntaxError, SyntaxError, "Syntax error") DEFINE_CREATE_AND_THROW_ERROR_FUNC(SyntaxError, SyntaxError, "Syntax error")
DEFINE_CREATE_AND_THROW_ERROR_FUNC(TypeError, TypeError, "Type error") DEFINE_CREATE_AND_THROW_ERROR_FUNC(TypeError, TypeError, "Type error")
DEFINE_CREATE_AND_THROW_ERROR_FUNC(WasmCompileError,
WasmCompileError,
"Compile error")
DEFINE_CREATE_AND_THROW_ERROR_FUNC(WasmLinkError, WasmLinkError, "Link error")
DEFINE_CREATE_AND_THROW_ERROR_FUNC(WasmRuntimeError,
WasmRuntimeError,
"Runtime error")
#undef DEFINE_CREATE_AND_THROW_ERROR_FUNC #undef DEFINE_CREATE_AND_THROW_ERROR_FUNC
......
...@@ -52,12 +52,21 @@ class PLATFORM_EXPORT V8ThrowException { ...@@ -52,12 +52,21 @@ class PLATFORM_EXPORT V8ThrowException {
const String& message); const String& message);
static v8::Local<v8::Value> CreateTypeError(v8::Isolate*, static v8::Local<v8::Value> CreateTypeError(v8::Isolate*,
const String& message); const String& message);
static v8::Local<v8::Value> CreateWasmCompileError(v8::Isolate*,
const String& message);
static v8::Local<v8::Value> CreateWasmLinkError(v8::Isolate*,
const String& message);
static v8::Local<v8::Value> CreateWasmRuntimeError(v8::Isolate*,
const String& message);
static void ThrowError(v8::Isolate*, const String& message); static void ThrowError(v8::Isolate*, const String& message);
static void ThrowRangeError(v8::Isolate*, const String& message); static void ThrowRangeError(v8::Isolate*, const String& message);
static void ThrowReferenceError(v8::Isolate*, const String& message); static void ThrowReferenceError(v8::Isolate*, const String& message);
static void ThrowSyntaxError(v8::Isolate*, const String& message); static void ThrowSyntaxError(v8::Isolate*, const String& message);
static void ThrowTypeError(v8::Isolate*, const String& message); static void ThrowTypeError(v8::Isolate*, const String& message);
static void ThrowWasmCompileError(v8::Isolate*, const String& message);
static void ThrowWasmLinkError(v8::Isolate*, const String& message);
static void ThrowWasmRuntimeError(v8::Isolate*, const String& message);
}; };
} // namespace blink } // namespace blink
......
This is a testharness.js-based test.
FAIL compileStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL compileStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS compileStreaming: empty body
PASS compileStreaming: empty body in a promise
FAIL instantiateStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL instantiateStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS instantiateStreaming: empty body
PASS instantiateStreaming: empty body in a promise
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL compileStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL compileStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS compileStreaming: empty body
PASS compileStreaming: empty body in a promise
FAIL instantiateStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL instantiateStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS instantiateStreaming: empty body
PASS instantiateStreaming: empty body in a promise
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL compileStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL compileStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS compileStreaming: empty body
PASS compileStreaming: empty body in a promise
FAIL instantiateStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL instantiateStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS instantiateStreaming: empty body
PASS instantiateStreaming: empty body in a promise
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL compileStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL compileStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS compileStreaming: empty body
PASS compileStreaming: empty body in a promise
FAIL instantiateStreaming: no body promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
FAIL instantiateStreaming: no body in a promise promise_rejects_js: function "function() { throw e }" threw object "TypeError: Failed to execute 'compile' on 'WebAssembly': Response object has a null body." ("TypeError") expected instance of function "function CompileError() { [native code] }" ("CompileError")
PASS instantiateStreaming: empty body
PASS instantiateStreaming: empty body in a promise
Harness: the test ran to completion.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment