-
Notifications
You must be signed in to change notification settings - Fork 1
[test] Test configureAll #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| // An empty data array will cause a trap. | ||
| assert_throws_js(WebAssembly.RuntimeError, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 currently throws a CompileError here. I think trapping makes more sense because the initial read is out of the array bounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose a CompileError because of symmetry with decoding wire bytes. Changing the type of error is a one-liner so I don't care much.
That said, it's convenient to throw the same kind of error for all possible failures, because then various failure cases can all fall through to the same bit of code that allocates and throws the actual error object. That seems to be what this PR suggests, so I'm fine with that.
| // Extra prototypes will cause a trap. | ||
| assert_throws_js(WebAssembly.RuntimeError, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 does not currently raise any error on extra contents in the arrays, but I think it's worth doing. See #86.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no problem.
| configureAll(makeProtosArray([proto]), | ||
| makeMethodsArray([null, null, null]), | ||
| makeDataArray(data), | ||
| null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 currently traps on this, but I don't think it should be necessary to inspect the value of the methods or prototypes before trying to install them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jakobkummerow pointed out that requiring non-null values here allows the optimized method wrappers to skip a null check, so I'll go ahead and make that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Also, for the record, we do need to inspect the value before installing it, because if it's a funcref then we have to fetch or allocate the JS wrapper for it. Conceptually this is a point where values transition from the Wasm world to the JS world (like extern.convert_any).
My personal preference would be to statically require an array of non-nullable (ref func).
| for (let disallowed of [null, undefined, nonextensible, unwritable, 10, "foo"]) { | ||
| const protosArray = makeProtosArray([disallowed]); | ||
| assert_throws_js(TypeError, () => { | ||
| configureAll(protosArray, methodsArray, dataArray, null); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 currently throws on unwritable, but not most of the other disallowed values. It also traps instead of throwing a TypeError when writing to null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
| for (disallowed of [null, undefined, 10, "foo", nonextensible, unwritable]) { | ||
| assert_throws_js(TypeError, () => { | ||
| configureAll(makeProtosArray([{}]), | ||
| makeMethodsArray([makeStructWithProto]), | ||
| makeDataArray(data), | ||
| disallowed); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 generally has the same mismatches in behavior here as when failing to write properties to a prototype object.
| configureAll(makeProtosArray([proto]), | ||
| makeMethodsArray([makeStructWithProto, null, null, null]), | ||
| makeDataArray(data), | ||
| constructors); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just like with the non-static methods, V8 traps on these null methods.
| 0, // parent prototype index 0 | ||
| ]; | ||
|
|
||
| for (let allowed of [null, {}, Object.getPrototypeOf({}), new Proxy({}, {})]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 does not allow null or the Proxy here, but I don't think there's any reason to restrict what values are allowed as prototypes beyond the normal rules.
| 0, // parent prototype index 0 | ||
| ]; | ||
|
|
||
| assert_throws_js(WebAssembly.RuntimeError, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 throws a CompileError here instead of trapping and similar for other cases of invalid data. I don't feel too strongly about what kind of error we throw for this kind of error.
| 1, // one method | ||
| 0x00, // normal method | ||
| 0x2, // two bytes in name | ||
| 0b11011111, 0b00000000, // invalid UTF-8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
V8 does not currently raise an error on invalid UTF-8. Instead it seems to take the raw byte stream as the name somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation happens to use an existing helper function that silently inserts replacement characters (0xFFFD) for invalid UTF-8. There's no particular reason for that, and it's easy to fix.
rmahdav
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks Thomas!
| 1, // one prototype | ||
| 1, // one constructor | ||
| ...stringToBytes("Foo"), | ||
| 3, // three static method configs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen if we specify 3 as the count of method configs here but define less (2 methods) or more (4 methods) in the next lines? Could this also be one example of unconsumed elements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. The case where there are extra method configs is similar to the "extra data" test and the case where there are not enough method configs is similar to the "early end of data" test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks!
jakobkummerow
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with comments
| // Extra prototypes will cause a trap. | ||
| assert_throws_js(WebAssembly.RuntimeError, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no problem.
| // An empty data array will cause a trap. | ||
| assert_throws_js(WebAssembly.RuntimeError, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose a CompileError because of symmetry with decoding wire bytes. Changing the type of error is a one-liner so I don't care much.
That said, it's convenient to throw the same kind of error for all possible failures, because then various failure cases can all fall through to the same bit of code that allocates and throws the actual error object. That seems to be what this PR suggests, so I'm fine with that.
| configureAll(makeProtosArray([proto]), | ||
| makeMethodsArray([null, null, null]), | ||
| makeDataArray(data), | ||
| null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Also, for the record, we do need to inspect the value before installing it, because if it's a funcref then we have to fetch or allocate the JS wrapper for it. Conceptually this is a point where values transition from the Wasm world to the JS world (like extern.convert_any).
My personal preference would be to statically require an array of non-nullable (ref func).
| for (let disallowed of [null, undefined, nonextensible, unwritable, 10, "foo"]) { | ||
| const protosArray = makeProtosArray([disallowed]); | ||
| assert_throws_js(TypeError, () => { | ||
| configureAll(protosArray, methodsArray, dataArray, null); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
| 1, // one method | ||
| 0x00, // normal method | ||
| 0x2, // two bytes in name | ||
| 0b11011111, 0b00000000, // invalid UTF-8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation happens to use an existing helper function that silently inserts replacement characters (0xFFFD) for invalid UTF-8. There's no particular reason for that, and it's easy to fix.
No description provided.