AssemblyScript / assemblyscript

A TypeScript-like language for WebAssembly.
https://www.assemblyscript.org
Apache License 2.0
16.78k stars 654 forks source link

Compiling esm esm cannot be used directly in the bundler module #2659

Open Mrxyy opened 1 year ago

Mrxyy commented 1 year ago

Bug description

Compiling esm code cannot be used directly in the bundler module,.e.g:

image

The Object.assign cant work. Because bundle module is not the same as browser esm.module export variable just only have getter.

image

image

Steps to reproduce

  1. use binding @external("../test","test")
  2. complie esm code image
  3. I hava a Compatibility method,but i think Not good enough. image

AssemblyScript version

^0.27.0

CountBleck commented 1 year ago

What bundler are you using?

Mrxyy commented 1 year ago

What bundler are you using?

webpack5

CountBleck commented 1 year ago

I suppose the solution is to use Object.defineProperties() instead of Object.assign()

Mrxyy commented 1 year ago

I suppose the solution is to use Object.defineProperties() instead of Object.assign()

Yes, the above code is just to ensure that the current compiled results work.

YSandro commented 7 months ago

Same problem. Generated binding to esm:

const __module0 = imports["./main.js"];
const adaptedImports = {
  "./main.js": Object.assign(Object.create(__module0), {
    myFunc(x) {
      // assembly/index/my_func(i32) => bool
      return __module0.myFunc(x) ? 1 : 0;
    },
  }),
};

In Chrome and Vivaldi works fine. if Firefox throw:

Uncaught TypeError: "myFunc" is read-only

If I edit manually to

const __module0 = imports["./main.js"];
const adaptedImports = {
  "./main.js": Object.assign({
    myFunc(x) {
      // assembly/index/my_func(i32) => bool
      return __module0.myFunc(x) ? 1 : 0;
    },
  }),
};

or to

const __module0 = imports["./main.js"];
const adaptedImports = {
  "./main.js": Object.create(__module0),
};

it works. Also works when calling func via globalThis in env.ts:

// env
@external("env", "myFunc")
export declare function my_func(x: f32): boolean

main.ts:

// ./main.js
globalThis.myFunc = (x: number): boolean => {
  console.info('main.js myFunc()');
  return true;
}

But manual edits or calls through a global object are unnecessary work.