Allow for js property inspection (#1876)

* Add support for #[wasm_bindgen(inspectable)]

This annotation generates a `toJSON` and `toString` implementation for
generated JavaScript classes which display all readable properties
available via the class or its getters

This is useful because wasm-bindgen classes currently serialize to
display one value named `ptr`, which does not model the properties of
the struct in Rust

This annotation addresses rustwasm/wasm-bindgen#1857

* Support console.log for inspectable attr in Nodejs

`#[wasm_bindgen(inspectable)]` now generates an implementation of
`[util.inspect.custom]` for the Node.js target only. This implementation
causes `console.log` and friends to yield the same class-style output,
but with all readable fields of the Rust struct displayed

* Reduce duplication in generated methods

Generated `toString` and `[util.inspect.custom]` methods now call
`toJSON` to reduce duplication

* Store module name in variable
This commit is contained in:
Katie
2019-11-26 10:39:57 -08:00
committed by Alex Crichton
parent 181b10be3f
commit df34cf843e
9 changed files with 228 additions and 0 deletions

View File

@ -170,3 +170,51 @@ exports.js_test_option_classes = () => {
assert.ok(c instanceof wasm.OptionClass);
wasm.option_class_assert_some(c);
};
/**
* Invokes `console.log`, but logs to a string rather than stdout
* @param {any} data Data to pass to `console.log`
* @returns {string} Output from `console.log`, without color or trailing newlines
*/
const console_log_to_string = data => {
// Store the original stdout.write and create a console that logs without color
const original_write = process.stdout.write;
const colorless_console = new console.Console({
stdout: process.stdout,
colorMode: false
});
let output = '';
// Change stdout.write to append to our string, then restore the original function
process.stdout.write = chunk => output += chunk.trim();
colorless_console.log(data);
process.stdout.write = original_write;
return output;
};
exports.js_test_inspectable_classes = () => {
const inspectable = wasm.Inspectable.new();
const not_inspectable = wasm.NotInspectable.new();
// Inspectable classes have a toJSON and toString implementation generated
assert.deepStrictEqual(inspectable.toJSON(), { a: inspectable.a });
assert.strictEqual(inspectable.toString(), `{"a":${inspectable.a}}`);
// Inspectable classes in Node.js have improved console.log formatting as well
assert.strictEqual(console_log_to_string(inspectable), `Inspectable { a: ${inspectable.a} }`);
// Non-inspectable classes do not have a toJSON or toString generated
assert.strictEqual(not_inspectable.toJSON, undefined);
assert.strictEqual(not_inspectable.toString(), '[object Object]');
// Non-inspectable classes in Node.js have no special console.log formatting
assert.strictEqual(console_log_to_string(not_inspectable), `NotInspectable { ptr: ${not_inspectable.ptr} }`);
inspectable.free();
not_inspectable.free();
};
exports.js_test_inspectable_classes_can_override_generated_methods = () => {
const overridden_inspectable = wasm.OverriddenInspectable.new();
// Inspectable classes can have the generated toJSON and toString overwritten
assert.strictEqual(overridden_inspectable.a, 0);
assert.deepStrictEqual(overridden_inspectable.toJSON(), 'JSON was overwritten');
assert.strictEqual(overridden_inspectable.toString(), 'string was overwritten');
overridden_inspectable.free();
};