wasm-pack
wasm-pack copied to clipboard
wasm-bindgen: imported JS function that was not marked as `catch` threw an error: Cannot read property 'width' of undefined
π Bug description
I can't access a property of an HtmlCanvasElement with rust, I'm having trouble using the "photon_rs" library with javascript, because of this bug, so I thought it was a bug with the "photon_rs" lib, so I decided to clone the lib code "photon_rs" and analyze it to find the error, that's when I came across this problem and decided to create a small simple project "hello world", then I could determine that the problem is not in the lib "photon_rs", it seems that the problem is in the "wasm-pack"
wasm-bindgen: imported JS function that was not marked as `catch` threw an error: Cannot read property 'width' of undefined
Stack:
TypeError: Cannot read property 'width' of undefined
at http://127.0.0.1:8080/teste.js:132:34
at logError (http://127.0.0.1:8080/teste.js:44:18)
at imports.wbg.__wbg_width_9eb2c66ac9dde633 (http://127.0.0.1:8080/teste.js:131:68)
at web_sys::features::gen_HtmlCanvasElement::HtmlCanvasElement::width::hc1421e5da4eb229c (<anonymous>:wasm-function[215]:0xdb55)
at teste::greet::hea5b9587a566489d (<anonymous>:wasm-function[33]:0x6085)
at greet (<anonymous>:wasm-function[257]:0xe7cb)
at http://127.0.0.1:8080/:19:24
teste.js:132 Uncaught TypeError: Cannot read property 'width' of undefined
at teste.js:132
at logError (teste.js:44)
at imports.wbg.__wbg_width_9eb2c66ac9dde633 (teste.js:131)
at web_sys::features::gen_HtmlCanvasElement::HtmlCanvasElement::width::hc1421e5da4eb229c (<anonymous>:wasm-function[215]:0xdb55)
at teste::greet::hea5b9587a566489d (<anonymous>:wasm-function[33]:0x6085)
at greet (<anonymous>:wasm-function[257]:0xe7cb)
at (index):19
π€ Expected Behavior
access all properties of HTML elements
π Steps to reproduce
lib.rs
mod utils;
use wasm_bindgen::prelude::*;
use web_sys::{HtmlCanvasElement};
//for production use: wasm-pack build --target no-modules --release
//for dev use: wasm-pack build --target no-modules --debug
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
// The `console.log` is quite polymorphic, so we can bind it with multiple
// signatures. Note that we need to use `js_name` to ensure we always call
// `log` in JS.
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_u32(a: u32);
// Multiple arguments too!
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn log_many(a: &str, b: &str);
}
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
}
#[wasm_bindgen]
pub fn greet(canvas: HtmlCanvasElement) {
//alert("Hello, teste!");
console_log!("greet {:?}", canvas.width());
}
Cargo.toml
[package]
name = "teste"
version = "0.1.0"
authors = ["insinfo <[email protected]>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.74" #0.2.63
js-sys = "0.3.51"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.5", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.3.24"
wasm-bindgen-futures = "0.4.24"
[dependencies.web-sys]
version = "0.3.51"
features = [
"Document",
"Element",
"HtmlElement",
"Node",
"Window",
"CanvasRenderingContext2d",
"ImageData",
"HtmlCanvasElement",
"HtmlImageElement",
"console",
'CssStyleDeclaration',
'EventTarget',
]
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
index.html
<!DOCTYPE html>
<html>
<head>
<title>teste</title>
<script id="script-teste" src="teste.js" ></script>
<script>
var modulo;
async function init() {
var scri = document.querySelector('#script-teste');
var url = scri.src.replace(/\.js$/, '_bg.wasm');
modulo = await wasm_bindgen(url);
}
init();
window.onload = function (e) {
setTimeout(function (e) {
var canvas = document.getElementById("canvas");
modulo.greet(canvas);
}, 1000);
};
</script>
</head>
<body>
<h1>teste</h1>
<img id="img"
src="https://dyl80ryjxr1ke.cloudfront.net/external_assets/hero_examples/hair_beach_v391182663/original.jpeg"
width="640" height="480">
<canvas id="canvas" width="640" height="480"></canvas>
</body>
</html>
generated index.js with: wasm-pack build --target no-modules --debug
let wasm_bindgen;
(function() {
const __exports = {};
let wasm;
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachegetUint8Memory0 = null;
function getUint8Memory0() {
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
function logError(f, args) {
try {
return f.apply(this, args);
} catch (e) {
let error = (function () {
try {
return e instanceof Error ? `${e.message}\n\nStack:\n${e.stack}` : e.toString();
} catch(_) {
return "<failed to stringify thrown value>";
}
}());
console.error("wasm-bindgen: imported JS function that was not marked as `catch` threw an error:", error);
throw e;
}
}
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
if (typeof(heap_next) !== 'number') throw new Error('corrupt heap');
heap[idx] = obj;
return idx;
}
/**
* @param {HTMLCanvasElement} canvas
*/
__exports.greet = function(canvas) {
wasm.greet(addHeapObject(canvas));
};
function _assertNum(n) {
if (typeof(n) !== 'number') throw new Error('expected a number argument');
}
async function load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get('Content-Type') != 'application/wasm') {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
async function init(input) {
if (typeof input === 'undefined') {
let src;
if (typeof document === 'undefined') {
src = location.href;
} else {
src = document.currentScript.src;
}
input = src.replace(/\.js$/, '_bg.wasm');
}
const imports = {};
imports.wbg = {};
imports.wbg.__wbg_alert_96651bef84688e4c = function() { return logError(function (arg0, arg1) {
alert(getStringFromWasm0(arg0, arg1));
}, arguments) };
imports.wbg.__wbg_log_cc87b1cd273573ca = function() { return logError(function (arg0, arg1) {
console.log(getStringFromWasm0(arg0, arg1));
}, arguments) };
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbg_width_9eb2c66ac9dde633 = function() { return logError(function (arg0) {
var ret = getObject(arg0).width;
_assertNum(ret);
return ret;
}, arguments) };
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
const { instance, module } = await load(await input, imports);
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
return wasm;
}
wasm_bindgen = Object.assign(init, __exports);
})();
π Your environment
Windows 10 wasm-pack version: wasm-pack 0.9.1 rustc version: rustc 1.53.0 (53cb7b09b 2021-06-17)
https://github.com/insinfo/photon-test https://github.com/silvia-odwyer/photon/issues/99
after a lot of brainstorming, I found out where the problem was, the "wasm-pack" is generating the javascript with error on this line: "wasm_bindgen = Object.assign(init, __exports);"
so to solve the problem I replace this line, so:
//wasm_bindgen = Object.assign(init, __exports);
wasm_bindgen = init;
/**
* Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
* @param obj1
* @param obj2
* @returns obj3 a new object based on obj1 and obj2
*/
function merge_options(obj1, obj2) {
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
and this line "return wasm;" that is why
//return wasm;
return merge_options(wasm, __exports);
this should ideally be fixed in a patch release.
Hi, I tried your code, can get the width
example: https://github.com/lencx/learn-wasm
- react: https://github.com/lencx/learn-wasm/blob/main/src/views/teste.tsx
- rust: https://github.com/lencx/learn-wasm/tree/main/@rsw/teste
website: https://wasm.nofwl.com/#/rsw/issues/teste
use vite to quickly start a wasm project: https://github.com/rustwasm/wasm-pack/issues/1016
@lencx I didn't understand what you meant exactly?
my code on github is already with the correction that I informed here.
I don't use npm , webpack, react or anything like that. Of the 20 projects I work on at the company, 15 are AngularDart and others are pure Javascript or Flutter
My web frontend projects are done with AngularDart or pure javascript, both my personal projects and my projects in the company where I work.
Sorry, because just looking at the code example you gave, I donβt know if you donβt use npm, webpack, etc.