-
-
Notifications
You must be signed in to change notification settings - Fork 59
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
Can't Extend Native Classes with ES6 #818
Comments
@vbresults can we have a snippet that we can use to reproduce the case? |
class Delegate extends UIResponder implements UIApplicationDelegate {
public static ObjCProtocols = [UIApplicationDelegate];
applicationDidReceiveRemoteNotification(application: UIApplication, userInfo: NSDictionary<string, any>) {
// ...<snip>
}
// ...<snip>
}
const application = require("application");
application.ios.delegate = Delegate; |
Hi @vbresults, are you getting any errors while building/running? |
@vbresults - this looks like it should be working as expected. The This article might be helpful in resolving the case: https://docs.nativescript.org/core-concepts/application-lifecycle#ios-uiapplicationdelegate I don't see you calling the |
@tdermendjiev Yes, the error is that Delegate is not a native class but instead a JS function. |
@vbresults it would be useful if you provide the exact error with the stack trace as well as the whole content of the js file. |
@tdermendjiev It's triggered by this line in UIApplicationMain(0, null, null, iosApp && iosApp.delegate ? NSStringFromClass(iosApp.delegate) : NSStringFromClass(Responder)); NSStringFromClass expects a class but instead it's getting a JS function. My guess is that NS uses some sort of built-in __extends function which does not affect ES6+ native extends. Make sure |
@vbresults I managed to reproduce the issue and indeed its related to the __extends function implemented by the ios runtime. ES6 extends has a different behavior and it doesn't call runtime's __extends. That said, ES6 is not supported by both the iOS and Android runtimes. We don't plan supporting ES6 in the near future. |
@tdermendjiev That's unfortunate. Native ES6 does not have some of the limitations that __extends does (specifically around inheritance and calling context); ES6 really helps to clean up my code. |
@vbresults ES6 support will certainly become more demanded and we will have to support it at one point. By saying that we do not plan it for the near future our point is that we do not plan it for the upcoming two or three releases of NativeScript. If the demand for it increases, we will escalate its implementation. |
+1 es6+ is definitely where the industry is going. Any updates on this? |
Ran into this tonight. With the recent updates to the android runtime to use the updated V8 versions. I've been running many apps with the tsconfig outputting Is the issue in the JSCore side? Curious how that works 😄 |
I have both good and bad news regarding this issue. The good one is that I managed to come up with a workaround for now, and bad is that we still haven't planned to invest time in making it work automatically. const Del = (UIResponder as any).extend({
applicationDidBecomeActive(application: UIApplication): void {
console.log("applicationDidBecomeActive", application);
}
}, {
protocols: [UIApplicationDelegate]
});
import * as application from 'application';
application.ios.delegate = Del;
application.run({ moduleName: 'app-root' }); This snippet casts the base class to One of the approaches for adding such support that I was thinking of was to provide a function attached to the global object, that has to be called manually for each class which extends a native class. For example something like this: class Delegate extends UIResponder implements UIApplicationDelegate {
public static ObjCProtocols = [UIApplicationDelegate];
applicationDidReceiveRemoteNotification(application: UIApplication, userInfo: NSDictionary<string, any>) {
// ...<snip>
}
// ...<snip>
}
__ns_extend_native(Delegate, UIResponder); Maybe we can log a new feature request for that, if you think that this idea is good. |
@mbektchiev helpful idea - I just came across this today as well. I like your suggestion however perhaps instead of a rather obj-c'y kind of name like There's probably a whole bunch of convenient helpers to help {N} developers built on top of native apis therefore I'd suggest something like this:
If there were a large enough amount of helpers just for native api targeted work I'd suggest a new barrel just for those specific helpers even. Ideally the entire
/cc @bradmartin thoughts ^ |
I definitely lean toward the naming @NathanWalker mentions. I'd never know or think to look for Also the imports off of Off topic question slightly, does webpack remove anything from global if not used? |
I agree with the concerns for Having said that I really like the idea to provide a more JS-friendly wrapper in the modules for the new function and not force developers to write the whatever-cumbursome-underscored-function-name we come up with. I think it would be a major breaking change to remove all of these properties from |
Ahhh good to know about the existing C functions being on global. If that is consistent then it makes sense to stay consistent. Having those methods exposed in core-modules should provide a few benefits: no need to create a declaration that defines all the global methods available, more JS friendly for development workflow. Of course, the exported methods from core-modules can just call the global method it's aligned with. I'm not sure how "testable" that is but I imagine it's possible. As for the having |
Makes sense @mbektchiev - I was under impression that If the method is just JS makes sense of course as an exported method from {N} framework barrels and not on global scope. I like native classes part of global scope with {N} actually, never bothered me. However perhaps I was missing something with your suggestion of |
I was extending Array and realized NS always wanted to target es5, then look up on GG to see if ES6 is supported, then led here. Would be nice if the team could provide some context to point out the limitation of the platform and how it connects to this incapability of supporting ES6. Atm, it feels much like a black box: "no you don't do it, that's all". |
I have been going nuts for 3 days trying to figure out why the Protocol based class in my TypeScript plugin would not work. While the vanilla js version did work. And just by coincidence I stumbled upon this issue here. After applying the workaround mentioned by @mbektchiev it finally worked! This should be posted on the documentation for subclassing objc classes. The example written there does not work: https://docs.nativescript.org/core-concepts/ios-runtime/how-to/ObjC-Subclassing#typescript-support |
Hi @manijak, thank you for bringing our attention to this inconsistency in the documentation and sorry for the inconvenience this has caused you. We'll update the article with a short notice about the problem and a link to this issue. |
Is ES6 going to actually be addressed? Using ES6 is no longer optional, but essential in 2019! The workaround to use TypeScript and compile it to ES5:
|
It actually should be possible to switch to ES6 support now with the only drawback that you'll have to do this trick whenever you need to extend a native class in your TS code. Other than that, we may be able to introduce the |
@mbektchiev Thank you for your response. This here is not a major issue and I can see why it's not a priority, but I know there are other problems that delay the support for ES6. It's a shame given that you created your premises - both JSCore and your V8 version support much newer features, so it's not the core runtime that is the blocker anymore. For example, we are required to deliver ES6 code, and I can't simply use ES6 JavaScript modules inside NativeScript without having to transpile them with tsc, which complicates the build process and increases the development time. |
This comment was marked as abuse.
This comment was marked as abuse.
actually would love to see that one too. For me this important to have es2015 target in my tsconfig. right now.you need es5 to get __extends for native inheritance. but it means you loose native async/await and other features. |
I work with JS Code only and need to extend NSObject for implementing own UITextFieldDelegate. ES6 approach: How to apply the hack for TS transpiler above to pure JS code? |
This comment was marked as abuse.
This comment was marked as abuse.
@NathanaelA: thanks, got it. TS notation confused me... Got it working that way in ES6:
|
@NickIliev What is the status of this? |
====== Assertion failed ======
|
From @vbresults on November 6, 2017 11:22
I ran into this when setting a delegate in my project which is TypeScript compiled down to ES6. The problem would be that application.js expects a native delegate object while it's a JS function in ES6.
Copied from original issue: NativeScript/NativeScript#5038
The text was updated successfully, but these errors were encountered: