diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8abca405f..2625cf75d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,18 @@ version: 2 updates: - - package-ecosystem: "npm" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "daily" +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 0 +- package-ecosystem: npm + directory: "/packages/backend" + schedule: + interval: daily + open-pull-requests-limit: 0 +- package-ecosystem: npm + directory: "/packages/client" + schedule: + interval: daily + open-pull-requests-limit: 0 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 62d558704..6caa3e377 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -595,6 +595,8 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する" smtpSecureInfo: "STARTTLS使用時はオフにします。" testEmail: "配信テスト" wordMute: "ワードミュート" +regexpError: "正規表現エラー" +regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:" instanceMute: "インスタンスミュート" userSaysSomething: "{name}が何かを言いました" makeActive: "アクティブにする" diff --git a/packages/backend/migration/1644010796173-convert-hard-mutes.js b/packages/backend/migration/1644010796173-convert-hard-mutes.js new file mode 100644 index 000000000..f06da6567 --- /dev/null +++ b/packages/backend/migration/1644010796173-convert-hard-mutes.js @@ -0,0 +1,64 @@ +const RE2 = require('re2'); +const { MigrationInterface, QueryRunner } = require("typeorm"); + +module.exports = class convertHardMutes1644010796173 { + name = 'convertHardMutes1644010796173' + + async up(queryRunner) { + let entries = await queryRunner.query(`SELECT "userId", "mutedWords" FROM "user_profile"`); + for(let i = 0; i < entries.length; i++) { + let words = entries[i].mutedWords + .map(line => { + const regexp = line.join(" ").match(/^\/(.+)\/(.*)$/); + if (regexp) { + // convert regexp's + try { + new RE2(regexp[1], regexp[2]); + return `/${regexp[1]}/${regexp[2]}`; + } catch (err) { + // invalid regex, ignore it + return []; + } + } else { + // remove empty segments + return line.filter(x => x !== ''); + } + }) + // remove empty lines + .filter(x => !(Array.isArray(x) && x.length === 0)); + + await queryRunner.connection.createQueryBuilder() + .update('user_profile') + .set({ + mutedWords: words + }) + .where('userId = :id', { id: entries[i].userId }) + .execute(); + } + } + + async down(queryRunner) { + let entries = await queryRunner.query(`SELECT "userId", "mutedWords" FROM "user_profile"`); + for(let i = 0; i < entries.length; i++) { + let words = entries[i].mutedWords + .map(line => { + if (Array.isArray(line)) { + return line; + } else { + // do not split regex at spaces again + return [line]; + } + }) + // remove empty lines + .filter(x => !(Array.isArray(x) && x.length === 0)); + + await queryRunner.connection.createQueryBuilder() + .update('user_profile') + .set({ + mutedWords: words + }) + .where('userId = :id', { id: entries[i].userId }) + .execute(); + } + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index d81688cbf..c331da732 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -123,7 +123,7 @@ "ms": "3.0.0-canary.1", "multer": "1.4.4", "nested-property": "4.0.0", - "node-fetch": "2.6.1", + "node-fetch": "2.6.7", "nodemailer": "6.7.2", "os-utils": "0.0.14", "parse5": "6.0.1", diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index e2e871dd2..dedda3cdf 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -11,26 +11,31 @@ type UserLike = { id: User['id']; }; -export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: string[][]): Promise { +export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: Array): Promise { // 自分自身 if (me && (note.userId === me.id)) return false; - const words = mutedWords - // Clean up - .map(xs => xs.filter(x => x !== '')) - .filter(xs => xs.length > 0); - - if (words.length > 0) { + if (mutedWords.length > 0) { if (note.text == null) return false; - const matched = words.some(and => - and.every(keyword => { - const regexp = keyword.match(/^\/(.+)\/(.*)$/); - if (regexp) { + const matched = mutedWords.some(filter => { + if (Array.isArray(filter)) { + return filter.every(keyword => note.text!.includes(keyword)); + } else { + // represents RegExp + const regexp = filter.match(/^\/(.+)\/(.*)$/); + + // This should never happen due to input sanitisation. + if (!regexp) return false; + + try { return new RE2(regexp[1], regexp[2]).test(note.text!); + } catch (err) { + // This should never happen due to input sanitisation. + return false; } - return note.text!.includes(keyword); - })); + } + }); if (matched) return true; } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index eb57aa2bf..aec7bbd2e 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -1,3 +1,4 @@ +const RE2 = require('re2'); import $ from 'cafy'; import * as mfm from 'mfm-js'; import { ID } from '@/misc/cafy-id'; @@ -117,7 +118,7 @@ export const meta = { }, mutedWords: { - validator: $.optional.arr($.arr($.str)), + validator: $.optional.arr($.either($.arr($.str.min(1)).min(1), $.str)), }, mutedInstances: { @@ -163,6 +164,12 @@ export const meta = { code: 'NO_SUCH_PAGE', id: '8e01b590-7eb9-431b-a239-860e086c408e', }, + + invalidRegexp: { + message: 'Invalid Regular Expression.', + code: 'INVALID_REGEXP', + id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', + } }, res: { @@ -191,6 +198,18 @@ export default define(meta, async (ps, _user, token) => { if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; if (ps.mutedWords !== undefined) { + // validate regular expression syntax + ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { + const regexp = x.match(/^\/(.+)\/(.*)$/); + if (!regexp) throw new ApiError(meta.errors.invalidRegexp); + + try { + new RE2(regexp[1], regexp[2]); + } catch (err) { + throw new ApiError(meta.errors.invalidRegexp); + } + }); + profileUpdates.mutedWords = ps.mutedWords; profileUpdates.enableWordMute = ps.mutedWords.length > 0; } diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index c4afef8b5..9f8e69431 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -4882,10 +4882,12 @@ node-fetch@*: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" -node-fetch@2.6.1, node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@2.6.7, node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-fetch@3.0.0-beta.9: version "3.0.0-beta.9" @@ -6169,20 +6171,11 @@ signal-exit@^3.0.5: integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675" - integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ== - dependencies: - decompress-response "^6.0.0" - once "^1.3.1" - simple-concat "^1.0.0" - -simple-get@^4.0.1: +simple-get@^4.0.0, simple-get@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== @@ -6653,6 +6646,11 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + trace-redirect@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/trace-redirect/-/trace-redirect-1.0.6.tgz#ac629b5bf8247d30dde5a35fe9811b811075b504" @@ -6998,6 +6996,11 @@ web-streams-polyfill@^3.0.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" @@ -7035,6 +7038,14 @@ whatwg-url@^10.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue index 19980dea1..bdccd7f1e 100644 --- a/packages/client/src/pages/settings/word-mute.vue +++ b/packages/client/src/pages/settings/word-mute.vue @@ -81,18 +81,65 @@ export default defineComponent({ }, async created() { - this.softMutedWords = this.$store.state.mutedWords.map(x => x.join(' ')).join('\n'); - this.hardMutedWords = this.$i.mutedWords.map(x => x.join(' ')).join('\n'); + const render = (mutedWords) => mutedWords.map(x => { + if (Array.isArray(x)) { + return x.join(' '); + } else { + return x; + } + }).join('\n'); + + this.softMutedWords = render(this.$store.state.mutedWords); + this.hardMutedWords = render(this.$i.mutedWords); this.hardWordMutedNotesCount = (await os.api('i/get-word-muted-notes-count', {})).count; }, methods: { async save() { - this.$store.set('mutedWords', this.softMutedWords.trim().split('\n').map(x => x.trim().split(' '))); + const parseMutes = (mutes, tab) => { + // split into lines, remove empty lines and unnecessary whitespace + let lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line != ''); + + // check each line if it is a RegExp or not + for(let i = 0; i < lines.length; i++) { + const line = lines[i] + const regexp = line.match(/^\/(.+)\/(.*)$/); + if (regexp) { + // check that the RegExp is valid + try { + new RegExp(regexp[1], regexp[2]); + // note that regex lines will not be split by spaces! + } catch (err) { + // invalid syntax: do not save, do not reset changed flag + os.alert({ + type: 'error', + title: this.$ts.regexpError, + text: this.$t('regexpErrorDescription', { tab, line: i + 1 }) + "\n" + err.toString() + }); + // re-throw error so these invalid settings are not saved + throw err; + } + } else { + lines[i] = line.split(' '); + } + } + }; + + let softMutes, hardMutes; + try { + softMutes = parseMutes(this.softMutedWords, this.$ts._wordMute.soft); + hardMutes = parseMutes(this.hardMutedWords, this.$ts._wordMute.hard); + } catch (err) { + // already displayed error message in parseMutes + return; + } + + this.$store.set('mutedWords', softMutes); await os.api('i/update', { - mutedWords: this.hardMutedWords.trim().split('\n').map(x => x.trim().split(' ')), + mutedWords: hardMutes, }); + this.changed = false; }, diff --git a/packages/client/src/scripts/check-word-mute.ts b/packages/client/src/scripts/check-word-mute.ts index 55637bb3b..74e258186 100644 --- a/packages/client/src/scripts/check-word-mute.ts +++ b/packages/client/src/scripts/check-word-mute.ts @@ -1,23 +1,28 @@ -export function checkWordMute(note: Record, me: Record | null | undefined, mutedWords: string[][]): boolean { +export function checkWordMute(note: Record, me: Record | null | undefined, mutedWords: Array): boolean { // 自分自身 if (me && (note.userId === me.id)) return false; - const words = mutedWords - // Clean up - .map(xs => xs.filter(x => x !== '')) - .filter(xs => xs.length > 0); - - if (words.length > 0) { + if (mutedWords.length > 0) { if (note.text == null) return false; - const matched = words.some(and => - and.every(keyword => { - const regexp = keyword.match(/^\/(.+)\/(.*)$/); - if (regexp) { + const matched = mutedWords.some(filter => { + if (Array.isArray(filter)) { + return filter.every(keyword => note.text!.includes(keyword)); + } else { + // represents RegExp + const regexp = filter.match(/^\/(.+)\/(.*)$/); + + // This should never happen due to input sanitisation. + if (!regexp) return false; + + try { return new RegExp(regexp[1], regexp[2]).test(note.text!); + } catch (err) { + // This should never happen due to input sanitisation. + return false; } - return note.text!.includes(keyword); - })); + } + }); if (matched) return true; } diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index e06e376bc..e5254efbc 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -1322,11 +1322,11 @@ aws4@^1.8.0: integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.0" babel-walk@3.0.0-canary-5: version "3.0.0-canary-5" @@ -2929,10 +2929,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== -follow-redirects@^1.10.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" - integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== +follow-redirects@^1.14.0: + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== forever-agent@~0.6.1: version "0.6.1" @@ -3041,9 +3041,9 @@ getpass@^0.1.1: assert-plus "^1.0.0" glob-parent@^5.1.0, glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" @@ -3490,14 +3490,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4245,9 +4238,11 @@ next-tick@~1.0.0: integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-gyp-build@~3.7.0: version "3.7.0" @@ -4532,9 +4527,9 @@ path-key@^3.0.0, path-key@^3.1.0: integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" @@ -5835,6 +5830,11 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + ts-loader@9.2.6: version "9.2.6" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" @@ -6188,6 +6188,11 @@ web-push@3.4.5: minimist "^1.2.5" urlsafe-base64 "^1.0.0" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webpack-cli@4.9.1: version "4.9.1" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3" @@ -6298,6 +6303,14 @@ websocket@1.0.34: utf-8-validate "^5.0.2" yaeti "^0.0.6" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"