Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

instanceof with multiple windows/iframes #5886

Closed
MarZl opened this issue Jan 13, 2015 · 15 comments

Comments

Projects
None yet
5 participants
@MarZl
Copy link

commented Jan 13, 2015

Hey,
I experienced an issue with the raycaster, when using multiple windows/iframes.
In my case objects instanceof Array === false in intersectObjects failed.
Object.prototype.toString.call( objects ) !== '[object Array]' works as expected.

This effect is described here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jan 16, 2015

Uh! Do you mind explaining a bit more what's happening?

@andre161292

This comment has been minimized.

Copy link

commented Jan 16, 2015

The problem with instanceof is, that every environment (every iframe, frame, window) has it's own internal classes (Array, Object, etc.). So if you have an environment, where var a is an Array, in the top environment, and you test for a instanceof iframe.contentWindow.Array, it returns false - and vice versa.

It's different for loaded scripts:
If you load the same library in both environments and test, for example, if a instanceof THREE.Texture and a instanceof iframe.contentWindow.THREE.Texture, it will return true for both expressions.

A good explanation can be found here: http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jan 20, 2015

If you load the same library in both environments and test, for example, if a instanceof THREE.Texture and a instanceof iframe.contentWindow.THREE.Texture, it will return true for both expressions.

And, isn't this the expected behaviour?

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jan 20, 2015

Oh wait. So you're trying to use the library that you're loading inside an iframe from outside?

@MarZl

This comment has been minimized.

Copy link
Author

commented Jan 24, 2015

Exactly. That's why instanceof Array isn't working as intended.

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Jan 24, 2015

That's a very strange use case. I'm not sure the whole library should get more unreadable because strange use cases...

@thure

This comment has been minimized.

Copy link

commented Apr 8, 2015

The use of instanceof also precludes creating custom classes that have instances of any THREE classes as properties and using those instances with other classes that check type that way, the same principle discussed on SO.

e.g. If you have an arbitrary class Rain with a property Rain.mesh that's an instance of THREE.Object3D created during construction, you can't add it to a THREE.Scene that belongs to an instance of a different class because it fails the instanceof THREE.Object3D check, even though it was created with that constructor.

It'd make writing abstractions over THREE easier if type checking were less strict, i.e. compared an instance's type property instead of instanceof THREE.<class>, but I haven't looked into the negative consequences of making such a change.

@kumavis

This comment has been minimized.

Copy link
Contributor

commented Apr 8, 2015

@mrdoob I agree that the particular usecase is uncommon, but the instanceof problem rears its head in a few different places. As @thure said, this problem makes it difficult for others to build modules/libraries on top of three.js and get them to play nice together (your object is not an instanceof my Object3D). Substack suggested using a feature-detection pattern instead to overcome this.

@mrdoob

This comment has been minimized.

Copy link
Owner

commented Apr 8, 2015

The consequences of not being so strict is (not forcing instanceof THREE.Object3D) is that avoiding breakage from version to version would be (even) more difficult. Changing to the API would be more tricky because users would be using it in ways I couldn't foresee and more people will get mad.

@kumavis

This comment has been minimized.

Copy link
Contributor

commented Apr 9, 2015

Not making more people mad is a good motivation.

That said, I'm going to move away from this particular issue which is originally focused on

var iframe = document.getElementsByTagName('iframe')[0]
window.Array !== iframe.contentWindow.Array

However, shims for Array.isArray are readily available

@mrdoob

This comment has been minimized.

Copy link
Owner

commented May 14, 2015

As the original issue mainly referred Array I guess we can just use Array.isArray() instead?

@kumavis

This comment has been minimized.

Copy link
Contributor

commented May 14, 2015

@mrdoob that sounds good to me
enable 'obsolete browsers' to get a better idea of compat on older browsers
http://kangax.github.io/compat-table/es5/#Array.isArray

@andre161292

This comment has been minimized.

Copy link

commented May 15, 2015

I think we're at cross-purposes. If the issue would only reffer to Arrays, this solution would be fine, but it isn't.
The main problem is, that we cannot identify, if a specific instance is the instance of a specific class of ThreeJS.

@mrdoob

This comment has been minimized.

Copy link
Owner

commented May 15, 2015

@andre161292 Doesn't your use case gets solved by just doing var THREE = window.contentWindow.THREE? from within the iframe?

@mrdoob

This comment has been minimized.

Copy link
Owner

commented May 15, 2015

Fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.