Bug 199540 - Carvana.com needs the fetch AbortSignal quirk
Summary: Carvana.com needs the fetch AbortSignal quirk
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore JavaScript (show other bugs)
Version: Safari Technology Preview
Hardware: All All
: P2 Normal
Assignee: youenn fablet
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-07-05 19:21 PDT by Zhifei Fang
Modified: 2019-07-05 22:37 PDT (History)
6 users (show)

See Also:


Attachments
Patch (1.52 KB, patch)
2019-07-05 20:02 PDT, youenn fablet
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Zhifei Fang 2019-07-05 19:21:41 PDT
In this website: https://www.carvana.com/vehicle/1251874

They use a polyfill for abort signal, I guess the reason is here:
https://bugs.webkit.org/show_bug.cgi?id=174980

Though we already fix this, I guess for a compatible reason, they just do a polyfill for safari everywhere without checking safari's version.


here is the code:

```
                 a = function(e) {
                    function a() {
                        t(this, a);
                        var e = n(this, (a.__proto__ || Object.getPrototypeOf(a)).call(this));
                        return e.aborted = !1, e.onabort = null, e
                    }
                    return function(e, t) {
                        if ("function" !== typeof t && null !== t)
                            throw new TypeError("Super expression must either be null or a function, not " + typeof t);
                        e.prototype = Object.create(t && t.prototype, {
                            constructor: {
                                value: e,
                                enumerable: !1,
                                writable: !0,
                                configurable: !0
                            }
                        }), t && (Object.setPrototypeOf ? Object.setPrototypeOf(e, t) : e.__proto__ = t)
                    }(a, i), r(a, [{
                        key: "toString",
                        value: function() {
                            return "[object AbortSignal]"
                        }
                    }, {
                        key: "dispatchEvent",
                        value: function(e) {
                            "abort" === e.type && (this.aborted = !0, "function" === typeof this.onabort && this.onabort.call(this, e)), function e(t, r, n) {
                                null === t && (t = Function.prototype);
                                var i = Object.getOwnPropertyDescriptor(t, r);
                                if (void 0 === i) {
                                    var a = Object.getPrototypeOf(t);
                                    return null === a ? void 0 : e(a, r, n)
                                }
                                if ("value" in i)
                                    return i.value;
                                var o = i.get;
                                return void 0 !== o ? o.call(n) : void 0
                            }(a.prototype.__proto__ || Object.getPrototypeOf(a.prototype), "dispatchEvent", this).call(this, e)
                        }
                    }]), a
                }(),
                o = function() {
                    function e() {
                        t(this, e), this.signal = new a
                    }
                    return r(e, [{
                        key: "abort",
                        value: function() {
                            var e = void 0;
                            try {
                                e = new Event("abort")
                            } catch (t) {
                                "undefined" !== typeof document ? (e = document.createEvent("Event")).initEvent("abort", !1, !1) : e = {
                                    type: "abort",
                                    bubbles: !1,
                                    cancelable: !1
                                }
                            }
                            this.signal.dispatchEvent(e)
                        }
                    }, {
                        key: "toString",
                        value: function() {
                            return "[object AbortController]"
                        }
                    }]), e
                }();
            "undefined" !== typeof Symbol && Symbol.toStringTag && (o.prototype[Symbol.toStringTag] = "AbortController", a.prototype[Symbol.toStringTag] = "AbortSignal"), function(e) {
                if (!e.AbortController || function(e) {
                    return e.navigator && (e.navigator.vendor && e.navigator.vendor.startsWith("Apple Computer") || e.navigator.userAgent && e.navigator.userAgent.match(/ (crios|gsa|fxios)\//i))
                }(e))
                    if (e.AbortController = o, e.AbortSignal = a, e.fetch) {
```

in here, e is the window, they are using a self defined object (a, o) to replace webkit's AbortContorller and AbortSignal


And in FetchRequest::initialWith 

    if (init.signal) {
        if (auto* signal = JSAbortSignal::toWrapped(scriptExecutionContext()->vm(), init.signal))
            m_signal->follow(*signal);
        else if (!init.signal.isUndefinedOrNull())  {
            if (auto exception = processInvalidSignal(*scriptExecutionContext()))
                return WTFMove(*exception);
        }
    }

We do a JSAbortSignal::toWrapped, this will do a jscDynamicCast, since here it has been replaced by the polyfill, we cannot do that. In result, we have an exception here.

I guess to allow this polyfill, we should call the AbortSignal's interface in js, rather than dynamic cast it here
Comment 1 youenn fablet 2019-07-05 19:56:00 PDT
The website might be using https://github.com/mo/abortcontroller-polyfill.
The website would probably need to update their polyfill.
I guess a quirk is the way to go here.
Comment 2 youenn fablet 2019-07-05 20:02:18 PDT
Created attachment 373559 [details]
Patch
Comment 3 Radar WebKit Bug Importer 2019-07-05 20:02:45 PDT
<rdar://problem/52712158>
Comment 4 WebKit Commit Bot 2019-07-05 22:37:42 PDT
Comment on attachment 373559 [details]
Patch

Clearing flags on attachment: 373559

Committed r247191: <https://trac.webkit.org/changeset/247191>
Comment 5 WebKit Commit Bot 2019-07-05 22:37:44 PDT
All reviewed patches have been landed.  Closing bug.