PeculiarVentures / webcrypto-liner

webcrypto-liner is a polyfill that let's down-level User Agents (like IE/Edge) use libraries that depend on WebCrypto. (Keywords: Javascript, WebCrypto, Shim, Polyfill)
MIT License
148 stars 26 forks source link

Failed to init in the Web Worker #76

Open Jack-Works opened 4 years ago

Jack-Works commented 4 years ago

https://github.com/PeculiarVentures/webcrypto-liner/blob/faae2d4b127c1830ceb2fad4736d6177feab3544/src/shim.ts#L11-18

Source code:

try {
  // Replace original crypto by liner
  delete (self as any).crypto;
  window.crypto = new Crypto();
  Object.freeze(window.crypto);
} catch (e) {
  Debug.error(e);
}

In the mainframe, crypto.* is defined on the Window interface and self or window has the prototype of Window therefore everything is fine.

In Web Worker, crypto.* is defined on the WorkerGlobalScope, but self is not direct instance of WorkerGlobalScope:

The prototype chain is:

self => DedicatedWorkerGlobalScope => WorkerGlobalScope

Therefore delete self.crypto doesn't work since crypto is not defined on the DedicatedWorkerGlobalScope but WorkerGlobalScope.

After the deletion implicitly failed (delete op return true for non-existence property, in this case, crypto)

Line 13 window.crypto = new Crypto(); failed to run because WorkerGlobalScope.crypto is a configurable getter but no setter.

Jack-Works commented 4 years ago

Workaround:

Run the following code before loading webcrypto-liner

const MaybeWorkerGlobalScope = Object.getPrototypeOf(Object.getPrototypeOf(globalThis))
const crypto = Object.getOwnPropertyDescriptor(MaybeWorkerGlobalScope, 'crypto')
// The crypto is defined in [WorkerGlobalScope], let's move it to [DedicatedWorkerGlobalScope]
if (crypto) {
    delete MaybeWorkerGlobalScope.crypto
    Object.defineProperty(globalThis, 'crypto', crypto)
}