JS1k demo doesnt draw anything on the screen (Chrome does)
Categories
(Core :: Graphics: Canvas2D, defect)
Tracking
()
People
(Reporter: mayankleoboy1, Unassigned)
References
(Regression)
Details
(Keywords: regression)
Go to https://js1k.com/2018-coins/demo/3209
ER: demo
AR: only a purple-ish background is shown. Nothing else draws.
Uncaught TypeError: c.r is not a function
y https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
b https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript:2
reload https://js1k.com/2018-coins/demo/3209:113
<anonymous> https://js1k.com/2018-coins/demo/3209:115
3209 line 113 > injectedScript line 2 > eval:1:531
y https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
forEach self-hosted:203
b https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript line 2 > eval:1
<anonymous> https://js1k.com/2018-coins/demo/3209 line 113 > injectedScript:2
reload https://js1k.com/2018-coins/demo/3209:113
<anonymous> https://js1k.com/2018-coins/demo/3209:115
| Reporter | ||
Comment 1•3 years ago
|
||
Regression1 : The translucent circle becomes opaque white:
https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=02d875d4f7d769cd03be3175490377dc600355fe&tochange=cdd65df84242fa01e9b2c690fb9078d7fba46cb6
| Reporter | ||
Comment 2•3 years ago
|
||
Regression2 : Nothing is drawn on the screen.
2022-11-22T11:36:08.992000: DEBUG : Found commit message:
Bug 1728999 - Add simple WPT testcases for the CanvasRenderingContext2D.direction property. r=lsalzman
And remove failure annotations for a couple of existing tests that we now pass.
Depends on D142701
Differential Revision: https://phabricator.services.mozilla.com/D142702
2022-11-22T11:36:08.992000: DEBUG : Did not find a branch, checking all integration branches
2022-11-22T11:36:08.992000: INFO : The bisection is done.
2022-11-22T11:36:09.002000: INFO : Stopped
| Reporter | ||
Updated•3 years ago
|
Updated•3 years ago
|
Comment 3•3 years ago
|
||
Set release status flags based on info from the regressing bug 1728999
:jfkthame, since you are the author of the regressor, bug 1728999, could you take a look? Also, could you set the severity field?
For more information, please visit auto_nag documentation.
Comment 4•3 years ago
•
|
||
Re: "Regression2 : Nothing is drawn on the screen."
Uncaught TypeError: c.r is not a function
This is clearly what stops the drawing. But it's very strange; I don't know what the demo is doing that would be affected by bug 1728999.
It seems that the (bizarre, compressed) JS is setting up a bunch of one- and two-letter aliases for canvas2d methods/attributes, and for some reason after bug 1728999 it ends up with .r being an alias for .direction, whereas before it was an alias for .stroke().
If I simply comment out the webidl declaration of the direction attribute in CanvasTextDrawingStyles, and make no other changes, the regression is fixed.
So apparently, even though the example doesn't (as far as I can see) try to make use of .direction in any way, the act of exposing it on the canvas2d context somehow affects the "decoding" of the compressed/obfuscated code. Maybe it embodies some fragile assumptions about the properties that it expects to exist on the object? I'm afraid deciphering this looks way above my limited JS knowledge...
Comment 5•3 years ago
|
||
(In reply to Mayank Bansal from comment #1)
Regression1 : The translucent circle becomes opaque white:
https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=02d875d4f7d769cd03be3175490377dc600355fe&tochange=cdd65df84242fa01e9b2c690fb9078d7fba46cb6
This is a result of bug 1627014 "Implement CanvasRenderingContext2D.createConicGradient", which I guess the demo is trying to use, but something isn't working right. Setting canvas.createConicGradient.enabled to false should help.
Ideally, we'd have a non-obfuscated testcase showing what kind of conic gradient we're mishandling here, assuming that's what is going on.
| Reporter | ||
Comment 6•3 years ago
|
||
Using https://lelinhtinh.github.io/de4js/ , this is the unobfuscated code i get:
for (v in c) c[v[2] + [v[9]]] = c[v];
a.style.backgroundColor = "rgb(0, 0, 26)";
var E, l, I, S, C, O, A, M, w = a.width,
h = a.height,
e = w / 2,
t = h / 2;
T = new AudioContext, P = T.createOscillator(), P.connect(G = T.createGain()), G.connect(T.destination), P.start(), G.gain.value = 0.1;
function y(b, d, f, g, k, m, n, q, s, u) {
4 > s && (c.g(), c.strokeStyle = "rgb(140, 26, 255)", c.lineWidth = 1, c.moveTo(b, d), 2 < s && (c.strokeStyle = "rgb(255, 102, 254)"), (2 == s || 0) && (n /= 5, q /= 5), 0 == s && (c.strokeStyle = "rgb(255, 255, 254)"), c.aC(f, g, k, m), u && (c.strokeStyle = "rgb(255, 255, 254)", c.lineWidth = 4), c.r(), y(k, m, k + n, m + q, k + 2 * (n * Math.random()), m + 2 * (q * Math.random()), n, q, s + 1), y(k, m, k + n, m + q, k + 2 * (n * Math.random()), m + 2 * (q * Math.random()), n, q, s + 1))
}(function b() {
c.e(0, 0, w, h), E = [];
for (var d = 0; 25 > d; d++) A = 70 * Math.random() - 35, M = 70 * Math.random() - 35, E.push([e + A, t + M, e + A, t + M, A, M]);
C ? (S = E[0], P.frequency.value = 8500, y(e, t, O.pageX * Math.random(), O.pageY * Math.random(), O.pageX, O.pageY, S[4], S[5], 2, 1)) : P.frequency.value = 300, E.forEach(function (g) {
y(e, t, g[0], g[1], g[2] + g[4] * Math.random(), g[3] + g[5] * Math.random(), g[4], g[5], 0)
}), setTimeout(b, 150), W(e, t, 5, e, t, 25, c1 = "rgb(255, 255, 255)", c2 = "rgba(255, 25, 255,0.7)", 25), C ? W(O.pageX, O.pageY, 10, O.pageX, O.pageY, 55, c1 = "rgb(255, 255, 255)", c2 = "rgba(255, 25, 255,0.1)", 250) : W(e, t, 5, e, t, 250, c1 = "rgba(0, 0, 5,0.1)", c2 = "rgba(255, 255, 255,0.2)", 250)
})();
function W(b, d, f, g, k, m, n, q, s) {
I = c.ei(b, d, f, g, k, m), I.addColorStop(0, n), I.addColorStop(1, q), c.fillStyle = I, c.g(), c.arc(e, t, s, 0, 2 * Math.PI, false), c.fill()
}
a.onmousemove = b => {
O = b, C = c.PP(b.pageX, b.pageY)
};
Comment 7•3 years ago
|
||
Huh, I think both "regressions" here are actually the same kind of underlying issue. The "Regression1 : The translucent circle becomes opaque white" occurs because when createConicGradient is enabled, the demo ends up calling that function instead of its intended createRadialGradient (and of course the parameters it passes are not at all sensible for that).
Again, this call is happening through a shorthand "alias" that has apparently been defined by the obfuscated JS here, and when we expose the additional API createConicGradient, the alias accidentally ends up referring to that instead of the expected method. I'm guessing there's some kind of assumption about the properties present on the canvas2d context, and they're being indexed instead of looked-up by name, or something like that.
So I'm not sure this is actually a Firefox regression at all; I think it may simply be a script that makes too many fragile assumptions about the APIs.
Comment 8•3 years ago
|
||
This looks like the problem:
for (v in c) c[v[2] + [v[9]]] = c[v];
If I'm understanding correctly, this creates the "aliases" for all the properties of the canvas2d context, using character 3 and character 10 (if present) of the property name as the abbreviation.
So "stroke" is abbreviated as r.
But so is "direction", if it exists.
Similarly, "createRadialGradient" gets abbreviated as ei, but so does "createConicGradient".
Updated•3 years ago
|
Updated•3 years ago
|
Comment 9•3 years ago
|
||
I believe this is INVALID; the problem arises because the demo script creates abbreviated "aliases" of all the canvas2d attributes/methods in an unreliable way (comment 8).
Running
for (i in document.createElement("canvas").getContext("2d")) console.log(i[2] + [i[9]] + " => " + i)
generates a list of all the "abbreviations" that the demo script will end up creating, and comparing the results of this across Safari, Chrome and Firefox we can see that the exact content of the list, and the order in which they're generated, varies considerably:
Safari: Chrome: Firefox:
n => canvas n => canvas a => drawImage
bk => webkitBackingStorePixelRatio oh => globalAlpha g => beginPath
bg => webkitImageSmoothingEnabled op => globalCompositeOperation l => fill
be => webkitLineDash l => filter r => stroke
be => webkitLineDashOffset at => imageSmoothingEnabled i => clip
oh => globalAlpha at => imageSmoothingQuality PP => isPointInPath
op => globalCompositeOperation rl => strokeStyle PS => isPointInStroke
rl => strokeStyle l => fillStyle ee => createLinearGradient
l => fillStyle as => shadowOffsetX ei => createRadialGradient
at => imageSmoothingEnabled as => shadowOffsetY ei => createConicGradient
at => imageSmoothingQuality ar => shadowBlur et => createPattern
n => lineWidth ao => shadowColor eg => createImageData
n => lineCap n => lineWidth ta => getImageData
n => lineJoin n => lineCap ta => putImageData
tt => miterLimit n => lineJoin ts => setLineDash
nf => lineDashOffset tt => miterLimit ts => getLineDash
as => shadowOffsetX nf => lineDashOffset o => closePath
as => shadowOffsetY n => font v => moveTo
ar => shadowBlur x => textAlign n => lineTo
ao => shadowColor xi => textBaseline aC => quadraticCurveTo
n => font r => direction zv => bezierCurveTo
x => textAlign nn => fontKerning c => arcTo
xi => textBaseline nc => fontStretch c => rect
r => direction nn => fontVariantCaps c => arc
tt => getContextAttributes tc => letterSpacing l => ellipse
t => setAlpha xr => textRendering e => clearRect
ti => setCompositeOperation rn => wordSpacing l => fillRect
aF => drawImageFromRect i => clip rt => strokeRect
tC => setStrokeColor ei => createConicGradient v => save
tl => setFillColor eg => createImageData s => restore
td => setLineWidth ee => createLinearGradient l => fillText
tp => setLineCap et => createPattern rt => strokeText
ti => setLineJoin ei => createRadialGradient ax => measureText
ti => setMiterLimit aI => drawFocusIfNeeded a => scale
t => setShadow a => drawImage t => rotate
eo => clearShadow l => fill a => translate
a => drawImage l => fillText a => transform
g => beginPath tt => getContextAttributes to => getTransform
l => fill ta => getImageData to => setTransform
r => stroke ts => getLineDash ss => resetTransform
i => clip to => getTransform aI => drawFocusIfNeeded
PP => isPointInPath CL => isContextLost n => canvas
PS => isPointInStroke PP => isPointInPath zm => mozImageSmoothingEnabled
ee => createLinearGradient PS => isPointInStroke oh => globalAlpha
ei => createRadialGradient ax => measureText op => globalCompositeOperation
ei => createConicGradient ta => putImageData rl => strokeStyle
et => createPattern s => reset l => fillStyle
eg => createImageData u => roundRect l => filter
ta => getImageData v => save at => imageSmoothingEnabled
ta => putImageData a => scale n => lineWidth
o => closePath ts => setLineDash n => lineCap
v => moveTo to => setTransform n => lineJoin
n => lineTo r => stroke tt => miterLimit
aC => quadraticCurveTo rt => strokeText nf => lineDashOffset
zv => bezierCurveTo a => transform as => shadowOffsetX
c => arcTo a => translate as => shadowOffsetY
c => rect c => arc ar => shadowBlur
c => arc c => arcTo ao => shadowColor
l => ellipse g => beginPath n => font
ts => setLineDash zv => bezierCurveTo x => textAlign
ts => getLineDash e => clearRect xi => textBaseline
e => clearRect o => closePath r => direction
l => fillRect l => ellipse nn => fontKerning
rt => strokeRect l => fillRect
v => save n => lineTo
s => restore v => moveTo
l => fillText aC => quadraticCurveTo
rt => strokeText c => rect
ax => measureText ss => resetTransform
a => scale s => restore
t => rotate t => rotate
a => translate rt => strokeRect
a => transform
to => getTransform
to => setTransform
ss => resetTransform
aI => drawFocusIfNeeded
Note that in all cases, there are a number of duplicates, and the order in which they occur varies. I can't find any spec that requires a particular ordering here; it seems to be quite arbitrary.
So it seems to me like this was a "neat hack" for a minimized demo that happened to work for the symbols the script actually uses, but has always been at risk of breaking any time the canvas API is updated; and indeed, adding createConicGradient in Firefox caused the abbreviation for createRadialGradient to be overwritten, and then adding direction caused the abbreviation for stroke to be overwritten.
At some point, as APIs get updated, it'll probably break in other browsers as well.
Updated•3 years ago
|
| Reporter | ||
Updated•3 years ago
|
Updated•3 years ago
|
Description
•