justjake / quickjs-emscripten

Safely execute untrusted Javascript in your Javascript, and execute synchronous code that uses async functions
https://www.npmjs.com/package/quickjs-emscripten
Other
1.18k stars 94 forks source link

Async Regression "TypeError: Object not disposable" in v0.26.0 #138

Closed sufianrhazi closed 5 months ago

sufianrhazi commented 6 months ago

The following code works as expected in v0.25.1, but fails with an error in v0.26.0:

import { getQuickJS } from 'quickjs-emscripten';

function assert(predicate: boolean, message: string) {
    if (!predicate) {
        throw new Error(message);
    }
}

async function sanityTest() {
    // Initialize a runtime & context
    const QuickJS = await getQuickJS();
    const runtime = QuickJS.newRuntime();
    const context = runtime.newContext();

    // Inject a global tracer() function to track executions
    let executed = false;
    const tracer = context.newFunction('tracer', () => {
        executed = true;
        return context.undefined;
    });
    context.setProp(context.global, 'tracer', tracer);
    tracer.dispose();

    // Evaluate some code that schedules a pending job
    context.evalCode('Promise.resolve(true).then(() => tracer())');

    // Verify our trace log hasn't been executed yet
    assert(!executed, 'tracer executed synchronously!');

    // Run pending jobs
    runtime.executePendingJobs();

    // Verify our trace log has been executed
    assert(executed, 'tracer not executed after executePendingJobs');
}

sanityTest();

The error I get when running in v0.26.0 is:

TypeError: Object not disposable
    at j (chunk-CH72DI2V.mjs?v=b51f19f5:1:347)
    at M.executePendingJobs (chunk-CH72DI2V.mjs?v=b51f19f5:5:3444)
    at sanityTest (sanity-test.ts?t=1704396176446:20:11)

I'm assuming this has to do with the using/dispose support added in 0.26.0, which may not be added to the intrinsic Promise.resolve() return value in the context?

justjake commented 5 months ago

Hello, how are you buillding & running this code? I can't reproduce the error in NodeJS w/ npx tsx ./test.mts. Do you have a tsconfig.json for this code? This code example runs to completion with no errors for me in NodeJS, compiled with this project's tsconfig.json.

It would be helpful to have the final output JS code, and information about the runtime you're using like:

justjake commented 5 months ago

I just published 0.26.1-rc.0, does that fix the issue for you?

sufianrhazi commented 5 months ago

Ah, apologies for not including that in the initial report. This is when executed in a browser (Chrome) and built with vite (esbuild + rollup). I'll get the specific versions to you and check if the new rc fixes the issue later today.

sufianrhazi commented 5 months ago

And I've confirmed that 0.26.1-rc.0 fixes the issue for me, thank you!

And to answer your questions, here's the system info it repros on:

To run the code, using this vite.config.js file:

import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
    base: './',
    build: {
        assetsDir: './',
        target: 'es2020',
    },
    optimizeDeps: {
        exclude: ['quickjs-emscripten'],
    },
});

And an example.html file containing:

<!DOCTYPE html>
<meta charset="UTF-8">
<script type="module" src="./example.ts"></script>

Place the repro script as example.ts, run the vite dev server and visit /example.html