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

Support for multiple window contexts for globals #4

Open
my2iu opened this issue Jun 14, 2018 · 3 comments
Open

Support for multiple window contexts for globals #4

my2iu opened this issue Jun 14, 2018 · 3 comments

Comments

@my2iu
Copy link

my2iu commented Jun 14, 2018

This is sort of obscure, but it would be nice to have support for the same classes existing in different global window contexts. For example, if you have an iframe, it will have its own set of global system classes in its own window object. Sometimes, you need to construct objects from this separate context or do weird comparisons etc.

// Example JS code of different system classes
// How can this be done in JsInterop?
a = new iframe.contentWindow.Date()
b = new Date()
a.constructor === b.constructor   // returns false

Whatever pattern you come up with for that might also be useful when running JavaScript code inside Java because in that case, you might have multiple JavaScript contexts, and you need to specify which JS context you are constructing objects in.

JSInterpreter jsInterpreter1 = new JSInterpreter();
JSInterpreter jsInterpreter2 = new JSInterpreter();
jsInterpreter2.create(Int8Array.class, 10);
@jDramaix
Copy link
Member

jDramaix commented Jun 14, 2018

I don't test the code but I think the code below could work:

import elemental2.core.JsDate;
import elemental2.base.JsConstructorFn;

@JsType(isNative = true)
interface HasDateCtor {
  @JsProperty(name = "Date")
  public JsConstructorFn<JsDate> getDateCtor();
}

//...
JsDate a = ((HasDateCtor)iframe.contentWindow).getDateCtor().construct();
JsDate b = new JsDate();

you could even add default method newDate() on the interface and invoke it directly:

 @JsOverlay
 default JsDate newDate() {
   return getDateCtor().construct();
 }

JsDate a = ((HasDateCtor)iframe.contentWindow).newDate();

Like I said I didn't test the code but this is what came first to my mind.

@my2iu
Copy link
Author

my2iu commented Jun 14, 2018

Possibly. It's all dependent on the output of J2CL, and I don't have access to that. In any case, the proposed workaround starts getting messy when working with namespaced system classes like Intl.Collator or something.

I was thinking of having an explicit method in jsinterop.base.Js like

public static <T> JsConstructorFn<T> asConstructorFnInContext(Class<T> clazz, @DoNotAutobox Object base) { ... }

that would magically work when used like this:

Js.asConstructorFnInContext(Intl.Collator.class, iframe.contentWindow);

And maybe there could also be a version that explicitly invokes the constructor as well

public static <T> JsConstructorFn<T> constructInContext(Class<T> clazz, @DoNotAutobox Object base, @DoNotAutobox Object... args) { ... }

Though I'm not sure if J2CL changes would be needed to get something like that to work.

With a Js method like that, you could use an iframe to load up some code and define some classes, like GWT. And you could reach in there and create objects from those classes without needing to create a whole bunch of separate factory classes.

@my2iu
Copy link
Author

my2iu commented Jun 14, 2018

Oh, it would also be good if this worked with JS Interop interfaces that represent JS classes too. I'm not sure if J2CL already does this or not.

@JsType(isNative=true,namespace="maps") interface MapMarker { ... }

MapMarker obj = Js.constructInContext(mapIframe.contentWindow, 
     MapMarker.class, 37.42, -122.08);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants