ajrcarey / pdfium-render

A high-level idiomatic Rust wrapper around Pdfium, the C++ PDF library used by the Google Chromium project.
https://crates.io/crates/pdfium-render
Other
364 stars 59 forks source link

Latest release of pdfium-lib wasm binary does not work #62

Closed DorianRudolph closed 1 year ago

DorianRudolph commented 1 year ago

https://github.com/paulocoutinhox/pdfium-lib/releases/tag/5407 changes how the PDFium module is defined. I was able to get the example working by replacing

Module.onRuntimeInitialized = async _ => {

with

PDFiumModule().then(async mod => {
    Module = mod;
    wasmTable = Module.asm.__indirect_function_table;

I also noticed that the Reflect::get calls don't seem to return an error when the result is undefined, instead they just return JsValue::UNDEFINED. I'm not entirely sure about this, but without defining the wasmTable variable I got an error in table.length() because table is undefined. So maybe the return values of Reflect::get always have to be checked for .is_undefined()?

ajrcarey commented 1 year ago

Hi @DorianRudolph and thank you for reporting this - this is incredibly helpful. Ideally pdfium-render would figure out for itself internally how to get to the wasm table, irrespective of Pdfium build version. Let me look at this in more detail during the course of the week.

ajrcarey commented 1 year ago

Hi @DorianRudolph, thank you again for reporting this. I have made the following small changes:

  1. examples/index.html now defaults to the new Promise-based module instantiation for upstream Pdfium WASM builds. Comments in the file explain how to use the older instantiation method.
  2. pdfium-render will now use Module.asm.__indirect_function_table as a fallback if it can't find a valid function table in the wasmTable global variable.

These two changes are in the latest commit. You can access them by making pdfium-render a git dependency in your Cargo.toml. It would be good if you could confirm you no longer need to set the wasmTable global variable yourself.

ajrcarey commented 1 year ago

As there have been no further comments, and since I believe the issue to be resolved, I am closing this issue.

Added guards to ensure Reflect::get() return values of JsValue::UNDEFINED are treated as errors, not valid values. Updated README.md. Packaged for release as part of version 0.7.27.

DorianRudolph commented 1 year ago

Hey, thanks for working on this so quickly. I wasn't able to test these changes until now. Unfortunately, the patch is not quite sufficient. The wasmTable is also used in the unpatch_pdfium_function_table and patch_pdfium_function_table functions. Right now I also get an error when saving to blob.

ajrcarey commented 1 year ago

Hi @DorianRudolph, thank you for the patch, much appreciated. Can you provide a small sample that demonstrates your save to blob problem, or at least give me the error message you are seeing?

DorianRudolph commented 1 year ago

Hi, I don't have a sample sample at hand right now, but here is the error message:

pdfium-render::PdfiumLibraryBindings::FPDF_SaveAsCopy(): aborting with error JsSysErrorPatchingFunctionTable(
    JsValue(TypeError: Cannot read properties of undefined (reading 'set')
    TypeError: Cannot read properties of undefined (reading 'set')
        at http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web.js:776:20
        at handleError (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web.js:370:18)
        at imports.wbg.__wbg_set_3bc2be231de215a5 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web.js:775:62)
        at js_sys::WebAssembly::Table::set::h26ce2e5b18b34a39 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[2508]:0x2393ed)
        at pdfium_render::wasm::PdfiumRenderWasmState::patch_pdfium_function_table::h2fd0758f2944d7b4 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[138]:0x6ef8d)
        at <pdfium_render::wasm::WasmPdfiumBindings as pdfium_render::bindings::PdfiumLibraryBindings>::FPDF_SaveAsCopy::h9a69a3f7909e19c1 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[169]:0x8639a)
        at <pdfium_render::thread_safe::ThreadSafePdfiumBindings<T> as pdfium_render::bindings::PdfiumLibraryBindings>::FPDF_SaveAsCopy::h488c09b5191aaf47 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[7635]:0x3054b6)
        at pdfium_render::document::PdfDocument::save_to_writer::hc36e73aeeb859791 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[1258]:0x1bc9a2)
        at pdfium_render::document::PdfDocument::save_to_bytes::hb313a399fe0ad1b2 (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[1459]:0x1d648f)
        at pdfium_render::document::PdfDocument::save_to_blob::h4ae8cb2271f9947c (http://127.0.0.1:5500/pdfextend-web/static/pdfextend_web_bg.wasm:wasm-function[872]:0x17a898)),
)

So the error occurs in the patch_pdfium_function_table function in

        // Pdfium's function table is exported by Emscripten directly into the wasmTable
        // global variable available to each web worker running in the browser.
        // Replace the function entry with the given index with the function in this module
        // with the given name.

        let table: WebAssembly::Table =
            Reflect::get(&js_sys::global(), &JsValue::from("wasmTable"))
                .map_err(PdfiumError::JsSysErrorRetrievingFunctionTable)?
                .into();
// ...

        if let Ok(function) = table.get(pdfium_function_index as u32) { // error: table == JsValue::UNDEFINED

This is the same error as you already fixed in the bind_to_pdfium function.

ajrcarey commented 1 year ago

That's very helpful, thank you. I have centralised the handling of the wasmTable, so that patch_pdfium_function_table() can also use the asm.__indirect_function_table fallback as well. Could you try your function now?

DorianRudolph commented 1 year ago

Thanks, it works now.

ajrcarey commented 1 year ago

Excellent, thank you for testing. Apologies it took so long to sort out. The changes will be packaged and released as part of crate version 0.7.27.