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

Uncaught TypeError: InternalJsUtil.m_getLength__jsinterop_base_JsArrayLike is not a function #73

Closed
manstis opened this issue Aug 10, 2021 · 5 comments

Comments

@manstis
Copy link

manstis commented Aug 10, 2021

Hello @niloc132 sorry, but looking for advice again.

So, given the following:

It all compiles OK now but there is a runtime issue I do not understand:

Uncaught TypeError: InternalJsUtil.m_getLength__jsinterop_base_JsArrayLike is not a function
    at Function.m_getLength__$devirt__jsinterop_base_JsArrayLike (marshaller-api.js:73311)
    at JsNativeXMLReader.m_removeWhitespace__elemental2_dom_Node__elemental2_dom_Node (marshaller-api.js:635825)
    at JsNativeXMLReader.$ctor__org_treblereel_gwt_xml_mapper_api_stream_impl_JsNativeXMLReader__java_lang_String (marshaller-api.js:635675)
    at Function.$create__java_lang_String (marshaller-api.js:635668)
    at DefaultXMLDeserializationContext.m_newXMLReader__java_lang_String (marshaller-api.js:636016)
    at PMML__XMLMapperImpl.m_read__java_lang_String__org_treblereel_gwt_xml_mapper_api_XMLDeserializationContext (marshaller-api.js:647935)
    at PMML__XMLMapperImpl.m_read__java_lang_String (marshaller-api.js:647931)
    at Function.load (marshaller-api.js:4498)
    at marshaller-api.js:648264
    at Object.goog.loadModule (marshaller-api.js:1090)

The code InternalJsUtil.m_getLength__jsinterop_base_JsArrayLike is indeed not a function.

It is commented out in the J2CL input:-

class InternalJsUtil extends j_l_Object {
 /** @protected */
 constructor() {
  super();
 }
 // /** @return {Object<string, *>} */
 // native static m_emptyObjectLiteral__() 
...
  // /** @return {number} */
  // native static m_getLength__jsinterop_base_JsArrayLike(/** IArrayLike<?> */ obj)
... 

Here's the (Closure compiler input?) .impl.java.js files:-

impl.java.js files.zip

There's a "nice" getter method with a different name in the J2CL input for InternalJsUtil.impl.java.js but clearly something somewhere wants to use the commented out native method (assuming the comment is really a comment and there's not some wizardry going on I do not understand).

/**
 * @param {IArrayLike} obj
 * @return {number}
 * @public
 */
InternalJsUtil.getLength = function(obj) {
  return obj.length;
};

Do you know what's going on?

@manstis
Copy link
Author

manstis commented Aug 10, 2021

Oh, PS, you only need compile https://github.com/manstis/marshaller/tree/jaxb2-shading/marshaller-api and not the whole thing but, regrettably, for now you'll need to also compile this plugin locally: treblereel/mapper-xml#90

@manstis
Copy link
Author

manstis commented Aug 11, 2021

@niloc132 I've pushed a new commit that shows the problem appears to be with any use of JsArrayLike<T>.

@manstis manstis mentioned this issue Aug 11, 2021
@manstis
Copy link
Author

manstis commented Aug 11, 2021

OK.. so I know the issue. Yay... and it is not in the plugin nor any replaced dependency.

The issue is that my shaded JAR included the com.google.jsinterop:jsinterop-annotations and com.google.jsinterop:base implementations. Since they were no longer defined as dependencies the plugins dependency replacement mechanism was not triggering. Excluding them from my shaded JAR and adding as explicit dependencies resolves this issue.

I submitted a PR #74 showing it works OK.

I obviously leave it to you as to whether you choose to merge.

@manstis
Copy link
Author

manstis commented Aug 11, 2021

Closing..

However the mucky workaround of making a shaded JAR with some only limited dependencies flattened sure smells bad.

... IMO, and I say it again, if Maven's dependency exclusions were supported none of this would be needed.

@manstis manstis closed this as completed Aug 11, 2021
@niloc132
Copy link
Member

Shading jsinterop-base is the problem here, and shading it.

Google deliberately (for reasons I do not understand) will only make a jsinterop-base jar in maven compatible with gwt2, and will not make it work with j2cl. We had to hack in some "detect specific known broken dependencies that the ecosystem is stuck with" into the plugin, in the form of "dependency replacements", but this would be very difficult to modify to somehow handle any possible shaded configuration. We would need to a) somehow detect that it was shaded, to any possible package, and b) look for any past/present/future release of jsinterop-base and recognize that the code is bad and remove it.

The "real" solution is to give up on jsinterop-base, or to convince the maintainers to rewrite it so that it is compatible with both at the same time. Note that you won't have this problem in bazel, since they require bazel consumers to depend on a version of the code that is modified by a script before it is imported:

https://github.com/google/jsinterop-base/blob/3db256c87fea1b90786451b1814f6354bb39f370/java/jsinterop/base/BUILD#L32-L42

In theory that could be a different solution, encourage a "standardized" format like // J2CL_ONLY across the ecosystem for lines that only j2cl should see... but j2cl already has a custom GwtIncompatible stripper, and we've been told that this should be treated as an internal implementation detail.

I'm sorry that there isn't a more satisfactory answer than this.

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