diff --git a/jest.browser.js b/jest.browser.js index a2741e5e1..ee942320d 100644 --- a/jest.browser.js +++ b/jest.browser.js @@ -6,12 +6,16 @@ const config = Object.assign({}, baseConfig, { globals: Object.assign({}, baseConfig.globals, { USER_AGENT }), + setupFiles: baseConfig.setupFiles.concat([ + 'jsdom-worker' + ]), testPathIgnorePatterns: baseConfig.testPathIgnorePatterns.concat([ '/test/spec/serverStorage.js', '/test/spec/features/server' ]), moduleNameMapper: Object.assign({}, baseConfig.moduleNameMapper, { - '^./node$': './browser' + '^./node$': './browser', + 'workers/(.*?).emptyWorker': '/build/esm/browser/workers/$1.worker.js', }) }); diff --git a/lib/oidc/TokenManager.ts b/lib/oidc/TokenManager.ts index ab7c03a0c..56cd12222 100644 --- a/lib/oidc/TokenManager.ts +++ b/lib/oidc/TokenManager.ts @@ -45,6 +45,7 @@ import { import { REFRESH_TOKEN_STORAGE_KEY, TOKEN_STORAGE_NAME } from '../constants'; import { EventEmitter } from '../base/types'; import { StorageOptions, StorageProvider, StorageType } from '../storage/types'; +import { TimerService } from '../services/TimerService'; const DEFAULT_OPTIONS = { // TODO: remove in next major version - OKTA-473815 @@ -76,6 +77,7 @@ export class TokenManager implements TokenManagerInterface { private storage: StorageProvider; private state: TokenManagerState; private options: TokenManagerOptions; + private timerService: TimerService; on(event: typeof EVENT_RENEWED, handler: TokenManagerRenewEventHandler, context?: object): void; on(event: typeof EVENT_ERROR, handler: TokenManagerErrorEventHandler, context?: object): void; @@ -132,6 +134,7 @@ export class TokenManager implements TokenManagerInterface { this.storage = sdk.storageManager.getTokenStorage({...storageOptions, useSeparateCookies: true}); this.clock = SdkClock.create(/* sdk, options */); this.state = defaultState(); + this.timerService = new TimerService(); } start() { @@ -141,7 +144,7 @@ export class TokenManager implements TokenManagerInterface { this.setExpireEventTimeoutAll(); this.state.started = true; } - + stop() { this.clearExpireEventTimeoutAll(); this.state.started = false; @@ -187,7 +190,7 @@ export class TokenManager implements TokenManagerInterface { } clearExpireEventTimeout(key) { - clearTimeout(this.state.expireTimeouts[key] as any); + this.timerService.clearTimeout(this.state.expireTimeouts[key] as any); delete this.state.expireTimeouts[key]; // Remove the renew promise (if it exists) @@ -215,14 +218,14 @@ export class TokenManager implements TokenManagerInterface { // Clear any existing timeout this.clearExpireEventTimeout(key); - var expireEventTimeout = setTimeout(() => { + var expireEventTimeout = this.timerService.setTimeout(() => { this.emitExpired(key, token); }, expireEventWait); - + // Add a new timeout this.state.expireTimeouts[key] = expireEventTimeout; } - + setExpireEventTimeoutAll() { var tokenStorage = this.storage.getStorage(); for(var key in tokenStorage) { diff --git a/lib/services/TimerService.ts b/lib/services/TimerService.ts new file mode 100644 index 000000000..e7355c566 --- /dev/null +++ b/lib/services/TimerService.ts @@ -0,0 +1,99 @@ +import timerWorker from '../workers/TimerWorker.emptyWorker'; + +/* global BUNDLER */ + +export interface TimerWorkerOutMessage { + action: 'timeoutCallback' | 'init', + timerId?: number, +} +export interface TimerWorkerInMessage { + action: 'setTimeout' | 'clearTimeout', + timerId: number, + timeout?: number, +} + +export class TimerService { + private timerWorker?: Worker; + private timersHandlers: Record void>; + private timerId: number; + + constructor() { + this.timersHandlers = {}; + this.timerId = 0; + + if (typeof Worker !== 'undefined') { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (BUNDLER === 'webpack') { + // webpack build (umd/cdn) + const TimerWorker = timerWorker as any; + this.timerWorker = new TimerWorker() as Worker; + } else { + if (!timerWorker?.workerSrc) { + // babel build (cjs), for node - use fallback + } else { + // rollup build (esm) + this.timerWorker = new Worker(this.getWorkerURL()); + } + } + + this.timerWorker?.addEventListener('message', this.handleWorkerEvent.bind(this)); + } + } + + private getWorkerURL(): string { + const workerBlob = new Blob([timerWorker.workerSrc], { type: 'text/javascript' }); + // eslint-disable-next-line compat/compat + return URL.createObjectURL(workerBlob); + } + + private handleWorkerEvent(ev: MessageEvent) { + const data = ev.data; + switch(data.action) { + case 'timeoutCallback': + this.handleTimeoutCallback(data); + break; + case 'init': + break; + default: + break; + } + } + + private handleTimeoutCallback(data: TimerWorkerOutMessage) { + const { timerId } = data; + const handler = this.timersHandlers[timerId!]; + if (handler) { + handler(); + } + } + + setTimeout(handler: () => void, timeout: number) { + if (this.timerWorker) { + const timerId = this.timerId++; + this.timersHandlers[timerId] = handler.bind(this); + this.timerWorker?.postMessage({ + action: 'setTimeout', + timeout, + timerId: timerId, + } as TimerWorkerInMessage); + return timerId; + } else { + // fallback + return setTimeout(handler, timeout); + } + } + + clearTimeout(timerId: number) { + if (this.timerWorker) { + this.timerWorker?.postMessage({ + action: 'clearTimeout', + timerId: timerId, + } as TimerWorkerInMessage); + delete this.timersHandlers[this.timerId]; + } else { + // fallback + return clearTimeout(timerId); + } + } +} diff --git a/lib/types/global.d.ts b/lib/types/global.d.ts index dcd2ca74e..e52bc6b36 100644 --- a/lib/types/global.d.ts +++ b/lib/types/global.d.ts @@ -2,6 +2,8 @@ declare const SDK_VERSION: string; +declare const BUNDLER: string; + declare interface PromiseConstructor { // eslint-disable-next-line max-len, @typescript-eslint/member-delimiter-style allSettled(promises: Array>): Promise>; diff --git a/lib/workers/TimerWorker.emptyWorker.ts b/lib/workers/TimerWorker.emptyWorker.ts new file mode 100644 index 000000000..2ad004a8e --- /dev/null +++ b/lib/workers/TimerWorker.emptyWorker.ts @@ -0,0 +1,2 @@ +const workerSrc = ''; +export default { workerSrc }; diff --git a/lib/workers/TimerWorker.worker.ts b/lib/workers/TimerWorker.worker.ts new file mode 100644 index 000000000..47f0fc3f1 --- /dev/null +++ b/lib/workers/TimerWorker.worker.ts @@ -0,0 +1,45 @@ +// /// +// /// +// declare var self: DedicatedWorkerGlobalScope; +import type { TimerWorkerInMessage, TimerWorkerOutMessage } from '../services/TimerService'; + +const timerIdToTimeout = {}; + +function handleSetTimeout(data: TimerWorkerInMessage) { + const { timerId, timeout } = data; + const timeoutId = setTimeout(() => { + self.postMessage({ + action: 'timeoutCallback', + timerId, + } as TimerWorkerOutMessage); + delete timerIdToTimeout[timerId]; + }, timeout); + timerIdToTimeout[timerId] = timeoutId; +} + +function handleClearTimeout(data: TimerWorkerInMessage) { + const { timerId } = data; + const timeoutId = timerIdToTimeout[timerId]; + if (timeoutId) { + clearTimeout(timeoutId); + delete timerIdToTimeout[timerId]; + } +} + +self.addEventListener('message', function(ev: MessageEvent) { + const data = ev.data; + switch (data.action) { + case 'setTimeout': + handleSetTimeout.call(this, data); + break; + case 'clearTimeout': + handleClearTimeout.call(this, data); + break; + default: + break; + } +}); + +self.postMessage({ + action: 'init', +} as TimerWorkerOutMessage); diff --git a/package.json b/package.json index f88542c66..4db3cf536 100644 --- a/package.json +++ b/package.json @@ -180,6 +180,7 @@ "@rollup/plugin-alias": "^3.1.8", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-replace": "^3.0.0", + "@rollup/plugin-node-resolve": "^15.2.1", "@tsd/typescript": "^4.6.4", "@types/jest": "^27.5.1", "@types/node": "^14.0.3", @@ -208,6 +209,7 @@ "jest-runner": "^28.1.0", "jest-runner-tsd": "^3.0.0", "json-loader": "0.5.4", + "jsdom-worker": "denysoblohin-okta/jsdom-worker#sync-blob", "lodash": "4.17.21", "rollup": "^2.70.2", "rollup-plugin-cleanup": "^3.2.1", @@ -216,6 +218,7 @@ "rollup-plugin-typescript2": "^0.30.0", "rollup-plugin-visualizer": "~5.5.4", "shelljs": "0.8.5", + "string-replace-loader": "^3.1.0", "ts-jest": "^28.0.2", "tsd": "^0.17.0", "typedoc": "^0.23.19", @@ -224,7 +227,8 @@ "webpack": "^5.78.0", "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.10.0", - "webpack-dev-server": "^4.9.2" + "webpack-dev-server": "^4.9.2", + "worker-loader": "^3.0.8" }, "jest-junit": { "outputDirectory": "./build2/reports/unit/", diff --git a/rollup.config.js b/rollup.config.js index 075b9d25d..20b1e4012 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -2,9 +2,11 @@ import replace from '@rollup/plugin-replace'; import alias from '@rollup/plugin-alias'; import cleanup from 'rollup-plugin-cleanup'; import typescript from 'rollup-plugin-typescript2'; +import { getBabelOutputPlugin } from '@rollup/plugin-babel'; import license from 'rollup-plugin-license'; import multiInput from 'rollup-plugin-multi-input'; import { visualizer } from 'rollup-plugin-visualizer'; +import resolve from '@rollup/plugin-node-resolve'; import { existsSync, mkdirSync, writeFileSync } from 'fs'; import pkg from './package.json'; @@ -12,11 +14,12 @@ const path = require('path'); let platforms = ['browser', 'node']; let entries = { + 'worker': 'lib/workers/TimerWorker.worker.ts', 'okta-auth-js': 'lib/exports/default.ts', 'core': 'lib/exports/core.ts', 'authn': 'lib/exports/authn.ts', 'idx': 'lib/exports/idx.ts', - 'myaccount': 'lib/exports/myaccount.ts' + 'myaccount': 'lib/exports/myaccount.ts', }; let preserveModules = true; const combinedOutputDir = true; // all entries share an output dir @@ -89,6 +92,7 @@ const getPlugins = (env, entryName) => { let plugins = [ replace({ 'SDK_VERSION': JSON.stringify(pkg.version), + 'BUNDLER': JSON.stringify('rollup'), 'global.': 'window.', preventAssignment: true }), @@ -97,18 +101,25 @@ const getPlugins = (env, entryName) => { { find: /.\/node$/, replacement: './browser' } ] })), + entryName === 'worker' && { + name: 'worker-to-string', + renderChunk(code) { + return `var workerSrc = \`${code}\`; export default { workerSrc };`; + }, + }, typescript({ // eslint-disable-next-line node/no-unpublished-require typescript: require('typescript'), tsconfigOverride: { compilerOptions: { sourceMap: true, - target: 'ES2017', // skip async/await transpile, + target: entryName === 'worker' ? 'ES3' : 'ES2017', // skip async/await transpile, module: 'ES2020', // support dynamic import declaration: false } } }), + entryName === 'worker' && resolve(), cleanup({ extensions, comments: 'none' @@ -120,10 +131,14 @@ const getPlugins = (env, entryName) => { } } }), + replace({ + 'TimerWorker.emptyWorker.js': 'TimerWorker.worker.js', + preventAssignment: true + }), multiInput({ relative: 'lib/', }), - createPackageJson(outputDir) + createPackageJson(outputDir), ]; // if ANALZYE env var is passed, output analyzer html @@ -140,19 +155,33 @@ const getPlugins = (env, entryName) => { return plugins; }; + export default Object.keys(entries).reduce((res, entryName) => { const entryValue = entries[entryName]; return res.concat(platforms.map((type) => { - return { + return ({ input: Array.isArray(entryValue) ? entryValue : [entryValue], external: makeExternalPredicate(type), plugins: getPlugins(type, entryName), output: [ { ...output, - dir: getOuptutDir(entryName, type) + dir: getOuptutDir(entryName, type), + ...(entryName === 'worker' ? { + plugins: [ + getBabelOutputPlugin({ + presets: [ + '@babel/preset-env', + ], + }) + ], + preserveModules: false, + sourcemap: false, // sourcemaps do not work with `worker-to-string` plugin + exports: 'none', + } : { + }) } ] - }; + }); })); }, []); diff --git a/scripts/lint.sh b/scripts/lint.sh index 1ba5e3252..0b97bed86 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -1,4 +1,4 @@ -#!/bin/bash -e +#!/bin/bash -x source ${OKTA_HOME}/${REPO}/scripts/setup.sh diff --git a/scripts/publish.sh b/scripts/publish.sh index c730a65f1..cde5e5a94 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -1,4 +1,4 @@ -#!/bin/bash -xe +#!/bin/bash -x source ${OKTA_HOME}/${REPO}/scripts/setup.sh diff --git a/test/spec/api-base-token.js b/test/spec/api-base-token.js index 1c440f77a..df12f2a97 100644 --- a/test/spec/api-base-token.js +++ b/test/spec/api-base-token.js @@ -141,8 +141,10 @@ describe('base token API', function() { }); }, expectations: function () { - expect(fetch).toHaveBeenCalledTimes(1); - const args = fetch.mock.calls[0][1]; + const hasWorker = typeof Worker !== 'undefined'; // jsdom-worker calls fetch for 'blob:' url + const calls = hasWorker ? 2 : 1; + expect(fetch).toHaveBeenCalledTimes(calls); + const args = fetch.mock.calls[calls-1][1]; const params = util.parseQueryParams(args.body); // decode form body expect(params).toEqual( { 'client_id': CLIENT_ID, @@ -165,8 +167,10 @@ describe('base token API', function() { }); }, expectations: function () { - expect(fetch).toHaveBeenCalledTimes(1); - const args = fetch.mock.calls[0][1]; + const hasWorker = typeof Worker !== 'undefined'; // jsdom-worker calls fetch for 'blob:' url + const calls = hasWorker ? 2 : 1; + expect(fetch).toHaveBeenCalledTimes(calls); + const args = fetch.mock.calls[calls-1][1]; const params = util.parseQueryParams(args.body); // decode form body expect(params).toEqual( { 'client_id': CLIENT_ID, diff --git a/test/spec/browserStorage.js b/test/spec/browserStorage.js index c8cf6f487..5f9ba4242 100644 --- a/test/spec/browserStorage.js +++ b/test/spec/browserStorage.js @@ -120,7 +120,7 @@ describe('browserStorage', () => { const fn = function() { browserStorage.getCookieStorage(); }; - expect(fn).toThrowError('Cannot read property \'secure\' of undefined'); + expect(fn).toThrowError(/Cannot read property 'secure' of undefined|Cannot read properties of undefined \(reading 'secure'\)/); }); it('requires a "secure" option', () => { diff --git a/test/support/jest/jest.config.js b/test/support/jest/jest.config.js index 4e850cd39..cfd26382b 100644 --- a/test/support/jest/jest.config.js +++ b/test/support/jest/jest.config.js @@ -19,7 +19,8 @@ module.exports = { 'collectCoverage': true, 'collectCoverageFrom': ['./lib/**','!./test/**'], 'globals': { - SDK_VERSION + SDK_VERSION, + BUNDLER: 'jest', }, 'transform': { '^.+\\.(js)$': 'babel-jest', diff --git a/test/support/util.js b/test/support/util.js index a942d4644..c3e216be0 100644 --- a/test/support/util.js +++ b/test/support/util.js @@ -127,7 +127,12 @@ function mockAjax(pairs) { setNextPair(pairs); } + const origFetch = global.fetch; jest.spyOn(global, 'fetch').mockImplementation(function (url, args) { + if (url.startsWith('blob:')) { + // called by 'jsdom-worker' + return origFetch(url, args); + } var pair = allPairs.shift(); if (!pair) { throw new Error('We are making a request that we have not anticipated: ' + url); diff --git a/tsconfig.json b/tsconfig.json index 31b3459fd..1f08a279e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,8 @@ "baseUrl": "./" }, "lib": [ - "dom" + "dom", + "webworker" ], "files": [ "package.json" diff --git a/webpack.common.config.js b/webpack.common.config.js index 9c31a84c3..2b1ddbb9c 100644 --- a/webpack.common.config.js +++ b/webpack.common.config.js @@ -36,12 +36,29 @@ var babelExclude = /node_modules\/(?!p-cancelable)/; module.exports = { module: { rules: [ + { + test: /TimerService.[jt]s$/, + loader: 'string-replace-loader', + options: { + search: 'TimerWorker.emptyWorker', + replace: 'TimerWorker.worker', + } + }, + { + test: /\.worker\.[jt]s$/, + use: [ { + loader: 'worker-loader', + options: { + inline: 'no-fallback' + } + } ], + }, { test: /\.[jt]s$/, exclude: babelExclude, loader: 'babel-loader', options: babelOptions - } + }, ] }, resolve: { @@ -52,7 +69,8 @@ module.exports = { }, plugins: [ new webpack.DefinePlugin({ - SDK_VERSION: JSON.stringify(SDK_VERSION) + SDK_VERSION: JSON.stringify(SDK_VERSION), + BUNDLER: JSON.stringify('webpack'), }) ] }; diff --git a/yarn.lock b/yarn.lock index 17c277946..7791cb23e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1793,6 +1793,18 @@ "@babel/helper-module-imports" "^7.10.4" "@rollup/pluginutils" "^3.1.0" +"@rollup/plugin-node-resolve@^15.2.1": + version "15.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz#a15b14fb7969229e26a30feff2816d39eff503f0" + integrity sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w== + dependencies: + "@rollup/pluginutils" "^5.0.1" + "@types/resolve" "1.20.2" + deepmerge "^4.2.2" + is-builtin-module "^3.2.1" + is-module "^1.0.0" + resolve "^1.22.1" + "@rollup/plugin-replace@^3.0.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-3.1.0.tgz#d31e3a90c6b47064f3c9f2ce0ded5bcf0d3b82f6" @@ -1818,6 +1830,15 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.4.tgz#74f808f9053d33bafec0cc98e7b835c9667d32ba" + integrity sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -2291,6 +2312,11 @@ dependencies: "@types/node" "*" +"@types/resolve@1.20.2": + version "1.20.2" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" + integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -3050,16 +3076,16 @@ ansi-red@^0.1.1: dependencies: ansi-wrap "0.1.0" -ansi-regex@^2.0.0, ansi-regex@^4.1.0, ansi-regex@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-regex@^3.0.1: +ansi-regex@^2.0.0, ansi-regex@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== +ansi-regex@^4.1.0, ansi-regex@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -3635,6 +3661,11 @@ beeper@^1.0.0: resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" integrity sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -3821,6 +3852,11 @@ buffer@^5.2.1, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -5074,6 +5110,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -5668,7 +5709,7 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== -estree-walker@^2.0.1: +estree-walker@^2.0.1, estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -7255,11 +7296,25 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.10.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" @@ -7377,6 +7432,11 @@ is-map@^2.0.2: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" @@ -8245,6 +8305,13 @@ jsdoctypeparser@^6.1.0: resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-6.1.0.tgz#acfb936c26300d98f1405cb03e20b06748e512a8" integrity sha512-UCQBZ3xCUBv/PLfwKAJhp6jmGOSLFNKzrotXGNgbKhWvz27wPsCsVeP7gIcHPElQw2agBmynAitXqhxR58XAmA== +jsdom-worker@denysoblohin-okta/jsdom-worker#sync-blob: + version "0.3.0" + resolved "https://codeload.github.com/denysoblohin-okta/jsdom-worker/tar.gz/0bb38c92042dedfd89b9db79e784e337889f16c9" + dependencies: + mitt "^3.0.0" + uuid-v4 "^0.1.0" + jsdom@^19.0.0: version "19.0.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-19.0.0.tgz#93e67c149fe26816d38a849ea30ac93677e16b6a" @@ -8330,6 +8397,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +json5@^2.1.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + json5@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab" @@ -8557,6 +8629,15 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -9101,6 +9182,11 @@ minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== +mitt@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -10706,6 +10792,15 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.14. path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.3: version "2.0.0-next.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" @@ -10935,6 +11030,15 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +schema-utils@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^3.1.1, schema-utils@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" @@ -11545,6 +11649,14 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-replace-loader@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-replace-loader/-/string-replace-loader-3.1.0.tgz#11ac6ee76bab80316a86af358ab773193dd57a4f" + integrity sha512-5AOMUZeX5HE/ylKDnEa/KKBqvlnFmRZudSOjVJHxhoJg9QYTwl1rECx7SLR8BBH7tfxb4Rp7EM2XVfQFxIhsbQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -12454,6 +12566,11 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid-v4@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/uuid-v4/-/uuid-v4-0.1.0.tgz#62d7b310406f6cecfea1528c69f1e8e0bcec5a3a" + integrity sha512-m11RYDtowtAIihBXMoGajOEKpAXrKbpKlpmxqyztMYQNGSY5nZAZ/oYch/w2HNS1RMA4WLGcZvuD8/wFMuCEzA== + uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -12970,6 +13087,14 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== +worker-loader@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-3.0.8.tgz#5fc5cda4a3d3163d9c274a4e3a811ce8b60dbb37" + integrity sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"