Skip to content

Polyfill TypedArray.slice() in older browsers. fixes #11008 #11011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

kripken
Copy link
Member

@kripken kripken commented Apr 27, 2020

Also enable LEGACY_VM_SUPPORT on wasm backend testing,
which was disabled for some reason.

@JustAMan
Copy link
Contributor

@kripken Mozilla-provided polyfill hard-crashed in WebOS 1.2 emulator (where I found the issue). The engine just died restarting app from scratch.

I've ended up just taking older code from yours like this: https://github.com/jellyfin/JavascriptSubtitlesOctopus/blob/master/src/pre-worker.js#L10-L17

@sbc100
Copy link
Collaborator

sbc100 commented Apr 28, 2020

WebOS 1.2 emulator! I've not heard that name in maybe a decade. What JS engine is running in there?

@kripken
Copy link
Member Author

kripken commented Apr 28, 2020

Ok, I changed it to use this.subarray as in that link - please let me know if that works.

@JustAMan
Copy link
Contributor

I've not heard that name in maybe a decade.

That's a bit strange, my TV has WebOS 2.0 and was manufactured in 2015. So it's not exactly recent, but it has a decent 4K panel and passive 3D, so I would still like to continue using it. Same could be said about WebOS 1.2 devices - they still have nice panels, and attaching an external TV box is a hassle as it usually adds one more remote to manage the device.

What JS engine is running in there?

navigator.userAgent says "Mozilla/5.0 (Web0S; Linux i686) AppleWebKit/537.41 (KHTML, like Gecko) Large Screen WebAppManager Safari/537.41".
But those engines are real funky, e.g. engine in WebOS 2.0 claims it supports Promises but chokes on Promise.resolve() wanting Promise.resolve(undefined) instead, etc.

@JustAMan
Copy link
Contributor

I think it should be good. Also it seems to have been lost, needs a nudge probably?

#if MIN_CHROME_VERSION < 45 || MIN_EDGE_VERSION < 14 || MIN_FIREFOX_VERSION < 38 || MIN_IE_VERSION != TARGET_NOT_SUPPORTED
// Older browsers may lack TypedArray.slice()
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice#Browser_compatibility
[Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that all of those actually have a super-class TypedArray that is not directly exposed. That is, instead of adding a method to each and every class, you can get a TypedArray reference via

var typedArrayProto = Int8Array.prototype.__proto__;

and then polyfill typedArrayProto.slice once.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, thanks, I didn't know that.

Do you know if that's well-supported in all legacy browsers?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't, unfortunately, and can't test it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still relevant. In fact, we need these polyfills.

Tested this polyfill:

var typedArrayProto = Object.getPrototypeOf(Int8Array.prototype);
if (typedArrayProto && !typedArrayProto.slice) {
    typedArrayProto.slice = function (begin, end) {
        return new this.constructor(this.subarray(begin, end));
    }
}

webOS 1.2 (WebKit)
Polyfill works correctly.

Object.getPrototypeOf(Int8Array.prototype):     [object ArrayBufferViewPrototype]
Int8Array.prototype:                            [object Int8ArrayPrototype]
Object.getPrototypeOf(Int8Array):               [object Object]
Int8Array:                                      [object Int8ArrayConstructor]

Object.getPrototypeOf(Int32Array.prototype):    [object ArrayBufferViewPrototype]
Int32Array.prototype:                           [object Int32ArrayPrototype]
Object.getPrototypeOf(Int32Array):              [object Object]
Int32Array:                                     [object Int32ArrayConstructor]

Object.getPrototypeOf(Int8Array.prototype) === Object.getPrototypeOf(Int32Array.prototype): true
Object.getPrototypeOf(Int8Array.prototype) === Object.getPrototypeOf({}): false

webOS 3 (Chrome 38)
Polyfill works, but {} gets slice. So it is probably better to leave as it is.

Object.getPrototypeOf(Int8Array.prototype):     [object Object]
Int8Array.prototype:                            [object Object]
Object.getPrototypeOf(Int8Array):               function Empty() {}
Int8Array:                                      function Int8Array() { [nativecode] }

Object.getPrototypeOf(Int32Array.prototype):    [object Object]
Int32Array.prototype:                           [object Object]
Object.getPrototypeOf(Int32Array):              function Empty() {}
Int32Array:                                     function Int32Array() { [nativecode] }

Object.getPrototypeOf(Int8Array.prototype) === Object.getPrototypeOf(Int32Array.prototype): true
Object.getPrototypeOf(Int8Array.prototype) === Object.getPrototypeOf({}): true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dmitrylyzo thanks for the info. Would you like to open a PR that takes this code and updates it to use the right polyfills?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested your polyfill - works fine. As I said, I think it is better (for legacy browsers) than the super-class polyfill, because in webOS 3 super-class polyfill adds slice to every object due to a common prototype (but it could just be a glitch of the emulator).

As for the other polyfills, they are for the libraries used in that project. Wouldn't their inclusion bloat the output file?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I ask what targets do you have that run webOS 3 (chrome 38). That seems like a rather old version of the browser to target.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly old TVs (https://webostv.developer.lge.com/discover/specifications/web-engine/). Jellyfin is targeting Chrome 27 as a rough approximation of webOS 1.2 and 2.0 (both WebKit).

@kripken
Copy link
Member Author

kripken commented Jul 16, 2020

I think this is blocked on getting confirmation that it works. @JustAMan did you get a chance to verify that? (Would also be good to verify @RReverser 's suggestion as well, as if that works too it sounds better.)

Base automatically changed from master to main March 8, 2021 23:49
@stale
Copy link

stale bot commented Nov 2, 2022

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.

@stale stale bot added the wontfix label Nov 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants