rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.57k stars 1.04k forks source link

Syntax: ambiguous indirect export with #[wasm_bindgen(module = "...")] #3165

Closed Ekleog closed 1 year ago

Ekleog commented 1 year ago

Hello people! I've recently started trying out web development in Rust-based WASM, with the goal to write cross-platform apps (including mobile).

I first want to say that the Rust web ecosystem looks great to me! That said, I'm not very used to it yet, and am hitting an issue I have no idea how to fix my first wasm-bindgen bindings crate

Describe the Bug

I'm trying to write a rust crate binding to SortableJS. My current code is available here.

However, when trying to run the example I wrote there using trunk, it seems like the javascript code generated by wasm-bindgen is invalid. I have checked that trunk does seem to make the js file available at the right location, and seeing how the network requests performed by my browser (and their responses) seem alright, I don't really know how to dig deeper.

Steps to Reproduce

  1. Clone my test repo
  2. cd examples/simple-list && trunk serve
  3. Open firefox on the URL served by trunk
  4. Open the development console, see that the Sortable import apparently failed with message SyntaxError: ambiguous indirect export: Sortable

Expected Behavior

Well… I'm not at all sure my code is correct as it's my first time writing wasm bindings myself, but if it is then I'd expect the list displayed to be sortable.

Actual Behavior

Instead, the console error message listed above appears. Unfortunately, I'm not really well-versed in javascript (at all), so I have literally no idea how to debug it: stackoverflow answers seem to point to syntax errors either in the upstream library or in the generated code, but given the number of downloads my guess is it's probably not in the upstream library, and I can see the brackets that stackoverflow says are missing in the wasm-bindgen-generated code.

Additional Context

Well… thank you for wasm-bindgen anyway, it's already great if only for web-sys and js-sys! :D And if I can't figure out how to make SortableJS work nicely within a crate that could be uploaded to crates.io for others to use, I guess I can always just depend on SortableJS manually and use it without the (module = "...") detail

Also, if it's me using wasm-bindgen wrong, please feel free to let me know! I have basically zero knowledge of the javascript ecosystem beyond copy-pasting stuff found on the internet… hope I'm not going to just bother you with an unactionable bug report.

Ekleog commented 1 year ago

Adding a few bits of information. First, I have noticed that upstream suggests using import Sortable from 'Sortable.js';. However, even setting js_name = default fails to make wasm-bindgen generate code like this, and instead generates import { default as default1 } from .... See the reproducer in this branch of the repo

Also, I have managed to get things to work, by adding the following patch to Sortable.js:

diff --git a/Sortable.js b/Sortable.js
index c394160..fbad6c9 100644
--- a/Sortable.js
+++ b/Sortable.js
@@ -4,12 +4,8 @@
  * @author     owenm    <owen23355@gmail.com>
  * @license MIT
  */
-(function (global, factory) {
-  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
-  typeof define === 'function' && define.amd ? define(factory) :
-  (global = global || self, global.Sortable = factory());
-}(this, (function () { 'use strict';

+export const Sortable = (function () { 'use strict';
   function ownKeys(object, enumerableOnly) {
     var keys = Object.keys(object);

@@ -3791,4 +3787,4 @@

   return Sortable;

-})));
+})();

Maybe you know why this patch makes things work, and how I could get them to work without having to patch upstream? The full code is here

Liamolucko commented 1 year ago

The problem is that the Sortable.js file you've grabbed is CommonJS (the module system used by Node.js), but Trunk is expecting an ES module. Your patch fixes it because it converts that file to an ES module.

It looks like Sortable already ships an ES module version of the library, though: https://unpkg.com/sortablejs@1.15.0/modular/sortable.esm.js. So, you should be able to use that instead.

(unpkg is just a website that lets you get at the contents of npm packages without downloading them.)

Ekleog commented 1 year ago

Ooh this is awesome, thank you!

Hopefully this issue will serve as documentation of this… surprising error message should someone else encounter it :)