Loading

使用AssemblyScript在360浏览器下报错 SyntaxError: Unexpected reserved word

背景

最近在一个项目中使用了AssemblyScript,它能将类似于TypeScript的代码编译为WebAssembly,在其他浏览器都能正常使用,然而在360浏览器上却会报错:SyntaxError: Unexpected reserved word。

原因

先看index.ts,里面有一个简单的add方法,add里面调用了console.log

export function add(a: i32, b: i32): i32 {
  console.log((a + b).toString());
  return a + b;
}

编译后生成的release.js

async function instantiate(module, imports = {}) {
  const adaptedImports = {
    env: Object.assign(Object.create(globalThis), imports.env || {}, {
      abort(message, fileName, lineNumber, columnNumber) {
        // ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
        message = __liftString(message >>> 0);
        fileName = __liftString(fileName >>> 0);
        lineNumber = lineNumber >>> 0;
        columnNumber = columnNumber >>> 0;
        (() => {
          // @external.js
          throw Error(`${message} in ${fileName}:${lineNumber}:${columnNumber}`);
        })();
      },
      "console.log"(text) {
        // ~lib/bindings/dom/console.log(~lib/string/String) => void
        text = __liftString(text >>> 0);
        console.log(text);
      },
    }),
  };
  const { exports } = await WebAssembly.instantiate(module, adaptedImports);
  const memory = exports.memory || imports.env.memory;
  function __liftString(pointer) {
    if (!pointer) return null;
    const
      end = pointer + new Uint32Array(memory.buffer)[pointer - 4 >>> 2] >>> 1,
      memoryU16 = new Uint16Array(memory.buffer);
    let
      start = pointer >>> 1,
      string = "";
    while (end - start > 1024) string += String.fromCharCode(...memoryU16.subarray(start, start += 1024));
    return string + String.fromCharCode(...memoryU16.subarray(start, end));
  }
  return exports;
}
export const {
  memory,
  add
} = await (async url => instantiate(
  await (async () => {
    try { return await globalThis.WebAssembly.compileStreaming(globalThis.fetch(url)); }
    catch { return globalThis.WebAssembly.compile(await (await import("node:fs/promises")).readFile(url)); }
  })(), {
  }
))(new URL("release.wasm", import.meta.url));

360浏览器报错锁定在await这一行

} = await (async url => instantiate(

查看360浏览器的内核版本,发现是86.0.4240.198,360浏览器已经是最新的版本了。
image

而支持在模块顶层使用await的chrome最低版本是89,点这里查看
image

所以出现了这个错误~

所以,有没有什么解决方法呢?

解决方法

不使用await就行了,用Promise代替await。

修改release.js,根据自己的代码进行修改,不能直接照抄

function instantiate(module, imports = {}) {
  return new Promise((resolve) => {
    // 如果有 __lowerString 需要先在这里定义
    let __liftString = function () {};
    const adaptedImports = {
      env: Object.assign(Object.create(globalThis), imports.env || {}, {
        abort(message, fileName, lineNumber, columnNumber) {
          // ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
          message = __liftString(message >>> 0);
          fileName = __liftString(fileName >>> 0);
          lineNumber = lineNumber >>> 0;
          columnNumber = columnNumber >>> 0;
          (() => {
            // @external.js
            throw Error(
              `${message} in ${fileName}:${lineNumber}:${columnNumber}`
            );
          })();
        },
        "console.log"(text) {
          // ~lib/bindings/dom/console.log(~lib/string/String) => void
          text = __liftString(text >>> 0);
          console.log(text);
        },
      }),
    };
    WebAssembly.instantiate(module, adaptedImports).then((res) => {
      const { exports } = res;
      const memory = exports.memory || imports.env.memory;

      __liftString = function (pointer) {
        if (!pointer) return null;
        const end =
            (pointer + new Uint32Array(memory.buffer)[(pointer - 4) >>> 2]) >>>
            1,
          memoryU16 = new Uint16Array(memory.buffer);
        let start = pointer >>> 1,
          string = "";
        while (end - start > 1024)
          string += String.fromCharCode(
            ...memoryU16.subarray(start, (start += 1024))
          );
        return string + String.fromCharCode(...memoryU16.subarray(start, end));
      };
      resolve(exports);
    });
  });
}

export const exports = new Promise((resolve, reject) => {
  globalThis.WebAssembly.compileStreaming(
    globalThis.fetch(new URL("release.wasm", import.meta.url))
  ).then((module) => {
    instantiate(module, {})
      .then((res) => resolve(res))
      .catch((err) => {
        console.error(err);
        reject(err);
      });
  });
});

引入

<script type="module">
    import { exports } from "./release.js";
    exports.then((res) => {
        // add方法
        const { add } = res;
        add(12, 34);
    });
</script>

完美。

posted @ 2022-08-24 15:52  马卡龙MK  阅读(1789)  评论(0编辑  收藏  举报