The "apply" function in Javascript cannot be found in the window.external extension object

Utilizing the javascript extension (known as window.external) in IE8 (or any IE version) to expose specific functions, I encountered an issue when attempting to call the apply function. Despite the belief that it is inherently available in every JS function, the browser consistently throws an exception stating that the apply function is not present for that function within the window.external object.

For instance, the following code functions correctly:

function onDataReceived(url, success, status, data, errorMessage) {
    alert(onDataReceived);
}

function innerTest() {
    alert(arguments[0] + ", " + arguments[1]);
}

function outerTest() {
    innerTest.apply(null, arguments);
}

outerTest("hello", "world");

// alerts "hello, world"

However, the subsequent code triggers an exception:

function outerTest() {
    window.external.innerTest.apply(null, arguments); // <-- exception
}

outerTest("hello", "world");

The main challenge lies in passing an unknown number of arguments to the external function, leading to a roadblock in my progress.

Any suggestions or insights would be greatly appreciated.

EDIT:
After accepting Mike Samuel's response, I realized that the apply function is not present in the window.external object, presumably due to it not being a native javascript object. As a temporary solution, I followed Mike's advice on the "worst case" scenario. Thank you.

Answer №1

In the scenario where window.external is considered a host object, or originates from an extension mechanism that prefers not to expose its prototype to page logic, it may function as intended but lack the typical call and apply functionalities. Fortunately, you can still utilize call and apply as shown below:

Function.prototype.apply.call(window.external, null, [argumentsToExtension])

For a more abstract approach:

Function.prototype.apply.apply(window.external, [null, [argumentsToExtension]])

Here, the null parameter represents the value of this, which should effectively equate to window following the standard call/apply conventions.

UPDATE:

If the previous methods fail, resorting to the "triangle of hackery" could be a viable option.

function triangleOfHackery(obj, methodName, args) {
  switch (args.length) {
    case 0: return obj[methodName]();
    case 1: return obj[methodName](args[0]);
    case 2: return obj[methodName](args[0], args[1]);
    case 3: return obj[methodName](args[0], args[1], args[2]);
    ...
  }
}

Answer №2

There is actually a general solution available. Here is a simple example to illustrate:

function executeFunction (funcName, ...args) {
    var argStr = '';
    for (let i in args) {
        argStr += ', this.args[' + i + ']';
    }
    return (new Function('return window.external[\'' + funcName + '\'](' + argStr.substring(2) + ')')).bind({args})();
}

// create a circular structure that cannot be converted to a string:
const b = {}; b.b = b;

// make a function call:
executeFunction('bar', 10, 'xyz', new Date(), function(){}, b);

// equivalent to:
window.external.bar(10, 'xyz', new Date(), function(){}, b);

As shown, it is not necessary to ensure that the parameters are serializable.

The key is to properly define the context and assign all the parameters to that context.

ES6 syntax was used to improve the code's readability. To make it compatible with IE8, you can convert it to ES5 syntax and include an ES5 shim to support Function.prototype.bind. Alternatively, you can avoid using bind altogether:

EDIT: ES5 compatible version:

function executeFunction (funcName) {
    var argStr = '';
    for (var i=1; i<arguments.length; i++) {
        argStr += ', this.args[' + i + ']';
    }
    return {
        args: arguments,
        func: new Function('return window.external[\'' + funcName + '\'](' + argStr.substring(2) + ')')
    }.func();
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for clearing text inputs in ReactJS

In my current Reactjs project using nextjs, I am facing an issue with clearing input fields after a click event. Below is the code snippet that I have been working on: <form onSubmit={handleSubmit}> <input type="text" ...

You can install the precise version of a package as mentioned in package.json using npm

At this moment, executing the command npm install will download the latest versions of packages. Is there a way to install the exact versions specified in the package.json file? ...

How to Stop Element Flickering While Hovering in Selenium IE Webdriver

My code is functioning perfectly in Firefox, but when I try it on Internet Explorer, there is flickering. Here is my code: WebElement mouseOver= driver.findElement(By.linkText("abc")); //I'm locating the element by link text. Selenium finds the ...

Discover the best practices for utilizing CSS selectors reliably in puppeteer

For a project, I am currently working on customizing a puppeteer script that is able to play a song from Soundcloud and record it. The main goal is to utilize a CSS selector to display the duration of the song as well. I am encountering difficulties with g ...

Can dates in the form of a String array be transmitted from the server to the client?

Struggling to send a String array from the server side to the client using Nodejs and Pug. Encounter errors like "SyntaxError: expected expression, got '&'" or "SyntaxError: identifier starts immediately after numeric literal". Server runs o ...

Angular version 8.2 combined with Firebase can result in errors such as those found in the `./src/app/app.module.ngfactory.js` file towards the end of the process when attempting to build with

My first time posing a query on this platform, and certainly not my last. The issue at hand involves the ng-build --prod process failing to complete and throwing errors in my Angular 8.2.14 application. I've integrated Firebase into my project succes ...

Ways to conceal a component based on a specific condition?

In my Angular 8 application, I need to dynamically hide a component based on a specific condition. The condition I want to check is: "status === EcheqSubmissionStatus.EXPIRED" Initially, I attempted the following approach: EcheqProcessComponent templat ...

Having trouble with my getJSON function, can't pinpoint the error in my code

After collaborating with some fellow stack users, I have developed the following: http://jsfiddle.net/9ywLq/ I am looking to integrate an external json file in order to achieve something similar to this: http://jsfiddle.net/RCB9M/ Currently, I am linki ...

What is the best way to show a macOS progress pie loading icon alongside files?

While using macOS, a pie loading icon appears next to a file during downloading or transferring. To illustrate, here is an example of a file being downloaded from Chrome: https://i.sstatic.net/8jS4X.png I am interested in implementing a similar feature i ...

Implementing React router for dynamic page rendering

I'm struggling to make sense of a particular piece of code. Can someone provide an explanation? I'm particularly confused about the role of "props" in this section and how it is essential for the code to work correctly. If I remove "props," my co ...

Tips for converting the Instagram cURL post request to a JavaScript request

I am attempting to convert the code I received from Instagram into a token. The code provided in the Instagram DOCS uses a curl request, but I would like to implement it using JavaScript instead. Here is how the original code looks: curl -X POST &bsol ...

Provide the flow type parameter to the React component

Is there a way to generate flow type in an external component without duplicating types when using it within another component? For instance: import {ExternalComponent} from '@npm-component/another-component'; type CurrentComponentType = {| d ...

To give an element a class in Javascript (without using jQuery) if it is currently hidden

Apologies if this question is not perfect, as I am still learning. I have been struggling to figure out how to add a class to an ID when the class is hidden using pure JavaScript (without jQuery). Below are my attempts so far: function hidekeep() { ...

Troublesome CSS Zoom causing issues with jQuery scrollTop

As I design a website that has a fixed width and zooms out on mobile browsers, I've opted to adjust the zoom using CSS rather than viewport meta tags: html, body { zoom: 0.8; } It's been effective so far, but now I'm facing an issue wi ...

Encountering issues with link button redirection

I have a question regarding a Link element and CustomButton element with an onClick handler. < Link to = "/dashboard" style = { linkStyles } > < CustomButton text = "Login" onClick = { handleSubmit } /> < /Link> The code ...

AngularJS is not immediately responsive to changes in $window.document.visibilityState

I am currently working with AngularJs version 1.4 and I need to be able to detect when a user is not on the tab of my app and when they return. To achieve this, I attempted using $watch in the following way: $rootScope.$watch(angular.bind($window, functio ...

Ways to apply CSS to a changing div ID

I am looking to apply CSS to a dynamically generated div ID. var status = var status = item.down().next().innerHtml(); if(status == "test") { var c = 'item_'+i ; c.style.backgroundColor = 'rgb(255, 125, 115)'; //'ite ...

"Using only JavaScript to target and manipulate child elements within the

I'm currently transitioning from using jQuery to pure JavaScript, and I've just started but am encountering difficulties. Specifically, I am unsure how to select child elements in the DOM. <div class="row-button"> <input type="submi ...

My changes to the HTML file are not being reflected in the browser, even after clearing the cache. This is happening in an Angular and Node.js application

I'm currently developing an application using Angular and Node.js. I've noticed that when I make changes to the HTML file, the browser isn't updating even after clearing the cache. Could this be a coding issue? Any suggestions on how to fix ...

Use JavaScript and AJAX to easily assign multiple variables with unique IDs to an array with just one click

This function is no longer supported Original query : I would greatly appreciate any assistance and guidance. I am attempting to create a function that moves selected products from the Cart to another table so I can reorder them according to customer de ...