2

I am fairly new to JS and creating a chrome extension where i have use Array.filter function, But for some website, website owner has created their own Array.filter function whose behavior is not same as built in function. Is there any way to override this user defined function and get the native behavior of this function. Any Help will be appreciated.

  • Content scripts have their own isolated environment, meaning your content script cant use variables / functions that were made in the injected page. So even if the site implemented their own `Array#filter` method your script wouldn't be able to use it. Unless you bypassed the isolation by injecting a script into the DOM of the page. – Patrick Evans Nov 20 '18 at 05:53
  • @PatrickEvans, I am injecting my JS to the DOM of page as its required to do so. – Chaudhary238 Nov 20 '18 at 05:55

2 Answers2

2

Run your code before the page scripts and use Object.defineProperty to redefine the method and forbid subsequent changes. You need to put that code in a DOM script element so that it runs in the page context (more info), using a literal string, not src property, to ensure it precedes any other page scripts (more info).

manifest.json:

"content_scripts": [{
  "matches": ["https://foo.bar/*"],
  "js": ["content.js"],
  "run_at": "document_start",
  "all_frames": true
}]

content.js:

const script = document.createElement("script");
script.textContent = `
  Object.defineProperty(Array.prototype, 'filter', {
    value: Array.prototype.filter,
    configurable: false,
    writable: false,
  });
`;
document.documentElement.appendChild(script);
script.remove();
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • 1
    Forcing the filter method to not be writable by the page could have unexpected results, like causing whatever logic is using it to error out. The page might have a legitimate reason for having a custom one – Patrick Evans Nov 20 '18 at 06:13
  • This is what OP wants AFAICT. – wOxxOm Nov 20 '18 at 06:14
2

To save the original Array#filter method you just save it to a variable and then use it when needed by using call():

//Saving the original method
var ArrayFilter = Array.prototype.filter;
//Then whenever needing to use it, call it by using call()
var someArray = [1,2,3];
var filteredArray = ArrayFilter.call(someArray,function(){ /* your filter callback */ });

Now you need to make this run before the script that creates the modified filter() method. You are going to have to do this by changing at which point your content script is loaded so it can load the other code. This is done by setting the run_at setting in the manifest:

manifest:

"content_scripts": [
  {
    "matches": ["http://*.example.com/*"],
    "run_at": "document_start",
    "js": ["contentScript.js"]
  }
],

contentScript.js

//injecting the script into the page
//or however you are currently doing it
var yourScript = document.createElement('script');
document.head.appendChild(yourScript);
yourScript.textContent = "/* your js code */";
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87