如何在 Rust WebAssembly 中填充 performance.now

How to polyfill performance.now in Rust WebAssembly

我正在尝试在 cloudflare workers webassembly 运行时中使用 jwt_simple 库。按照链接文档中的基本示例,在执行 key.authenticate(claims)? 之前一切正常,此时在我的终端 运行 wrangler:

中生成以下堆栈跟踪
ReferenceError: performance is not defined
    at __wbg_now_63f780680ee9cc56 (./index_bg.mjs:331:15)
    at wasm://wasm/001926f2:wasm-function[264]:0x252a9
    at wasm://wasm/001926f2:wasm-function[409]:0x2925d
    at wasm://wasm/001926f2:wasm-function[167]:0x1fb99
    at wasm://wasm/001926f2:wasm-function[410]:0x292b9
    at wasm://wasm/001926f2:wasm-function[284]:0x25ea0
    at wasm://wasm/001926f2:wasm-function[132]:0x1cbd9
    at wasm://wasm/001926f2:wasm-function[38]:0x9bbc
    at wasm://wasm/001926f2:wasm-function[143]:0x1dc3b
    at wasm://wasm/001926f2:wasm-function[106]:0x19ccb at line 330, col 13

我怀疑这是因为当 key.authenticate 试图验证 jwt 仍然有效时它调用 performance.now,根据 this forum post is not provided by cloudflare workers to prevent timing attacks. I don't fully understand how webassembly works, but I do know that I can polyfill performance.now in javascript as is done here.

如何在 webassembly 环境中使用这个 polyfill?

在NodeJS运行环境中使用perf_hooks

import { performance } from 'perf_hooks'

否则声明一个具有存根函数的全局performance对象:

const performance = {
  now: () => Date.now(), // milliseconds used for timing diffs
}

在文件生成后替换 performace.now() 的所有实例:

$ sed -i '' 's/performance.now()/Date.now()/' index_bg.mjs

我最终使用 js_sys Reflect 库通过全局范围将 Date.now 分配给 performance.now

use js_sys::{global, Reflect, Object};

pub fn polyfill() {
    let global = global();
    //let performance = {}
    let performance = Object::new();
    //performance.now = global.Date.now
    Reflect::set(
        &performance,
        &"now".into(),
        &Reflect::get(
            &Reflect::get(&global, &"Date".into()).unwrap(),
            &"now".into()
        ).unwrap()
    ).unwrap();
    //global.performance = performance
    Reflect::set(
        &global,
        &"performance".into(),
        &performance
    ).unwrap();
}

然后确保在需要之前调用 polyfill performance.now