2

I want to override the postMessage() function in all Worker created after the override. I am doing this in a browser extension from a content script before page is loaded.

I have tried to simply override it like this:

Worker.prototype.postMessage = function() {
    console.log('post1:');
};

Worker.postMessage = function() {
    console.log('post2');
};

But this does nothing.

I also tried proxying the object creation like this:

const workerTarget = Worker;

const workerHandler = {
    construct(target, args) {
        console.log(`Creating a ${target.name}`);
        console.log('args:' + args);
        var t = new workerTarget(args);
        return t;
    },
  };
  
const workerProxy = new Proxy(workerTarget, workerHandler);
Worker = workerProxy;

This seems to work since I get the console log entries and the worker is not messed up, i.e. it still does it's job.

But if I try to override postMessage() after the Worker is constructed like this:

const workerTarget = Worker;

const workerHandler = {
    construct(target, args) {
        console.log(`Creating a ${target.name}`);
        console.log('args:' + args);
        var t = new workerTarget(args);
        t.postMessage = function(...args2) {
            console.log('post');
        };
        return t;
    },
};

const workerProxy = new Proxy(workerTarget, workerHandler);
Worker = workerProxy;

It does not work, nothing happens to the Worker.

EDIT I tried another approach, using the onmessage property instead, which should let me inspect any message posted by any worker thread to the main script?

const onmessagegetter = Object.getOwnPropertyDescriptor(Worker.prototype, 'onmessage').get;
const onmessagesetter = Object.getOwnPropertyDescriptor(Worker.prototype, 'onmessage').set;
Object.defineProperty(Worker.prototype, 'onmessage', {
  get() {
    console.log('getCalled');
    return onmessagegetter.apply(this);
  },
  set() {
    console.log('setCalled');
    return onmessagesetter.apply(this, arguments);
  }
});

Will this let me inspect all messages posted by any worker? (dedicated/shared/service)

EDIT2 Looks like this will only let me see when the onmessage() is declared not when the event is triggered.

4
  • What would you like to achieve? Why is it important to be able to override postMessage()? Commented Nov 22, 2024 at 16:44
  • I want to see and edit the content/payload of postMessage, or onmessage, same thing. Commented Nov 22, 2024 at 16:57
  • You only want to override the Worker object's method (i.e the one you can access on the main thread) and not the WorkerGlobalScope's one, right? Your first snippet should do this, assuming Worker is in the same global as the scripts that will run new Worker. jsfiddle.net/0fqz8nc4 Commented Nov 26, 2024 at 7:27
  • No, I want to know what created Workers post to the main script. I guess it does not work because it is another scope? However, I tried to use onmessage instead, that should let me inspect any message posted by workers? But, I have problems getting that to work too. See my edit. Commented Nov 26, 2024 at 14:33

2 Answers 2

0

to overide postMessage to all Worker instance create after your script runs, use a Proxy to intercept the Worker constructor and modify the postMessage method on each worker after it's instantiated:

 const workerTarget = Worker;
    const workerHandler = {
      construct(target, args){
        const workInstance = new target(...args);
        workerInstance.postMessage = function(...messageArgs){
         console.log('Intercepted postMessage:', messageArgs);
        };
        return workerInstance;
      }
    };
   Worker = new Proxy(workerTarget, workerHandler);

this is ensure that postMessage is overridden for all workers created afterwords. make sure the script run before any workers are created on the page.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, that is what I thought should work. Basically same as my script. But it does not work (I tested your exact script to be sure) . The proxying of construct works, but the postMessage is never modified.
0

So I still do not know exactly why you cannot override postMessage, so if anyone can give a good explanation please comment.

I resolved my problem with another approach, pre appending my own script to the Worker script at creation like this:

const workerHandler = {
    construct(target, args) {
        console.log(`Creating a ${target.name}`);
        console.log('args:' + args);
        
        const request = new XMLHttpRequest();
        request.open("GET", args, false); // `false` makes the request synchronous
        request.send(); // blocks until response

        if (request.status === 200) {
            console.log('XHR Success');
        }
        else{
            console.log('XHR Failed');
        }

        const sourceBlob = new Blob([request.responseText]);
        const blob = new Blob([ '(' + payload.toString() + ')();' , sourceBlob ], {type: 'application/javascript'});
        const t = new target(URL.createObjectURL(blob));
        
        return t;
    },
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.