How is modifying _init() affecting parent()? - javascript

I'm trying to update a Gnome-shell extension. In it, I override the _init method of an object, which I'm doing like this:
function newInitAppSwitcherPopup() {
this.parent();
...
}
AltTab.AppSwitcherPopup.prototype._init = newInitAppSwitcherPopup;
The new method fails with:
JS ERROR: TypeError: The method 'parent' cannot be called
What I find very surprising here is that the parent method actually exists (if I change the name I get a "not defined" error).
What I don't understand is that the original AppSwitcherPopup._init is still using this call to parent (https://git.gnome.org/browse/gnome-shell/tree/js/ui/altTab.js?h=gnome-3-16#n54).
This was working well under Gnome 3.12, but is broken for Gnome 3.16...I guess they changed something in their GObject or inheritance models?

i have a similar code working for my config widget
const MenuConfigWidget = new GObject.Class({
Name: 'SimpleMenu.Prefs.MenuConfigWidget',
GTypeName: 'SimpleMenuMenuConfigWidget',
Extends: Gtk.Grid,
_init: function(params) {
this.parent({... });
...
}
});
Do you extend the class our just monkey patch the _init function?

Related

After GNOME Shell extension's monkey-patching, this.parent is unexpected

For the raise-activated GNOME Shell 3.16 extension I'm trying to monkey-patch the AppSwitcherPopup._finish method. Like the original, the patched version calls this.parent:
function _modifiedFinish(timestamp) {
// ...monkey-patched code...
this.parent(timestamp);
}
function enable() {
_originalFinish = AltTab.AppSwitcherPopup.prototype._finish;
AltTab.AppSwitcherPopup.prototype._finish = _modifiedFinish;
}
(full code)
But I get this stack trace in the console (from running gnome-shell --replace):
(gnome-shell:24452): Gjs-WARNING **: JS ERROR: TypeError: The method '_keyReleaseEvent' is not on the superclass
_parent#resource:///org/gnome/gjs/modules/lang.js:129
_modifiedFinish#/home/lastorset/.local/share/gnome-shell/extensions/Alt_Tab_Mod_Only_Raise_Activated_Window#dsboger.com.br/extension.js:34
SwitcherPopup<._keyReleaseEvent#resource:///org/gnome/shell/ui/switcherPopup.js:199
wrapper#resource:///org/gnome/gjs/modules/lang.js:169
In this case, SwitcherPopup._keyReleaseEvent is calling this, and this should be an instance of the AppSwitcherPopup subclass. I believe this.parent should be the same after patching—why is it now trying to call the caller? And for that matter, why doesn't that succeed?
I looked up the GJS code that generated this.parent, but I can't quite spot what's missing.
After digging a bit more I found a way to fix it. In the GJS class model, the parent function is actually looking for the method's owner's superclass in order to call the method of the same name. Looks like every GJS class has a wrapFunction helper that sets _owner. I used that to patch the function instead:
AltTab.AppSwitcherPopup.prototype._finish = AltTab.AppSwitcherPopup.wrapFunction('_finish', _modifiedFinish);

cant call function in another dojo module from dojo module

I'm having trouble calling a method from my dojo module in another dojo module. The code of my calling module is:
define([
"Templates/MarkTicket",
"DataTypes/MarkTicketForm_Data",
"DBCalls/MarkTicketDB",
...], function (MarkTicket, MarkTicketForm_Data, MarkTicketDB, ...
) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
postCreate: function () {
//both modules have Test Method
MarkTicketDB.Test("call from MarkTicketForm");//works great
MarkTicket.Test("call from MarkTicketForm");//object doesnt support property or method test
},
...
});
});
The call to Test in MarkTicketDB works just fine, but I get the error shown in the code comment when I try to call Test method in MarkTicket. MarkTicket only shows a Createsubclass and extend method when I debug. The module I'm calling these methods from is also located in the Templates directory -- could this be the problem? (I've also tried defining Templates/MarkTicket as just MarkTicket in the define statement)The Templates package is defined in my main page
Any ideas?
Thanks
As I said in my comment I think the problem may be that my calling module (MarkTicketForm) is a dijit dialog that is instantiated and opened through MarkTicket here is the code:
MarkTicket:
...
postCreate: function () {
MT = new MarkTicketForm();//instaniate MarkTicketForm inside MarkTicket
}
...
//call a Method in MarkTicket Form to open the dialog
MT.showForm(TicketInfo);
...
MarkTicketForm (code to show dialog):
...
showForm: function (ticketInfo) {
ID = ticketInfo.ID;
var DateRcvd = this.formatDate(ticketInfo.DateRcvd);
this.lblID.innerHTML = ticketInfo.ID;
this.lblTicket.innerHTML = ticketInfo.Ticket;
this.lblRcvd.innerHTML = DateRcvd;
this.lblType.innerHTML = ticketInfo.TicketType;
this.myDialog.show();
},
...
Like g00glen00b said, you should have listed the code for MarkTicket. However, since you said that:
MarkTicket only shows a Createsubclass and extend method when I debug.
...it's clear that MarkTicket is a class created through dojo.declare().
Presumably Test() is an method on MarkTicket instances, not on the MarkTicket class itself. Therefore, you could do something like this:
var m = new MarkTicket();
m.Test("call from MarkTicketForm");

extending an object with new functions in Javascript

Basically Dub and Dub.socialize objects already exist as an included library. I'm trying to extend the library with some additional custom functions that I created.
I attempted the following concept below:
Dub.socialize = {
setUID : function(preUID, postUID)
{
// .. function code here
}
}
However, I receive the following error "Uncaught TypeError: Cannot set property 'setUID' of undefined" from my console.
Obviously my knowledge of objects is a bit misled. What would be the proper method of extending this function into the already existing object library?
A simple solution could be
Dub.socialize.setUID = function(preUID, postUID) {};
Try this:
Dub.socialize.prototype.setUID = function(preUID, postUID) {
...
};
Object Constructor and prototyping
Edit: Realized you're working with a "static" object. This only works for something that is instantiated, and since you're not making new instances, this doesn't apply.
If you are going to create the function for declared object means then you have to use "prototype" keyword for example.
`var Dub = {
socialize: new Object()
};
Dub.socialize.prototype.setUID = function(preUID, postUID) {
// Function Body
};`
http://www.javascriptkit.com/javatutors/proto3.shtml

dojo 1.9: what annotation does declare.safeMixin add?

I have been reading through the dojo 1.9 documentation about declare.safeMixin(), focusing on the difference between it and lang.mixin.
Here is the explanation I found...
safeMixin() is a function defined in dojo/declare. It has the same functionality as dojo/_base/lang::mixin(), but additionally it annotates all copied methods compatibly with dojo/declare. This decoration can affect how this.inherited() works in mixed-in methods.
I can follow the example but it doesn't really explain exactly what is added and where, can anyone give any further examples of what annotation is added to each copied method?
So to be clear, I'm not asking for an explanation of inheritance, I'm just asking specifically about the annotations added by using declare.safeMixin() instead of lang.mixin.
Using safeMixin allows you to mix functions into an instance that can take advantage of this.inherited the same way that prototype methods defined using declare can.
For example, the following will log 2 messages:
require([
"dojo/_base/lang",
"dojo/_base/declare"
], function(lang, declare){
var A = declare(null, {
method: function () {
console.log('method in prototype');
}
});
var a = new A();
declare.safeMixin(a, {
method: function () {
this.inherited(arguments);
console.log('method in instance');
}
});
a.method();
});
Without safeMixin, you wouldn't be able to call this.inherited(arguments) from the overriding method (at least, not without additional parameters) - you'd end up getting an error:
Error: declare: can't deduce a name to call inherited()
safeMixin adds the nom property to functions that are mixed in to the target. This property is set to the key from the source object that the function was assigned to. e.g. if you call declare.safeMixin(target, { foo: function() {} }), the nom property for that function is "foo". This is necessary for this.inherited(arguments) to automatically figure out that it should call the parent "foo". The alternative to using safeMixin would be to explicitly specify the name of the parent function: this.inherited('foo', arguments);.

JSON.stringify missing superclass properties when using a subclass with Spine

I'm seeing strange behaviour using JSON.stringify against a subclassed model in Spine, and I'm hoping someone can help!
Here's a simplified excerpt from some code that we've got on one of our projects:
define([
"jquery",
"underscore"
],
function ($, _) {
var SuperClass = Spine.Model.sub();
SuperClass.configure("SuperClass", "SuperClassProperty");
var SubClass = SuperClass.sub();
SubClass.configure("SubClass", "SubClassProperty");
var instance = new SubClass({ SuperClassProperty: "Super", SubClassProperty: "Sub" });
console.log(instance);
var json = JSON.stringify(instance);
console.log(json);
});
The "console.log(instance)" is printing out exactly what I would expect in this scenario:
result
SubClassProperty: "Sub"
SuperClassProperty: "Super"
cid: "c-0"
__proto__: ctor
However, when I use JSON.stringify against the instance, this is all that I am returned:
{"SubClassProperty":"Sub"}
Why doesn't the SuperClassProperty get included in the stringify?
I've ruled out a problem with the JSON.stringify method by forcing JSON2 to override Chrome's native JSON object; both implementations yield the same result. It looks like stringify will delegate to the "toJSON" function on the object if there is one - and in this case there is (as part of Spine).
So it looks like either (a) this is a bug in Spine, or (b) I'm doing something incorrectly, which is the more likely option.
I know I can work around this problem by re-configuring the superclass properties on the subclass as well:
SubClass.configure("SubClass", "SuperClassProperty", "SubClassProperty");
However this seems counter-intuitive to me (what's the point of subclassing?), so I'm hoping that's not the answer.
Update: I've done some debugging through the Spine source code, and from what I can tell the problem is the way that I'm configuring the subclass:
var SubClass = SuperClass.sub();
SubClass.configure("SubClass", "SubClassProperty");
Calling "configure" here appears to wipe out the attributes from SuperClass. The "toJSON" implementation on the Model prototype is as follows:
Model.prototype.toJSON = function() {
return this.attributes();
};
Since the attributes collection is reset when SubClass is configured, the SuperClass properties don't come through in the JSON string.
I'm not sure if I shouldn't be calling "configure" on subclassed objects, but I can't find anywhere in the documentation that says I should be doing something else - this is the only reference I can find for subclassing Models (from: http://spinejs.com/docs/models):
Models can be also be easily subclassed:
var User = Contact.sub();
User.configure("User");
As I suspected, the problem was in the way that I'm using Spine. This comment from the author of Spine infers that using "configure" on a subclass will wipe out the attributes of the superclass. I have to admit I don't understand why this is; it seems counter-intuitive to me, but at least I now know that it's not a bug.
In case anyone else runs into this issue, the way I've worked around it is by adding my own extension method to the Spine Model as follows:
(function () {
var Model = Spine.Model;
Model.configureSub = function () {
var baseAttributes = this.attributes.slice();
this.configure.apply(this, arguments);
this.attributes = baseAttributes.concat(this.attributes);
return this;
};
})();
Now to configure my subclass:
var SubClass = SuperClass.sub();
SubClass.configureSub("SubClass", "SubClassProperty");
And now my JSON correctly reflects the properties from both the super and subclasses.

Categories

Resources