-
-
Notifications
You must be signed in to change notification settings - Fork 654
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
[js] support creating extern classes by calling a constructor function without "new" keyword #3441
Comments
Let's see. Some suggestions. Regarding the "Type" functionalities I don't know how it would reflect on 2014-10-05 19:10 GMT-03:00 Dan Korostelev [email protected]:
[image: Imagem inline 1] |
IIRC, calling "new" in js creates an empty object, calls the constructor function with |
I think that independently of the inner workings the result of: var myref = new Class() Is the same. 2014-10-05 19:28 GMT-03:00 Dan Korostelev [email protected]:
[image: Imagem inline 1] |
Yeah, but can we safely use |
We should adapt it some way. 2014-10-05 19:45 GMT-03:00 Dan Korostelev [email protected]:
[image: Imagem inline 1] |
Is it a coding style difference or is there an actual runtime difference between the two ? |
I'm not sure. AFAIK, in JS if a constructor function returns an object, it will be used as a value of |
I believe they are quite equivalent. |
I don't really see the point of this either. Unless someone proves that there's a noticeable runtime difference I'm in favor of keeping the status quo. |
The problem still remains.
|
I might be misunderstanding the problem here. |
Actually for this issue to be solved, HaxeJS as a whole needs this feature. JQuery, Express and others libs can have this "new-less" instantiation.
|
I thought this was optional and you might as well use |
Simn is right. |
Yeah you can do |
They are not the same, but some library implementors write their constructors to be callable both ways: http://elegantcode.com/2010/12/21/basic-javascript-part-4-enforcing-new-on-constructor-functions/ I think this safety convention was started back in JQuery, but many (most?) modern libs these days don't bother. |
I don't think those libraries both work with |
Still I think the "noNew" meta is still necessary. 2014-10-06 11:23 GMT-03:00 Dan Korostelev [email protected]:
[image: Imagem inline 1] |
Calling with and without new are not the same. However, we are only interested in the case where a constructor function is called with new when it is supposed to be called without. In this case the object the function is returning must be the newly instantiated object, and according to new symantics in JavaScript: the returned object will be used instead of the newly created object by the new keyword. So effectively this will be the same result. Unless I am missing something this means we do not need a "noNew" meta, unless we are concerned about the extra object that gets allocated. |
But the user will need something like this if he wants to use Express. //Must be compiled to: 2014-10-06 13:05 GMT-03:00 Sam [email protected]:
[image: Imagem inline 1] |
What's wrong with var app = new require('express')(); ? Will give the same result. |
I tought it wouldn't work. 2014-10-06 13:16 GMT-03:00 Sam [email protected]:
[image: Imagem inline 1] |
It doesn't work in all instances ... sometimes you need to first assign the On Mon, Oct 6, 2014 at 10:21 AM, Eduardo Dias da Costa <
|
Yes sometimes it returns the "Class" var TheClass = require("theclass"); or it can be the instance. var ref = require("express")(); 2014-10-06 13:38 GMT-03:00 Franco Ponticelli [email protected]:
[image: Imagem inline 1] |
What's wrong with
being
? |
This case is ok.
|
with intrusive you mean to expensive? |
maybe it could only be checked if the class is extern? |
I don't think it would be significant, but we would have to add it in quite a few places. The same issue could crop up with overrides and I don't even want to start thinking about what happens when constrained type parameters get involved. I'm actually considering removing this feature entirely because it's so fragile. It might be better to apply native field names really early and somehow deal with field access, but that's just hacky as well. |
As a first step couldn't we just disallow unification of fields with @:native metadata with other types in general. Even if they have the same @:native metadata? |
For the record, I have a macro that brings support of |
@nadako I run into the selfCall problem over and over again when writing externs for gulp plugins, especially because they overload the function a lot. It would be very very helpful to have something like @:selfCall, because it would make the externs so much cleaner. |
btw. i used a valueOf hack before you dissallowed non valid js identifiers. But this doesn't work anymore ;) one example: @:jsRequire("gulp-watch") extern class GulpWatch
{
@:overload(function (glob:String, ?options:GulpWatchOptions, ?cb:Stream->?(Void->Void)->Stream):Stream {})
@:native("valueOf()") public static function watch (glob:String, ?options:GulpWatchOptions, ?cb:Stream->?(Void->Void)->Void):Stream;
} how would you write it without something like @:selfCall |
I would argue that this: @:jsRequire("gulp-watch") extern class GulpWatch
{
@:overload(function (glob:String, ?options:GulpWatchOptions, ?cb:Stream->?(Void->Void)->Stream):Stream {})
@:selfCall public static function watch (glob:String, ?options:GulpWatchOptions, ?cb:Stream->?(Void->Void)->Void):Stream;
} looks very clean compared to another solution. |
i know that you could use |
Try now :-) |
wow that's nice, thx a lot. I spotted one last problem with it. If you assign a function to a variable this is not working: var f = gulp.GulpWatch.watch; // generates var f = gulp.GulpWatch.watch; in js |
is this a problem with |
should be this line right? Line 526 in bae7da5
|
Yeah, i changed that in the |
what's the problem? |
no @:native works as expected, it was just a question without testing ;) |
thx |
so much better now ;) |
I lost track of what this issue is about. Can we just close it now? :) |
I'm not sure, we're originally talked about self-calling constructors while I added a |
Ok, I'll just assign it to you then! |
I was checking LuaXe, which has support for this feature ( public inline function new( arg ) {
return untyped __js__('MyClass')( arg );
} |
okay, now genjs supports @:jsRequire("myapp")
extern class MyApp {
@:selfCall function new();
@:selfCall function run():Void;
}
class Main {
static function main() {
var app = new MyApp();
app.run();
}
} generates: (function () { "use strict";
var MyApp = require("myapp");
var Main = function() { };
Main.main = function() {
var app = MyApp();
app();
};
Main.main();
})(); @clemos @frabbit or anyone who is working on externs please confirm that it's good enough. |
See #2784 (comment)
It seems that it's quite common in JS libraries that objects are created by simply calling a function instead of using "new SomeConstructor" syntax (e.g.
JQuery
,express
,socket.io
), so I think it makes sense for us to support that.The most straightforward way is probably to use metadata for the constructor field that simply makes JS generator omit the
new
keyword, i.e.But I don't really know to what extent is it compatible with e.g.
Type.createInstance
. @aduros, @clemos, @eduardo-costa any comments?The text was updated successfully, but these errors were encountered: