Search code examples
javascriptweb-worker

Specify charset for importscripts in webworkers


I am using webworkers for executing a script seperately apart from my main js thread. While importing the script inside the webworker how to specify the charset?


Solution

  • There is no defined way to do it.

    According to specs, fetch a classic worker imported script must read the fetched data as UTF-8:

    1. Let source text be the result of UTF-8 decoding response's body.

    (Same applies for fetch a classic worker script b.t.w.)

    This leaves no room for doubt. Even setting the charset in the Content-Type header wouldn't help here (while it should for fetching classic scripts).

    Now, it seems Chrome doesn't honor this rule (at least not for data:// URLs, I didn't try with real file served, and for blob:// URLs they don't even look at the defined charset...), but Firefox does.

    // we store the text encoded as base64 to preserve the encoding
    // original text is `postMessage("é and ü")`
    const script_url = "data:text/javascript;charset=windows-1252;base64,cG9zdE1lc3NhZ2UoIukgYW5kIPwiKQ==";
    
    // importScript() test
    {
      const worker_script = `importScripts( "${ script_url }" );`;
      const import_worker = new Worker( URL.createObjectURL( new Blob( [ worker_script ], { type: "text/javascript" } ) ) );
      import_worker.onmessage = (evt) => {
        console.log( 'importScripts:', evt.data );
      };
    }
    
    // Worker script test
    {
      const direct_worker = new Worker( script_url );
      direct_worker.onmessage = (evt) => {
        console.log( 'worker script:', evt.data );
      };
    }
    
    // inline script test
    {
      const script = document.createElement( 'script' );
      script.src = script_url;
      document.head.append( script );
      onmessage = (evt) => {
        console.log( 'inline-script:', evt.data );
      };
    }


    Of course, there are ways around that:

    • Definitely the best solution is to re-encode your scripts as UTF-8.
    • Another completely hacky solution is to fetch your script as a Blob, read it as a DOMString using the correct encoding, and then generate a new UTF-8 Blob that you'd serve to importScripts. Doable, but really ugly.