magjac / d3-graphviz

Graphviz DOT rendering and animated transitions using D3
BSD 3-Clause "New" or "Revised" License
1.69k stars 103 forks source link

Can't import web worker using importScripts with vscode webview #249

Closed chouzz closed 2 years ago

chouzz commented 2 years ago

Hi, I would like to use d3-graphviz in vscode webview, it works good. But seems once I make it as a web woker, I cannot load "@hpcc-js/wasm" successfullly.

I make some investigate and found it related importScripts in workerCore.js.

VSCode's webview has some limit with web worker, it don't allowed to use importScripts.

Here is the description from vscode's webview page:

Web Workers are supported inside of webviews but there are a few important restrictions to be aware of. First off, workers can only be loaded using either a data: or blob: URI. You cannot directly load a worker from your extension's folder. If you do need to load worker code from a JavaScript file in your extension, try using fetch:


const workerSource = 'absolute/path/to/worker.js';

fetch(workerSource) .then(result => result.blob()) .then(blob => { var blobUrl = URL.createObjectURL(blob); new Worker(blobUrl); });

>**Worker scripts also do not support importing source code using importScripts or import(...)**.

However, I try to change `importScripts` to `fetch`, but seems it didn't work, here is my changes in https://github.com/magjac/d3-graphviz/blob/master/src/workerCode.js#L14:

export function workerCodeBody(port) {

self.document = {}; // Workaround for "ReferenceError: document is not defined" in hpccWasm

port.addEventListener('message', function(event) {
    let hpccWasm = self["@hpcc-js/wasm"];
    if (hpccWasm == undefined && event.data.vizURL) {
      // importScripts(event.data.vizURL);  // comment this line, vscode webview don't support importScripts

// ----------------------- This is my changes var workerSource = event.data.vizURL fetch(workerSource) .then(result => result.blob()) .then(blob => { const blobUrl = URL.createObjectURL(blob); new Worker(blobUrl); }) // -------------------------- hpccWasm = self["@hpcc-js/wasm"]; hpccWasm.wasmFolder(event.data.vizURL.match(/.*\//)[0]); // This is an alternative workaround where wasmFolder() is not needed // document = {currentScript: {src: event.data.vizURL}}; ... }



But my changes didn't work, the line `hpccWasm = self["@hpcc-js/wasm"]; ` still can't get hpccWasm, do you know how to change this   to make web woker works in vscode webview?

Very appreciate if you can give some ideas.
magjac commented 2 years ago

Sorry for not responding sooner. I wanted to find something sensible to say, but didn't have the time to figure it out. Did you solve the problem?

chouzz commented 2 years ago

I decided to not use web woker in vscode webview, it works good now.

Anyway, it's not a issue about d3-graphviz. Thanks your reply.

Veykril commented 1 year ago

How did you avoid using the web worker? We are hitting this problem in rust-analyzer now and I am unsure how work around this.

chouzz commented 1 year ago

@Veykril Just use webpack and babel compile to the js.

In the js file:

import * as d3 from 'd3';
import * as d3Graphzviz from 'd3-graphviz';
import Vue from 'vue';

Use this js file in the html. Here are webpack configuration:

target: 'web',
entry: './assets/js/index.js',
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'graph.js',
    libraryTarget: 'window',
},
plugins: [
    new htmlWebpackPlugin({
        template: 'assets/index.html',
        inject: 'body',
        publicPath: '#{root}/dist'
    }

and let webpack and babel compile it to es2015, and it works for me in vscode webview panel.

Veykril commented 1 year ago

Thanks I'll try that (though I'd hope I could get around this without the need for babel or webpack) ❤️

Edit: Looks like it just works if you disable the webworker and shared webworker option