diff --git a/.github/workflows/docs-public.yml b/.github/workflows/docs-public.yml new file mode 100644 index 00000000..e81b7205 --- /dev/null +++ b/.github/workflows/docs-public.yml @@ -0,0 +1,34 @@ +# This is a basic workflow to help you get started with Actions + +name: Public docs + +on: + push: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Build website + run: cd website && yarn && yarn build + - name: Deploy to GitHub Pages + if: success() + uses: crazy-max/ghaction-github-pages@v2 + with: + target_branch: gh-pages + build_dir: website/build + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b2809017 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created +# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages + +name: Release + +on: + push: + branches: + - master + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + - name: install + run: yarn + - name: publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: yarn semantic-release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..448d0239 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,31 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Test + +on: ["push", "pull_request"] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [12.x, 14.x, 16.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - name: yarn install + run: yarn --frozen-lockfile + - name: test + run: yarn test + - name: coverage test + run: yarn jest --coverage + - uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/__tests__/patch.js b/__tests__/patch.js index eee94a45..1885094a 100644 --- a/__tests__/patch.js +++ b/__tests__/patch.js @@ -5,7 +5,8 @@ import produce, { produceWithPatches, enableAllPlugins, isDraft, - immerable + immerable, + nothing } from "../src/immer" enableAllPlugins() @@ -1277,3 +1278,10 @@ test("#648 assigning object to itself should not change patches", () => { } ]) }) + +test("#791 patch for nothing is stored as undefined", () => { + const [newState, patches] = produceWithPatches({abc: 123}, draft => nothing) + expect(patches).toEqual([{op: "replace", path: [], value: undefined}]) + + expect(applyPatches({}, patches)).toEqual(undefined) +}) diff --git a/__tests__/regressions.js b/__tests__/regressions.js index d3e63cac..329b0a09 100644 --- a/__tests__/regressions.js +++ b/__tests__/regressions.js @@ -239,5 +239,17 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) { bar: {x: 3} }) }) + + test("#807 new undefined member not stored", () => { + const state = {} + const newState = produce(state, draft => { + draft.baz = undefined + }) + expect(state).not.toBe(newState) + expect(Object.hasOwnProperty.call(newState, "baz")).toBe(true) + expect(newState).toEqual({ + baz: undefined + }) + }) }) } diff --git a/src/core/current.ts b/src/core/current.ts index 9e49fd70..3a201988 100644 --- a/src/core/current.ts +++ b/src/core/current.ts @@ -8,8 +8,7 @@ import { set, ImmerState, isDraftable, - ArchtypeMap, - ArchtypeSet, + Archtype, getArchtype, getPlugin } from "../internal" @@ -45,15 +44,15 @@ function currentImpl(value: any): any { set(copy, key, currentImpl(childValue)) }) // In the future, we might consider freezing here, based on the current settings - return archType === ArchtypeSet ? new Set(copy) : copy + return archType === Archtype.Set ? new Set(copy) : copy } function copyHelper(value: any, archType: number): any { // creates a shallow copy, even if it is a map or set switch (archType) { - case ArchtypeMap: + case Archtype.Map: return new Map(value) - case ArchtypeSet: + case Archtype.Set: // Set will be cloned as array temporarily, so that we can replace individual items return Array.from(value) } diff --git a/src/core/finalize.ts b/src/core/finalize.ts index 273c6386..67842fa3 100644 --- a/src/core/finalize.ts +++ b/src/core/finalize.ts @@ -11,9 +11,7 @@ import { isDraft, SetState, set, - ProxyTypeES5Object, - ProxyTypeES5Array, - ProxyTypeSet, + ProxyType, getPlugin, die, revokeScope, @@ -84,7 +82,7 @@ function finalize(rootScope: ImmerScope, value: any, path?: PatchPath) { state.scope_.unfinalizedDrafts_-- const result = // For ES5, create a good copy from the draft first, with added keys and without deleted keys. - state.type_ === ProxyTypeES5Object || state.type_ === ProxyTypeES5Array + state.type_ === ProxyType.ES5Object || state.type_ === ProxyType.ES5Array ? (state.copy_ = shallowCopy(state.draft_)) : state.copy_ // Finalize all children of the copy @@ -92,7 +90,7 @@ function finalize(rootScope: ImmerScope, value: any, path?: PatchPath) { // Although the original test case doesn't seem valid anyway, so if this in the way we can turn the next line // back to each(result, ....) each( - state.type_ === ProxyTypeSet ? new Set(result) : result, + state.type_ === ProxyType.Set ? new Set(result) : result, (key, childValue) => finalizeProperty(rootScope, state, result, key, childValue, path) ) @@ -124,7 +122,7 @@ function finalizeProperty( const path = rootPath && parentState && - parentState!.type_ !== ProxyTypeSet && // Set objects are atomic since they have no keys. + parentState!.type_ !== ProxyType.Set && // Set objects are atomic since they have no keys. !has((parentState as Exclude).assigned_!, prop) // Skip deep patches for assigned keys. ? rootPath!.concat(prop) : undefined diff --git a/src/core/immerClass.ts b/src/core/immerClass.ts index a2954a16..6975225c 100644 --- a/src/core/immerClass.ts +++ b/src/core/immerClass.ts @@ -185,7 +185,7 @@ export class Immer implements ProducersFns { this.useProxies_ = value } - applyPatches(base: Objectish, patches: Patch[]): T { + applyPatches(base: T, patches: Patch[]): T { // If a patch replaces the entire state, take that replacement as base // before applying patches let i: number diff --git a/src/core/proxy.ts b/src/core/proxy.ts index b906ff4c..7aaaf4cd 100644 --- a/src/core/proxy.ts +++ b/src/core/proxy.ts @@ -15,8 +15,7 @@ import { DRAFT_STATE, die, createProxy, - ProxyTypeProxyObject, - ProxyTypeProxyArray + ProxyType } from "../internal" interface ProxyBaseState extends ImmerBaseState { @@ -28,14 +27,14 @@ interface ProxyBaseState extends ImmerBaseState { } export interface ProxyObjectState extends ProxyBaseState { - type_: typeof ProxyTypeProxyObject + type_: ProxyType.ProxyObject base_: any copy_: any draft_: Drafted } export interface ProxyArrayState extends ProxyBaseState { - type_: typeof ProxyTypeProxyArray + type_: ProxyType.ProxyArray base_: AnyArray copy_: AnyArray | null draft_: Drafted @@ -54,7 +53,7 @@ export function createProxyProxy( ): Drafted { const isArray = Array.isArray(base) const state: ProxyState = { - type_: isArray ? ProxyTypeProxyArray : (ProxyTypeProxyObject as any), + type_: isArray ? ProxyType.ProxyArray : (ProxyType.ProxyObject as any), // Track which produce call this is associated with. scope_: parent ? parent.scope_ : getCurrentScope()!, // True for both shallow and deep changes. @@ -158,7 +157,14 @@ export const objectTraps: ProxyHandler = { markChanged(state) } - if (state.copy_![prop] === value && typeof value !== "number") return true + if ( + state.copy_![prop] === value && + // special case: NaN + typeof value !== "number" && + // special case: handle new props with value 'undefined' + (value !== undefined || prop in state.copy_) + ) + return true // @ts-ignore state.copy_![prop] = value @@ -187,7 +193,7 @@ export const objectTraps: ProxyHandler = { if (!desc) return desc return { writable: true, - configurable: state.type_ !== ProxyTypeProxyArray || prop !== "length", + configurable: state.type_ !== ProxyType.ProxyArray || prop !== "length", enumerable: desc.enumerable, value: owner[prop] } diff --git a/src/core/scope.ts b/src/core/scope.ts index 4505ea63..9cfd9ae9 100644 --- a/src/core/scope.ts +++ b/src/core/scope.ts @@ -5,8 +5,7 @@ import { Immer, DRAFT_STATE, ImmerState, - ProxyTypeProxyObject, - ProxyTypeProxyArray, + ProxyType, getPlugin } from "../internal" import {die} from "../utils/errors" @@ -78,8 +77,8 @@ export function enterScope(immer: Immer) { function revokeDraft(draft: Drafted) { const state: ImmerState = draft[DRAFT_STATE] if ( - state.type_ === ProxyTypeProxyObject || - state.type_ === ProxyTypeProxyArray + state.type_ === ProxyType.ProxyObject || + state.type_ === ProxyType.ProxyArray ) state.revoke_() else state.revoked_ = true diff --git a/src/plugins/es5.ts b/src/plugins/es5.ts index d0c3e02d..5cfa77f4 100644 --- a/src/plugins/es5.ts +++ b/src/plugins/es5.ts @@ -11,8 +11,7 @@ import { is, loadPlugin, ImmerScope, - ProxyTypeES5Array, - ProxyTypeES5Object, + ProxyType, getCurrentScope, die, markChanged, @@ -74,7 +73,7 @@ export function enableES5() { const draft = createES5Draft(isArray, base) const state: ES5ObjectState | ES5ArrayState = { - type_: isArray ? ProxyTypeES5Array : (ProxyTypeES5Object as any), + type_: isArray ? ProxyType.ES5Array : (ProxyType.ES5Object as any), scope_: parent ? parent.scope_ : getCurrentScope(), modified_: false, finalized_: false, @@ -139,10 +138,10 @@ export function enableES5() { const state: ES5State = drafts[i][DRAFT_STATE] if (!state.modified_) { switch (state.type_) { - case ProxyTypeES5Array: + case ProxyType.ES5Array: if (hasArrayChanges(state)) markChanged(state) break - case ProxyTypeES5Object: + case ProxyType.ES5Object: if (hasObjectChanges(state)) markChanged(state) break } @@ -155,7 +154,7 @@ export function enableES5() { const state: ES5State | undefined = object[DRAFT_STATE] if (!state) return const {base_, draft_, assigned_, type_} = state - if (type_ === ProxyTypeES5Object) { + if (type_ === ProxyType.ES5Object) { // Look for added keys. // probably there is a faster way to detect changes, as sweep + recurse seems to do some // unnecessary work. @@ -179,7 +178,7 @@ export function enableES5() { markChanged(state) } }) - } else if (type_ === ProxyTypeES5Array) { + } else if (type_ === ProxyType.ES5Array) { if (hasArrayChanges(state as ES5ArrayState)) { markChanged(state) assigned_.length = true @@ -253,7 +252,7 @@ export function enableES5() { } function hasChanges_(state: ES5State) { - return state.type_ === ProxyTypeES5Object + return state.type_ === ProxyType.ES5Object ? hasObjectChanges(state) : hasArrayChanges(state) } diff --git a/src/plugins/mapset.ts b/src/plugins/mapset.ts index 0be2ef67..6fbfd572 100644 --- a/src/plugins/mapset.ts +++ b/src/plugins/mapset.ts @@ -13,8 +13,7 @@ import { createProxy, loadPlugin, markChanged, - ProxyTypeMap, - ProxyTypeSet, + ProxyType, die, each } from "../internal" @@ -50,7 +49,7 @@ export function enableMapSet() { // Create class manually, cause #502 function DraftMap(this: any, target: AnyMap, parent?: ImmerState): any { this[DRAFT_STATE] = { - type_: ProxyTypeMap, + type_: ProxyType.Map, parent_: parent, scope_: parent ? parent.scope_ : getCurrentScope()!, modified_: false, @@ -208,7 +207,7 @@ export function enableMapSet() { // Create class manually, cause #502 function DraftSet(this: any, target: AnySet, parent?: ImmerState) { this[DRAFT_STATE] = { - type_: ProxyTypeSet, + type_: ProxyType.Set, parent_: parent, scope_: parent ? parent.scope_ : getCurrentScope()!, modified_: false, diff --git a/src/plugins/patches.ts b/src/plugins/patches.ts index bc3ba282..e0cdc091 100644 --- a/src/plugins/patches.ts +++ b/src/plugins/patches.ts @@ -16,19 +16,12 @@ import { isSet, isMap, loadPlugin, - ProxyTypeProxyObject, - ProxyTypeES5Object, - ProxyTypeMap, - ProxyTypeES5Array, - ProxyTypeProxyArray, - ProxyTypeSet, - ArchtypeMap, - ArchtypeSet, - ArchtypeArray, + ProxyType, + Archtype, die, isDraft, isDraftable, - ArchtypeObject + NOTHING } from "../internal" export function enablePatches() { @@ -43,19 +36,19 @@ export function enablePatches() { inversePatches: Patch[] ): void { switch (state.type_) { - case ProxyTypeProxyObject: - case ProxyTypeES5Object: - case ProxyTypeMap: + case ProxyType.ProxyObject: + case ProxyType.ES5Object: + case ProxyType.Map: return generatePatchesFromAssigned( state, basePath, patches, inversePatches ) - case ProxyTypeES5Array: - case ProxyTypeProxyArray: + case ProxyType.ES5Array: + case ProxyType.ProxyArray: return generateArrayPatches(state, basePath, patches, inversePatches) - case ProxyTypeSet: + case ProxyType.Set: return generateSetPatches( (state as any) as SetState, basePath, @@ -198,7 +191,7 @@ export function enablePatches() { patches.push({ op: REPLACE, path: [], - value: replacement + value: replacement === NOTHING ? undefined : replacement }) inversePatches.push({ op: REPLACE, @@ -217,7 +210,7 @@ export function enablePatches() { const p = path[i] // See #738, avoid prototype pollution if ( - (parentType === ArchtypeObject || parentType === ArchtypeArray) && + (parentType === Archtype.Object || parentType === Archtype.Array) && (p === "__proto__" || p === "constructor") ) die(24) @@ -232,10 +225,10 @@ export function enablePatches() { switch (op) { case REPLACE: switch (type) { - case ArchtypeMap: + case Archtype.Map: return base.set(key, value) /* istanbul ignore next */ - case ArchtypeSet: + case Archtype.Set: die(16) default: // if value is an object, then it's assigned by reference @@ -246,22 +239,22 @@ export function enablePatches() { } case ADD: switch (type) { - case ArchtypeArray: + case Archtype.Array: return base.splice(key as any, 0, value) - case ArchtypeMap: + case Archtype.Map: return base.set(key, value) - case ArchtypeSet: + case Archtype.Set: return base.add(value) default: return (base[key] = value) } case REMOVE: switch (type) { - case ArchtypeArray: + case Archtype.Array: return base.splice(key as any, 1) - case ArchtypeMap: + case Archtype.Map: return base.delete(key) - case ArchtypeSet: + case Archtype.Set: return base.delete(patch.value) default: return delete base[key] diff --git a/src/types/types-internal.ts b/src/types/types-internal.ts index 7ebc7d81..d3bc5612 100644 --- a/src/types/types-internal.ts +++ b/src/types/types-internal.ts @@ -17,17 +17,21 @@ export type AnyArray = Array export type AnySet = Set export type AnyMap = Map -export const ArchtypeObject = 0 -export const ArchtypeArray = 1 -export const ArchtypeMap = 2 -export const ArchtypeSet = 3 +export const enum Archtype { + Object, + Array, + Map, + Set +} -export const ProxyTypeProxyObject = 0 -export const ProxyTypeProxyArray = 1 -export const ProxyTypeES5Object = 4 -export const ProxyTypeES5Array = 5 -export const ProxyTypeMap = 2 -export const ProxyTypeSet = 3 +export const enum ProxyType { + ProxyObject, + ProxyArray, + Map, + Set, + ES5Object, + ES5Array +} export interface ImmerBaseState { parent_?: ImmerState diff --git a/src/utils/common.ts b/src/utils/common.ts index f41ee0aa..dae5064e 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -9,10 +9,7 @@ import { AnySet, ImmerState, hasMap, - ArchtypeObject, - ArchtypeArray, - ArchtypeMap, - ArchtypeSet, + Archtype, die } from "../internal" @@ -47,8 +44,7 @@ export function isPlainObject(value: any): boolean { const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor - if (Ctor === Object) - return true + if (Ctor === Object) return true return ( typeof Ctor == "function" && @@ -92,7 +88,7 @@ export function each( enumerableOnly?: boolean ): void export function each(obj: any, iter: any, enumerableOnly = false) { - if (getArchtype(obj) === ArchtypeObject) { + if (getArchtype(obj) === Archtype.Object) { ;(enumerableOnly ? Object.keys : ownKeys)(obj).forEach(key => { if (!enumerableOnly || typeof key !== "symbol") iter(key, obj[key], obj) }) @@ -102,7 +98,7 @@ export function each(obj: any, iter: any, enumerableOnly = false) { } /*#__PURE__*/ -export function getArchtype(thing: any): 0 | 1 | 2 | 3 { +export function getArchtype(thing: any): Archtype { /* istanbul ignore next */ const state: undefined | ImmerState = thing[DRAFT_STATE] return state @@ -110,17 +106,17 @@ export function getArchtype(thing: any): 0 | 1 | 2 | 3 { ? state.type_ - 4 // cause Object and Array map back from 4 and 5 : (state.type_ as any) // others are the same : Array.isArray(thing) - ? ArchtypeArray + ? Archtype.Array : isMap(thing) - ? ArchtypeMap + ? Archtype.Map : isSet(thing) - ? ArchtypeSet - : ArchtypeObject + ? Archtype.Set + : Archtype.Object } /*#__PURE__*/ export function has(thing: any, prop: PropertyKey): boolean { - return getArchtype(thing) === ArchtypeMap + return getArchtype(thing) === Archtype.Map ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop) } @@ -128,14 +124,14 @@ export function has(thing: any, prop: PropertyKey): boolean { /*#__PURE__*/ export function get(thing: AnyMap | AnyObject, prop: PropertyKey): any { // @ts-ignore - return getArchtype(thing) === ArchtypeMap ? thing.get(prop) : thing[prop] + return getArchtype(thing) === Archtype.Map ? thing.get(prop) : thing[prop] } /*#__PURE__*/ export function set(thing: any, propOrOldValue: PropertyKey, value: any) { const t = getArchtype(thing) - if (t === ArchtypeMap) thing.set(propOrOldValue, value) - else if (t === ArchtypeSet) { + if (t === Archtype.Map) thing.set(propOrOldValue, value) + else if (t === Archtype.Set) { thing.delete(propOrOldValue) thing.add(value) } else thing[propOrOldValue] = value diff --git a/src/utils/plugins.ts b/src/utils/plugins.ts index 6b2568ab..6c959acc 100644 --- a/src/utils/plugins.ts +++ b/src/utils/plugins.ts @@ -7,10 +7,7 @@ import { ImmerBaseState, AnyMap, AnySet, - ProxyTypeES5Array, - ProxyTypeES5Object, - ProxyTypeMap, - ProxyTypeSet, + ProxyType, die } from "../internal" @@ -74,14 +71,14 @@ interface ES5BaseState extends ImmerBaseState { } export interface ES5ObjectState extends ES5BaseState { - type_: typeof ProxyTypeES5Object + type_: ProxyType.ES5Object draft_: Drafted base_: AnyObject copy_: AnyObject | null } export interface ES5ArrayState extends ES5BaseState { - type_: typeof ProxyTypeES5Array + type_: ProxyType.ES5Array draft_: Drafted base_: any copy_: any @@ -90,7 +87,7 @@ export interface ES5ArrayState extends ES5BaseState { /** Map / Set plugin */ export interface MapState extends ImmerBaseState { - type_: typeof ProxyTypeMap + type_: ProxyType.Map copy_: AnyMap | undefined assigned_: Map | undefined base_: AnyMap @@ -99,7 +96,7 @@ export interface MapState extends ImmerBaseState { } export interface SetState extends ImmerBaseState { - type_: typeof ProxyTypeSet + type_: ProxyType.Set copy_: AnySet | undefined base_: AnySet drafts_: Map // maps the original value to the draft value in the new set diff --git a/website/yarn.lock b/website/yarn.lock index b54d2d3d..b1877337 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2811,9 +2811,9 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" - integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== + version "1.5.5" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014" + integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -7602,9 +7602,9 @@ postcss-zindex@^4.0.1: uniqs "^2.0.0" postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.35" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" - integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== + version "7.0.36" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" + integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -8779,9 +8779,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1"