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 ``` 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) 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 On Tue, Mar 22, 2016 at 6:05 PM, Giovanni Campagna < scampa.giova...@gmail.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
_______________________________________________ javascript-list mailing list javascript-list@gnome.org https://mail.gnome.org/mailman/listinfo/javascript-list