Why Are Certain Function Calls Termed "Illegal Invocations" in JavaScript

Uncaught TypeError: Illegal invocation in Chrome

In your code you are assigning a native method to a property of custom object.
When you call support.animationFrame(function () {}) , it is executed in the context of current object (ie support). For the native requestAnimationFrame function to work properly, it must be executed in the context of window.

So the correct usage here is support.animationFrame.call(window, function() {});.

The same happens with alert too:

var myObj = {
myAlert : alert //copying native alert to an object
};

myObj.myAlert('this is an alert'); //is illegal
myObj.myAlert.call(window, 'this is an alert'); // executing in context of window

Another option is to use Function.prototype.bind() which is part of ES5 standard and available in all modern browsers.

var _raf = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;

var support = {
animationFrame: _raf ? _raf.bind(window) : null
};

CommonJS Illegal invocation error when calling function on module.exports

I found the answer here: Why are certain function calls termed "illegal invocations" in JavaScript?

It seems some native functions depend on context, so to fix this I bind to window:

module.exports.requestAnimationFrame = 
(window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame).bind(window);

Uncaught TypeError: Illegal invocation in JavaScript

The console's log function expects this to refer to the console (internally). Consider this code which replicates your problem:

var x = {};
x.func = function(){
if(this !== x){
throw new TypeError('Illegal invocation');
}
console.log('Hi!');
};
// Works!
x.func();

var y = x.func;

// Throws error
y();

Here is a (silly) example that will work, since it binds this to console in your make function:

var make = function(callback,params){
callback.call(console, params);
}

make(console.log,'it will be accepted!');

This will also work

var make = function(callback,params){
callback(params);
}

make(console.log.bind(console),'it will be accepted!');

Illegal Invocation error when console.log passed in a function

Change

o.printToConsole(console.log);

to

o.printToConsole(console.log.bind(console));

or

o.printToConsole(function(){ console.log.apply(console.log, arguments) });

The console.log function only works when the receiver (this) is the console (in fact, it's browser dependent).

JavaScript: TypeError: Illegal invocation but I'm not calling any function

This behavior is caused by the implementation of the specification. These DOM nodes are so-called 'platform objects' and the way they implement getters is slightly different from 'normal' javascript.

In short: they can not be extended without extra work.

var a = document.getElementById("something");
var b = Object.create(a);

When the baseURI of b is accessed, its this points to b which is not a valid 'platform object'. This causes the Illegal invocation error. Accessing it through the prototype does work because then its this points to the prototype which is a valid 'platform object'.

This comment on an issue of Chrome explains it in more detail and also supplies a workaround if you really need it: https://bugs.chromium.org/p/chromium/issues/detail?id=495437#c7

Illegal invocation on window['document']['body']['append'] function

F1["append"] is only a reference to Element.prototype.append:

var F1 = window["document"]["body"];var F2 = F1["append"];console.log(F2 === Element.prototype.append);

Illegal invocation' using input setCustomValidity and TS

As @Heretic Monkey pointed out, you should use event.target.setCustomValidity rather than destructuring the method to avoid losing the context of the function when it's called. See Why are certain function calls termed "illegal invocations" in JavaScript?.

Then, to properly type the event you may want to start by changing the onChange typing in Input.tsx.

// src/Input.tsx
type PropsType = {
//...
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
};

Then update your handleChange callback accordingly in App.tsx.

// src/App.tsx
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
//...
if (type === "email" && !emailPattern.test(value)) {
event.target.setCustomValidity("Please select a valid email address.");
} else {
event.target.setCustomValidity("");
}
}


Related Topics



Leave a reply



Submit