I am not able to make child object from another module .... prototype seems to be stripped away

RESOLVED INVALID

Status

Add-on SDK
General
RESOLVED INVALID
8 years ago
8 years ago

People

(Reporter: Matěj Cepl, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(URL)

Attachments

(1 attachment)

3.88 KB, application/zip
Details
(Reporter)

Description

8 years ago
Created attachment 451740 [details]
reproducer

When I run the attached project and in the opened firefox I got to URL http://bugzilla.redhat.com/998 (the oldest open bug in the Red Hat Bugzilla), I get this output:

(jetpack-sdk)johanka:test-package$ cfx run -a firefox
++ date +%j
+ odd=0
+ '[' 0 -eq 1 ']'
+ setarch x86_64 /usr/bin/firefox -profile /tmp/tmpRdpeh9.mozrunner
info: Now we are inside!
info: this = [object Object]
info: location = https://bugzilla.redhat.com/show_bug.cgi?id=998
info: doc = https://bugzilla.redhat.com/show_bug.cgi?id=998
info: bug number = 998
info: this = [object Object]
info: prototype = undefined
info: constructor = function RHBugzillaPage(doc, config) {
    BZPage.call(this, doc, config);
    console.log("location = " + this.doc.location);
    this.bugId = util.getBugNo(this.doc.location.href);
    console.log("doc = " + this.doc.location);
    console.log("bug number = " + this.bugId);
    console.log("this = " + this);
    console.log("prototype = " + this.prototype);
    console.log("constructor = " + this.constructor);
    console.log("this.getURL = " + this.getURL);
    console.log("bug URL = " + this.getURL());
    console.log("Now we are outside!");
}
info: this.getURL = undefined
error: An exception occurred.
Traceback (most recent call last):
  File "resource://jid0-uxmbewgoltuuuqrhkhrr7hw3iqy-jetpack-core-lib/errors.js", line 49, in 
    return callback.apply(this, arguments);
  File "resource://jid0-uxmbewgoltuuuqrhkhrr7hw3iqy-jetpack-core-lib/tab-browser.js", line 257, in eventHandler
    callback(event.target.defaultView);
  File "resource://jid0-uxmbewgoltuuuqrhkhrr7hw3iqy-test-package-lib/main.js", line 54, in 
    var curPage = new construct(doc, config);
  File "resource://jid0-uxmbewgoltuuuqrhkhrr7hw3iqy-test-package-lib/rhbzpage.js", line 28, in RHBugzillaPage
    console.log("bug URL = " + this.getURL());
TypeError: this.getURL is not a function

-------------------------------------

The significant thing about this is that both prototype (and prototype.getURL) seem to be stripped away from the child object.
(Reporter)

Comment 1

8 years ago
Note, I am totally willing to accept that I am doing inheritance completely wrong but it is to the best of my knowledge plain implementation of what is suggested by both Flanagan and Crockford. So, if I am doing it wrong, it could be expected there will be another lot of Javascript newbies, who will do it wrong as well.

Note also, that I have tried to use api-utils.publicConstructor but the result was even worse than what I have here ... the same script finished even with "this.doc doesn't exist" error.

Comment 2

8 years ago
You're passing the wrong thing to util.heir() on line 36 of rhbzpage.js.  This line:

  RHBugzillaPage.prototype = util.heir(BZPage.prototype);

Should be:

  RHBugzillaPage.prototype = util.heir(BZPage);

That's because util.heir()'s parameter is the constructor to "inherit" from, not the constructor's prototype.  So when you pass BZPage.prototype to util.heir(), p == BZPage.prototype, so f.prototype is set to BZPage.prototype.prototype, which is undefined.  RHBugzillaPage's prototype is therefore set to an empty object with the wrong prototype.

When I make the change I mentioned above, console.log(this.getURL) prints the right thing, i.e., BZPage.prototype.getURL().

Also, I think you are confusing `prototype` for `__proto__`.  `prototype` is a property on constructors.  If you have a constructor F, F.prototype becomes the prototype of all instances created by F.  So F.prototype is like a template for all instances of F.  Instances don't have a `prototype` property.  So if you have an instance f of F, f.prototype is not F.prototype.  f.prototype is actually undefined.  SpiderMonkey gives you a way of getting to F.prototype from f through f's `__proto__` property.  In other words, f.__proto__ == F.prototype (unless you set f.__proto__ to a different object, which is possible).  So when you have this line in RHBugzillaPage():

  console.log("prototype = " + this.prototype);

It will always print undefined, since `this` is an RHBugzillaPage instance and not a constructor.

This isn't a bug in Jetpack or even with the use of Jetpack, so resolving invalid.
Status: NEW → RESOLVED
Last Resolved: 8 years ago
Resolution: --- → INVALID
(Reporter)

Comment 3

8 years ago
(In reply to comment #2)
> You're passing the wrong thing to util.heir() on line 36 of rhbzpage.js.  This
> line:
> 
>   RHBugzillaPage.prototype = util.heir(BZPage.prototype);
> 
> Should be:
> 
>   RHBugzillaPage.prototype = util.heir(BZPage);

Oh shoot ... talking about snatching defeat out of the mouth of victory.

> When I make the change I mentioned above, console.log(this.getURL) prints the
> right thing, i.e., BZPage.prototype.getURL().

Yes, it does.

>   console.log("prototype = " + this.prototype);

Yes, you are right ... that was hastily written testing call, which was obviously wrong. I know about the difference between __proto__ and prototype. It should be f.constructor.prototype, right? (well, it is actually the same as __proto__)

> This isn't a bug in Jetpack or even with the use of Jetpack, so resolving
> invalid.

Yes. Thank you very very much.
The Add-on SDK is no longer a Mozilla Labs experiment and has become a big enough project to warrant its own Bugzilla product, so the "Add-on SDK" product has been created for it, and I am moving its bugs to that product.

To filter bugmail related to this change, filter on the word "looptid".
Component: Jetpack SDK → General
Product: Mozilla Labs → Add-on SDK
QA Contact: jetpack-sdk → general
Version: Trunk → unspecified
You need to log in before you can comment on or make changes to this bug.