Closed
Bug 1145058
Opened 10 years ago
Closed 10 years ago
SpeciesConstructor is broken without @@species support (breaking use of slice/subarray on typed arrays with a custom .constructor)
Categories
(Core :: JavaScript: Standard Library, defect)
Core
JavaScript: Standard Library
Tracking
()
RESOLVED
FIXED
mozilla39
Tracking | Status | |
---|---|---|
firefox38 | --- | unaffected |
firefox39 | + | fixed |
People
(Reporter: beingalink, Assigned: Waldo)
References
Details
(Keywords: regression)
Attachments
(1 file, 1 obsolete file)
3.24 KB,
patch
|
Details | Diff | Splinter Review |
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0
Build ID: 20150318055750
Steps to reproduce:
Visit https://instant.io and click the "Browse" button under "Start seeding". Then select a file.
Actual results:
Under "Log" the message "Creating .torrent file..." appears but nothing happens.
Expected results:
A hash should get generated for the file and seeding should start. I first filed a bug for the website but it appears to be a firefox bug: https://github.com/feross/instant.io/issues/22 A dev there assumes it to be related to a bug in the crypto.subtle api.
[Tracking Requested - why for this release]: recent regression.
Regression range:
good=2015-03-06
bad=2015-03-07
http://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=0189941a3fd5&tochange=43fb1f92e8d4
Alice, any idea about the suspected bug?
Status: UNCONFIRMED → NEW
status-firefox38:
--- → unaffected
tracking-firefox39:
--- → ?
Ever confirmed: true
Keywords: regression
Comment 3•10 years ago
|
||
Blocks: 1139759
Component: Untriaged → JavaScript: Standard Library
Flags: needinfo?(jwalden+bmo)
OS: Mac OS X → All
Product: Firefox → Core
Comment 4•10 years ago
|
||
Something changed with the way Uint8Array.prototype.subarray works and it broke the 'buffer' npm module which browserify uses (i.e. this Firefox change will break tons of sites, the Amazon AWS SDK, more...).
https://github.com/feross/buffer
I tried narrowing down the exact reason the tests started failing, but I'm having difficulty. If others want to take a look, here's how to run the test suite:
git clone git@github.com:feross/buffer.git
cd buffer
npm install
npm run test-browser-local
Copy the URL into Firefox Nightly and look at the console logs.
Updated•10 years ago
|
Assignee | ||
Comment 5•10 years ago
|
||
The first question is *how* it broke. The implementation is approximately as literal a translation from spec steps as possible. (Our previous implementation was not exactly the spec implementation, tho I'm not sure I could enumerate the exact differences.) If there's a problem, it may well be a spec problem.
I'll see what I can do, investigating now, but I may not be able to get to this until Tuesday. Given this landed a couple weeks ago, it shouldn't be the end of the world if it stays in another couple days.
Assignee | ||
Comment 6•10 years ago
|
||
I'm a bit pressed for time, but a skim of buffer source suggests the problem. The latest ES6 specs have this (I think unproven) conceit that the various typed array methods are subclass-ready. What this means is that the methods that take a typed array as this and produce a new typed array, do so approximately using |this.constructor|.
// Steps 18-20.
var defaultConstructor = _ConstructorForTypedArray(obj);
var constructor = SpeciesConstructor(obj, defaultConstructor);
It appears (I could be mistaken) you're calling subarray on a Buffer instance. A Buffer instance is a typed array, so that's fine. You'll get Uint8Array for the defaultConstructor line above.
function SpeciesConstructor(obj, defaultConstructor) {
var C = obj.constructor;
if (C === undefined) {
return defaultConstructor;
}
if (!IsConstructor(C)) {
ThrowError(JSMSG_NOT_CONSTRUCTOR, DecompileArg(1, C));
}
return C;
}
But then for the constructor, the above algorithm will give you back -- because Buffer values have .constructor === Buffer -- the Buffer function. And Buffer doesn't have the same signature as a typed array constructor has:
function Buffer (subject, encoding) {
Which suggests (although again, I'm not 100% certain, just going by inspection, quickly) we're invoking that, creating something that in no way matches what the caller wants (presumably a typed array and all), and things go south further along.
If the above analysis is correct -- and it might well not be, this is pretty quick -- the current subclassing scheme at least as regards typed arrays is not compatible with current shipping code. It's not clear to me whether current shipping code could be changed or not for this, if we wanted to stay the course on this.
Anyway. I'm out now, others can pick this up if they're around, or it can wait til Monday/Tuesday.
Flags: needinfo?(jwalden+bmo)
I think this would probably work again when SpeciesConstructor actually tried to look up @@species. I assume that would fail and we would just execute the defaultConstructor.
Comment 8•10 years ago
|
||
(In reply to Tom Schuster [:evilpie] from comment #7)
> I think this would probably work again when SpeciesConstructor actually
> tried to look up @@species. I assume that would fail and we would just
> execute the defaultConstructor.
That's right. If you are miss an essential step if you are not looking up @@species as shown in http://people.mozilla.org/%7Ejorendorff/es6-draft.html#sec-speciesconstructor. If you aren't ready to support @@species a more appropriate interim definition for SpeciesConstructor would be for it to always use defaultConstrutor.
Based upon a quick scan of Buffer.js it looks to me that fixing SpeciesConstructor should be enough to get the existing Buffer code to work (at least for subarray, I don't really look at other methods).
I think a version of Buffer that was an ES6 subclass of Uint32Array could be much simpler than the existing code. Such a version would over-ride @@species in exactly the way it was intended. That allows the subclass constructor to have a different signature from it superclass.
Comment 9•10 years ago
|
||
Jeff,
> It appears (I could be mistaken) you're calling subarray on a Buffer instance
Buffer is not a proper subclass of Uint8Array. The Buffer constructor actually just returns a Uint8Array that we've "augmented" with additional function properties so it looks/acts like a Buffer. It's just a Uint8Array.
Comment 10•10 years ago
|
||
Also, just want to emphasize that lots of sites will break if we don't figure out a solution to this (either by making Firefox behave like before, or fixing 'buffer' if that's even possible).
I would love to move Buffer to being a proper ES6 subclass of Uint8Array, but if this involves using new class syntax that breaks in older browsers, then we can't do it for a long time...
There are many users of browserify (and thus 'buffer') including Yahoo, Keybase, and more (https://github.com/substack/node-browserify/wiki/browserify-in-the-wild).
Comment 11•10 years ago
|
||
(In reply to Feross Aboukhadijeh from comment #10)
> Also, just want to emphasize that lots of sites will break if we don't
> figure out a solution to this (either by making Firefox behave like before,
> or fixing 'buffer' if that's even possible).
>
I'm pretty sure that a complete implementation of SpeciesConstructor within SpiderMonkey will fix the problem.
In the meantime, here is a possible work around. The ES6 specification for Uint8Array.prototype.subarray (actually it applies to all kinds of typed arrays) calls the three argument form of the typed array construcgtors (http://people.mozilla.org/~jorendorff/es6-draft.html#sec-%typedarray%-buffer-byteoffset-length ) on the "species constructor'. Because of the current SpiderMonkey SpeciesConstructor implementation it is new'ing Buffer instead passing the three arguments that Uin8Array would accept for that overload.
The work around is within the Buffer constructor, check if it was called with exactly three arguments. The first argument will be an ArrayBuffer instance, the other two arguments will be integers. If the argument signature matches that configuration you are probably being called from within subarray, so do
return new Uint8Array(arguments[0], arguments[1], arguments[2])
additional compatibility note: The old Kronos Typed Array spec. did not provide algorithms for most methods, so the inner workings of the typed arrays methods could vary from implementation to implementation. So, legacy implementations subarray may or may not have accessed the this value's constructor property and may or may not have called its three argument form.
>
> There are many users of browserify (and thus 'buffer') including Yahoo,
> Keybase, and more
> (https://github.com/substack/node-browserify/wiki/browserify-in-the-wild).
Comment 12•10 years ago
|
||
(In reply to Feross Aboukhadijeh from comment #10)
...
>
> I would love to move Buffer to being a proper ES6 subclass of Uint8Array,
> but if this involves using new class syntax that breaks in older browsers,
> then we can't do it for a long time...
I'm pretty sure you can "hand wire" a version of Buffer that followed the ES6 subclass conventions without using actual class syntax.
Assignee | ||
Comment 13•10 years ago
|
||
Blah, I made the assumption a method without spec step comments was the spec algorithm. :-( Sorry about that. Updated to spec algorithm, commented the steps we can't implement without @@species as being wrong, and changed to use defaultConstructor in its absence.
Feel free to land this if you review it earlier than I can get to it. My tree is a couple weeks old, still waiting on jorendorff to rebase it, so I will have a little pain if I have to land this myself.
Attachment #8583568 -
Flags: review?(evilpies)
Assignee | ||
Updated•10 years ago
|
Assignee: nobody → jwalden+bmo
Status: NEW → ASSIGNED
Comment 14•10 years ago
|
||
Comment on attachment 8583568 [details] [diff] [review]
Fix SpeciesConstructor to the spec algorithm, with a comment highlighting the spec not-following we must do, lacking @@species
Review of attachment 8583568 [details] [diff] [review]:
-----------------------------------------------------------------
Stealing, as per Waldo's request on IRC. APPROVED. r=me
::: js/src/builtin/Utilities.js
@@ +171,5 @@
> + ThrowError(JSMSG_NOT_NONNULL_OBJECT, "object's 'constructor' property");
> +
> + // Steps 6-7. We don't yet implement @@species and Symbol.species, so we
> + // don't implement this correctly right now. Somebody fix this!
> + var s = /* ctor[Symbol.species] */ undefined;
OK, this lets us type up as much of this as we can. Cool.
::: js/src/tests/ecma_6/TypedArray/slice.js
@@ +68,5 @@
> + mathConstructor.constructor = Math.sin;
> + assertDeepEq(mathConstructor.slice(4), new constructor(4));
> +
> + assertEq("species" in Symbol, false,
> + "you've implemented @@species -- add real tests here!");
ah, here's the test I was looking for. Good.
Attachment #8583568 -
Flags: review?(evilpies) → review+
Assignee | ||
Comment 15•10 years ago
|
||
Assignee | ||
Updated•10 years ago
|
Attachment #8583568 -
Attachment is obsolete: true
Assignee | ||
Updated•10 years ago
|
Keywords: checkin-needed
Hardware: x86 → All
Summary: Creating a torrent on https://instant.io doesn't work in current firefox nightly → SpeciesConstructor is broken without @@species support (breaking use of slice/subarray on typed arrays with a custom .constructor)
Version: 39 Branch → Trunk
Comment 16•10 years ago
|
||
Looks like this is about to land soon, but tracking anyway for 39 since this is a recent regression.
status-firefox39:
--- → affected
Comment 17•10 years ago
|
||
Flags: in-testsuite+
Keywords: checkin-needed
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla39
You need to log in
before you can comment on or make changes to this bug.
Description
•