Search code examples
namespacesweb-worker

Web worker importScripts fails to place script variables in global scope


TL;DR I have a worker which imports two objects via importScripts. They do not appear in "self". Moz docs say:

        importScripts() method of the WorkerGlobalScope interface 
        synchronously imports one or more scripts into the worker's scope.

So where are they?!

Details: Three files: index.html, worker.js, foo.js

index.html contains:

const worker = new Worker('./worker.js')
worker.postMessage({ file: './foo.js', var: 'foo' })

worker.js contains:

onmessage = e => {
    params = e.data
    console.log('worker: params', params)
    console.log('worker: this === self', this === self)
    importScripts(params.file)
    console.log(self[params.var], eval(params.var), foo)
}

foo.js contains:

const foo = { one: 1, two: 2 }
const bar = { three: 3, four: 4 }

I.e. the html passes the path and variable name to the worker which imports the path and, using the name of the variable, attempts to find it in "self". Fails.

Yet using either "eval" or the variable itself, not its name, works as expected.

Here are the console messages:

worker: params {file: "./foo.js", var: "foo"}
worker: this === self true
undefined {one: 1, two: 2} {one: 1, two: 2}

So where does the worker place the variables imported from foo.js?!

NB: this may seem like an odd thing to do, why not just use the variable? Deep reasons exist having to do with a highly (re)factored repo.


Solution

  • Using const and let to declare variables does not add them to the global scope object, such as the workers self or window (see MDN description for const). Using var does, however:

    const x = 1;
    let y = 2;
    var z = 3;
    
    console.log(window.x, window.y, window.z);
    // undefined undefined 3
    

    Changing your variable declarations for foo and bar to use var should fix the problem.