Closed softvision-oana-arbuzov closed 5 years ago
Searching online, this TypeError: "CSS2Properties doesn't have an indexed property setter for '0'"
error seems to be something people run into with React from time to time. Sure enough, that seems to be the case here. It's failing in this initializer:
}), V = a(p.prototype, "onResize", [Y.action], {
enumerable: !0,
initializer: function() {
var e = this;
return Object(J.debounce)(250, function() {
var t = {
desktop: Z.d,
largeDesktop: Z.g,
mobile: Z.i,
mobileOnly: Z.j,
tablet: Z.n,
tabletLandscape: Z.o
};
Object.keys(t).forEach(function(e) {
var n, r = t[e].replace(/@media\s+/, "");
t = oe({}, t, (n = {}, n[e] = window.matchMedia(r).matches, n))
}), e.setStateDeprecated({
isMediaQueriesSet: !0,
viewport: oe({}, e.viewport, {
height: window.innerHeight,
width: window.innerWidth
}),
mediaQueries: oe({}, e.mediaQueries, t)
})
})
}
})
I noticed that commenting out the two "media queries" lines un-broke the page, but I couldn't find any obvious leads from the top down, so I started from the bottom of the stack trace.
This is the function where it's failing (with an auxiliary function):
function it(e, t) {
e = e.style;
for (var n in t)
if (t.hasOwnProperty(n)) {
var r = 0 === n.indexOf("--"),
o = ot(n, t[n], r);
"float" === n && (n = "cssFloat"),
r ? e.setProperty(n, o) : e[n] = o
}
}
function ot(e, t, n) {
return null == t || "boolean" === typeof t ||
"" === t ? "" : n || "number" !== typeof t ||
0 === t || Vi.hasOwnProperty(e) &&
Vi[e] ? ("" + t).trim() : t + "px"
}
It's bombing on the e[n] = o
part (effectively element.style["0"] = undefined
)
This is the object where the 0
property comes from:
Object {
0: undefined
bottom: 0
left: 0
marginBottom: 0
marginLeft: 0
marginRight: 0
marginTop: 0
paddingBottom: 0
paddingLeft: 0
paddingRight: 0
paddingTop: 0
position: "absolute"
right: 0
top: 58
<prototype>: Object
}
These are the elements it's trying to set the style properties of:
<a data-metrics-event-name="clickAction" data-metrics-link-module="score strip" data-metrics-link-name="2019020300" data-metrics-link-type="global nav" data-metrics-link-url="/gamecenter/2019020300/2018/POST22/patriots@rams" aria-label="Patriots 13">
<a data-metrics-event-name="clickAction" data-metrics-link-module="score strip" data-metrics-link-name="2019020300" data-metrics-link-type="global nav" data-metrics-link-url="/gamecenter/2019020300/2018/POST22/patriots@rams" aria-label="Rams 3">
<a data-metrics-event-name="clickAction" data-metrics-link-module="score strip" data-metrics-link-name="2019020300" data-metrics-link-type="global nav" data-metrics-link-url="/gamecenter/2019020300/2018/POST22/patriots@rams" aria-label="Final">
And all the various objects involved seem to be native objects.
As expected, I can't reproduce the problem in a reduced test-case:
document.createElement("a").style["0"] = undefined;
/* or even */
it(document.createElement("a"), {0: undefined});
Weirder still, Chrome is also running the same element.style[0]=undefined
on the same elements without throwing an exception like Firefox. And if I hack it so Firefox uses the setProperty
form or skips the 0, it also works.
Frankly I'm stumped as to why certain CSS2Properties
objects would selectively reject a 0 index like this. @bzbarsky, you wouldn't happen to have any ideas?
Hmm. So if we are hitting that exception, that means we landed in the [[DefineOwnProperty]] for CSS2Properties. A trivial way to reproduce that is:
Object.defineProperty(document.documentElement.style, 0, {});
To get there via simple assignment, though, I think a few things have to be true:
So here is a simple testcase that reproduces the issue in Firefox:
<script>
"use strict";
document.documentElement.style[0] = undefined;
</script>
So I guess a few things to check:
style.cssText
at the point when we do the assignment? Especially if we can get that information in Chrome...That said, my testcase does NOT throw an exception in Chrome. That seems to be a bug in Chrome, per spec. In particular, per spec the following sequence of events should take place:
OrdinarySetWithOwnDescriptor
.ownDesc
set to undefined, since there is no existing property named 0. OrdinarySetWithOwnDescriptor
), but never finds an object with a property named 0. Eventually it gets to Object.prototype
and reaches step 2.c there, which synthesizes an ownDesc. Since the thing is synthesizes is a data descriptor, we enter step 3, Receiver is the CSS2Properties
object, it has no own property named "0", still, so we go to step 3.e.i and call CreateDataProperty
.Chrome does throw if I explicitly do Object.defineProperty(document.documentElement.style, 0, {});
. Safari seems to not throw in either case...
@domenic, do you know what Chrome is actually implementing here. :(
Not sure myself, but @yuki3 probably knows.
I've not yet carefully followed this thread, however, off the top of my head, the following would be related.
Chrome (Blink) implements CSSStyleDeclaration's camel-cased attributes as named properties knowing it's wrong. document.documentElement.style
is a CSSStyleDeclaration
, so probably this is related?
I don't see how that would affect indexed property access at all.
I'm sorry. I read the thread again. Let me describe what Chrome is doing.
For indexed/named properties, V8 supports several kinds of callback functions, such as getter, setter, descriptor (getOwnPropertyDescriptor), deleter, enumerator, and definer (defineProperty). Blink implements each callback as needed. So, technically we can implement different behaviors for setter and definer. I confirmed that Chrome checks whether it's strict mode or not in definer, but does not check it in setter. This is a problem.
There is another problem in Chrome. Chrome implements camel-cased attributes as named properties (this is wrong), which support both of getter and setter. Despite that the standard says that there is indexed getter but no indexed setter, Chrome actually supports both of indexed getter and indexed setter. The indexed setter falls back to the named setter, like below.
let style = document.documentElement.style;
style.cssText = "...";
// => style's named setter("cssText", "...");
style[0] = "...";
// => style's indexed setter(0, "...");
// => style's named setter("0", "..."); with a conversion from 0 to "0"
This makes Chrome behave weirdly, and this is why assignment doesn't throw but Object.defineProperty throws. Does this explanation (not behavior) makes sense? I agree that Blink's implementation is strange and wrong sadly.
@yuki3 thank you for explaining that.
Next question: where do we go from here? Is Chrome willing to align with the current spec (and we get this site to fix their code as needed)? Or do we need to spec something either like what Chrome does or with at least the same observable effects in this case? If we choose to do the latter, I suspect we can manage with just web idl spec changes and not ES spec changes, presumably by having [[Set]] not fall through to OrdinarySetWithOwnDescriptor when O supports indexed properties but has no indexed property setter.
I personally do not have a conplainment in the current spec, and happy to follow it. The problem (for Blink bindings team) is a hack of CSSStyleDeclaration. If the hack is gone (= no named properties), it seems easy to fix the indexed setter to throw an exception in strict mode.
Let me file an issue against Blink CSS team about this tomorrow. I'll cc you.
It looks like that got duplicated to a longstanding issue that I had given up on ever being fixed in Chrome...
Is there any way to fix the behavior for names that look like array indices without completely fixing the named property issue?
The issue in Chrome. (paper trail)
I'm now trying to workaround this with this patch.
@yuki3 Thank you!
It appears as though this page is no longer breaking with the CSS2Properties glitch, so since Chromium has also landed a fix to be interoperable here, I think we might as well close this one as fixed.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue at https://webcompat.com/issues/new if you are experiencing a similar problem.
URL: https://www.nfl.com/gamecenter/2019020300/2018/POST22/patriots@rams?icampaign=scoreStrip-globalNav-2019020300
Browser / Version: Firefox Nightly 67.0a1 (2019-02-03) Operating System: Windows 10 Pro Tested Another Browser: Yes
Problem type: Site is not usable Description: Blank page displayed on “Patriots vs Rams” score page Steps to Reproduce:
Expected Behavior: “Patriots vs Rams” score and details page is displayed.
Actual Behavior: Blank page is displayed.
Note
Watchers: @softvision-oana-arbuzov @softvision-sergiulogigan @cipriansv
sv;
Browser Configuration
From webcompat.com with ❤️