On Tue, 2016-03-22 at 18:27 +0000, Andrea Giammarchi wrote: > Thanks Giovanni, that would solve only if `GLocalFile` will still > implements everything monkey-patched on `Gio.File` otherwise the lie > is gonna be a disaster in terms of expectations: > > ```js > Gio.File.prototype.allFiles = function () { /* do something */ }; > Gio.File.new_for_path('/').allFiles(); // throws an error if it > doesn't inherit > ```
Right, that's exactly what you cannot do: they are separate objects, changing one does not affect the other. > To restate my concern: I would like to have instances implementing > interfaces be runtime aware of changes to such interfaces, otherwise > there's no way to patch upfront in a consistent way any prototype > which is not future proof or polyfill friendly, because you cannot > patch instances unless you wrap all of them, which is the Proxy mess > I've recently dropped due performance implications (faster on > bootstrap, catastrophic while running) That will require changes in gjs I am afraid. The code involved is in gi/object.cpp at object_instance_new_resolve() for object prototypes, and gi/interface.cpp at interface_new_resolve() for "interface" prototypes. The functions are called to "resolve" a property, that is, to make it lazily appear when the code is referencing it. One way to do so is to modify object_instance_new_resolve(), check if a property with that name exists on the interface object, then resolve to an accessor property that forwards to the interface. A little hackish, and probably with a lot of overhead to define the accessor property in C++, but it should work. > Is anyhow clearer what I am expecting? Yeah, I understand it won't > work now ... but at least I hope it's clear. > > Best Regards Cheers, Giovanni > > > > > > On Tue, Mar 22, 2016 at 6:05 PM, Giovanni Campagna <scampa.giovanni@g > mail.com> wrote: > > Ok, let's try a factual response... > > > > On Tue, 2016-03-22 at 17:24 +0000, Andrea Giammarchi wrote: > > > > There is not even any Gio.LocalFile known to JS. > > > > > > ```js > > > const a = imports.gi.Gio.File.new_for_path('./a.js'); > > > > > > // here the "now known to JS" Gio.LocalFile.prototype > > > Object.getPrototypeOf(a).shenanigans = true; > > > > > > const b = imports.gi.Gio.File.new_for_path('./b.js'); > > > > > > // all instances affected indeed > > > print(b.shenanigans); // true > > > ``` > > > > > > > It's not exposed in the GIR file, so there is never a prototype > > > object created in the first place > > > > Yes, there is a prototype object created. Every JS object with > > custom > > behavior has a custom prototype object in SpiderMonkey, that's just > > how > > it is. > > > > This prototype object is "GLocalFile", and it's stored in an > > invisible > > object that exists just to reference it, as well as other hidden > > classes that appear through GType but not through introspection. > > > > It's supposed to be mostly invisible, but it's unavoidable. > > > > > There is: > > > > > > ```js > > > const a = imports.gi.Gio.File.new_for_path('./a.js'); > > > // here the *shared* Gio.LocalFile.prototype > > > Object.getPrototypeOf(a); > > > ``` > > > > > > > In GJS, you can check if an object implements an interface with > > > myObj.constructor.implements(Gio.File). > > > > > > That's good to know, thanks, yet if you read first messages of > > this > > > thread it was about patching upfront and not at runtime. > > > I understand I can find at runtime pretty much anything I want, > > but > > > since there is an introspection ability, why are there > > undocumented > > > instances around with undocumented prototypes? > > > > > > Or better, why `Gio.File.new` creates something unrelated with > > > `Gio.File.prototype` or `Gio.File` methods ? > > > Since this super secret thing is easily leaked, why not fixing > > this > > > instead of saying that it shouldn't be known? > > > > You can't fix that. > > > > The truth is, Gio.File is a lie. > > Indeed, Gio.File.prototype.replace_contents !== > > (Gio.File.new_for_path('/foo')).replace_contents > > > > What it means is that Gio.File is an object that exists only to > > hold > > methods that quack like the actual interface methods, if you call > > them > > explicitly with say > > Gio.File.prototype.replace_contents.call(file, "bla") > > , but has nothing to do with the interface methods exposed on each > > object. > > > > The reason for this is that prototype inheritance is single, but a > > GObject class can have multiple interfaces, so there is no good > > place > > to put Gio.File.prototype on the prototype chain from file to > > Object.prototype (in a way that's generic and consistent with say, > > Gtk.Label and Gtk.Buildable). > > So what happens is that every class that also implements an > > interface > > will resolve all interface methods on its own prototype. > > > > In the Gtk.Label case, Gtk.Label implements Gtk.Buildable and > > Gtk.Widget implements Gtk.Buildable, both visible in the GIR, which > > means > > Gtk.Label.prototype.hasOwnProperty('custom_tag_start') === true > > and > > Gtk.Widget.prototype.hasOwnProperty('custom_tag_start') === true > > > > In the GLocalFile case, GLocalFile implements Gio.File, and we know > > that from GType at runtime, so > > window.<invisible > > name>.GLocalFile.prototype.hasOwnProperty('replace_contents') === > > true > > but you don't know that unless you poke at Object.getPrototypeOf > > > > Yes, this is very awkward if you monkey patch prototypes, but > > that's > > just how it is. > > > > > The reason I've asked is that I've discovered there are hidden > > > classes the GIR won't tell me, doesn't know, but **are** on my > > way. > > > > > > > I don't believe Spidermonkey would support overloading > > instanceof > > > for this > > > > > > `instanceof` is the most easily "overloaded" ( not actually > > > overloaded, it just checks > > > `rightSide.prototype.isPrototypeOf(leftSide)` ) operator which is > > why > > > I am asking if this would ever be solved. > > > > Now, if we tell a lie, we should at least be consistent about it, > > and > > that's why > > Gio.File.new_for_path('/') instanceof Gio.File > > should return true > > > > Checking the prototype would not work, but instanceof can be > > overloaded > > "properly", because after all we have access to the C API of SM and > > we > > can do what we want. > > > > Indeed, that's https://bugzilla.gnome.org/show_bug.cgi?id=587030 > > which has had patches for a while and probably needs a rebase, but > > would make the Gio.File lie less visible to programmers. > > > > Hope this clarifies the situation, and cheers, > > > > Giovanni
signature.asc
Description: This is a digitally signed message part
_______________________________________________ javascript-list mailing list javascript-list@gnome.org https://mail.gnome.org/mailman/listinfo/javascript-list