Skip to main content

Bug Tracker

Side navigation

#14001 closed feature (notabug)

Opened June 07, 2013 02:24PM UTC

Closed March 01, 2014 10:13PM UTC

Easy context switching (temporarily load in an iFrame)

Reported by: timmywil Owned by:
Priority: low Milestone: None
Component: core Version: 1.10.1
Keywords: 1.11-discuss Cc:
Blocked by: Blocking:
Description

From Mr. Diego Perini =>

For ages I have been wanting to load jQuery in a temporary IFRAME then moving it to the main browsing context and finally remove the IFRAME used for loading.

Since the IFRAME is going to disappear all the method calls executed in that context or not explicitly scoped will fail and return errors (for example setTimeout => window.setTimeout and parseFloat => window.parseFloat etc.).

To make this work I need the patches you can see in the attached file.

It seems to me none of these changes will introduce incompatibilities.

Can you have a look and tell me if this would be possible?

Attachments (1)
Change History (11)

Changed June 07, 2013 02:33PM UTC by timmywil comment:1

component: unfiledcore
keywords: → 1.11-discuss
priority: undecidedlow
status: newopen

I've recommended Diego make a pull request. Just wanted to get the team's thoughts. I think it's plausible, but it would be good to see a use case in action.

Changed June 07, 2013 02:35PM UTC by timmywil comment:2

description: For ages I have been wanting to load jQuery in a temporary IFRAME then moving it to the main browsing context and finally remove the IFRAME used for loading. \ From Mr. Diego Perini: \ \ Since the IFRAME is going to disappear all the method calls executed in that context or not explicitly scoped will fail and return errors (for example setTimeout => window.setTimeout and parseFloat => window.parseFloat etc.). \ \ To make this work I need the patches you can see in the attached file. \ \ It seems to me none of these changes will introduce incompatibilities. \ \ Can you have a look and tell me if this would be possible? \ For ages I have been wanting to load jQuery in a temporary IFRAME then moving it to the main browsing context and finally remove the IFRAME used for loading. \ From Mr. Diego Perini: \ \ From Mr. Diego Perini: \ \ Since the IFRAME is going to disappear all the method calls executed in that context or not explicitly scoped will fail and return errors (for example setTimeout => window.setTimeout and parseFloat => window.parseFloat etc.). \ \ To make this work I need the patches you can see in the attached file. \ \ It seems to me none of these changes will introduce incompatibilities. \ \ Can you have a look and tell me if this would be possible? \

Changed June 07, 2013 02:36PM UTC by timmywil comment:3

description: For ages I have been wanting to load jQuery in a temporary IFRAME then moving it to the main browsing context and finally remove the IFRAME used for loading. \ From Mr. Diego Perini: \ \ From Mr. Diego Perini: \ \ Since the IFRAME is going to disappear all the method calls executed in that context or not explicitly scoped will fail and return errors (for example setTimeout => window.setTimeout and parseFloat => window.parseFloat etc.). \ \ To make this work I need the patches you can see in the attached file. \ \ It seems to me none of these changes will introduce incompatibilities. \ \ Can you have a look and tell me if this would be possible? \ \ From Mr. Diego Perini => \ \ For ages I have been wanting to load jQuery in a temporary IFRAME then moving it to the main browsing context and finally remove the IFRAME used for loading. \ \ Since the IFRAME is going to disappear all the method calls executed in that context or not explicitly scoped will fail and return errors (for example setTimeout => window.setTimeout and parseFloat => window.parseFloat etc.). \ \ To make this work I need the patches you can see in the attached file. \ \ It seems to me none of these changes will introduce incompatibilities. \ \ Can you have a look and tell me if this would be possible?

Changed June 07, 2013 02:38PM UTC by dmethvin comment:4

_comment0: If jQuery is loaded in an iframe, all the constructors such as Array or Object will belong to the iframe. That will cause issues if there are checks such as `thing.constuctor === Array` when `thing` was created in the parent. I don't know if that may affect our code or client code, especially for oldIE which is very cranky about those things. Did all unit tests pass after this patch? \ \ There was a thread going on at http://forum.jquery.com/topic/save-the-jquery-factory-reuse-it-in-frames-no-2nd-network-request to get the unit tests working in a similar situation but it seems to have stalled. \ \ I think it may be a good idea to explicitly scope things to our internal `window`, especially for non-browser environments, but that is only part of the proposal. \ 1370615954827072

If jQuery is loaded in an iframe, all the constructors such as Array or Object will belong to the iframe. That will cause issues if there are checks such as thing.constructor === Array when thing was created in the parent. I don't know if that may affect our code or client code, especially for oldIE which is very cranky about those things. Did all unit tests pass after this patch?

There was a thread going on at http://forum.jquery.com/topic/save-the-jquery-factory-reuse-it-in-frames-no-2nd-network-request to get the unit tests working in a similar situation but it seems to have stalled.

I think it may be a good idea to explicitly scope things to our internal window, especially for non-browser environments, but that is only part of the proposal.

Changed June 07, 2013 02:40PM UTC by gibson042 comment:5

Sending the top level IIFE frameElement && /^loader/.test(frameElement.name) ? parent : this instead of window, aside from the obvious concerns like "frameElement is not defined" and "WTF is 'loader'?", will screw with non-browser environments like jsdom.

Changed June 07, 2013 03:19PM UTC by jaubourg comment:6

I don't wanna raise the deads but wouldn't it be time to give newInstance another go? For those who never heard of it, the main jQuery closure was referenced as a newInstance method. So we had something like:

window.jQuery = ( function newInstance( window ) {

    var jQuery = { /*...*/ };

    jQuery.newInstance = newInstance;

    return jQuery;

} )( window );

It always creates a fresh new instance of jQuery (no plugins) and it was faster than sub while re-performing the support tests.

Bonus point: we could publish the newInstance main closure as an official npm module which would solve a lot of problems we have in that env.

Changed June 08, 2013 01:13PM UTC by diego.perini@gmail.com comment:7

@dave, thank your for that link, it shows there is a demand for that, very similar in scope to the changes proposed in this patch. As you have noticed these are simple scoping changes that will probably also benefit headless environments, and they are innocuous (tests always needed though).

Maybe there are others like those that I couldn't find during my tests.

The last diff line in that patch, related to the "frameELement" property, was unintentionally left in and should not be considered part of this request. It was just part of my testing and not yet part of this proposal.

@gibson042, can you tell me more about the "frameElement is not defined" error you get related to this standard property of the host browsing context ?

That line (pass "parent" instead of "window") would have effect only when explicitly loaded in an iframe having its name string starting with "loader".

My request was limited to explicitly scoping methods to the internal "window".

Though, since it slipped in, it would be good for me to have some feedback on that "frameElement" trickery, I currently have other alternatives and ideas for that.

Changed June 08, 2013 01:38PM UTC by anonymous comment:8

@jaubourg

that's the way I am currently using to retrieve the original source code by explicitly naming the IFE and saving it internally or externally somewhere.

The same could be achieve by getting the "arguments.callee" but that would be a violation when "use strict"; is enforced in user code.

Also in my current testing I am saving names, references and strings of code in an two level deeper property of the host context, namely I use "window.navigator.modules" as my namespace. This also leads to 0 globals.

While I am not sure this is everybody's objective, I swear I am trying to do my best to avoid breaking jQuery for others. I am sure both objectives are possible without too much effort.

Changed June 08, 2013 02:28PM UTC by diego.perini@gmail.com comment:9

Just wanted to say that the previous anonymous comment to @jaubourg is from me.

I forgot to set the user name and I am not able to change it.


Diego

Changed July 17, 2013 05:19PM UTC by diego comment:10

Here are the list of object types, global/window properties and methods that need to be explicitly scoped in code to allow new instances to work across browser contexts.

object_types = 'Boolean|Number|String|Function|Object|Array|RegExp|Date|Math|Error';

global_props = 'Infinity|NaN|undefined';

global_methods = 'eval|escape|unescape|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|parseInt|parseFloat|isFinite|isNaN';

window_props = 'closed|defaultStatus|document|frames|history|length|location|name|navigator|opener|parent|screen|self|status|top|innerHeight|innerWidth|outerHeight|outerWidth|pageXOffset|pageYOffset|screenLeft|screenTop|screenX|screenY';

window_methods = 'alert|blur|focus|open|close|confirm|prompt|print|moveBy|moveTo|resizeBy|resizeTo|scroll|scrollBy|ScrollTo|clearTimeout|setTimeout|clearInterval|setInterval';

If we had access to the original source of the generating Javascript code we would not need to explicitly scope each method/property, however explicitly scoping will allow extending jQuery with plugin/modules and have new instances include the needed plugin/modules.

Changed March 01, 2014 10:13PM UTC by dmethvin comment:11

resolution: → notabug
status: openclosed

It's interesting, but nobody's taken it up as a cause and I can also see possible issues with use in environments like node.js. Probably better if someone could experiment a bit and come up with compelling use cases.