From addca156d27c9fae9509b6184e809d3b8a7fcf75 Mon Sep 17 00:00:00 2001 From: aleclarson Date: Wed, 30 Jan 2019 18:25:24 -0500 Subject: [PATCH] feat: support async recipes Drafts won't be revoked until the returned promise is fulfilled or rejected. As suggested by @Yurickh in #302 --- __tests__/base.js | 32 ++++++- src/es5.js | 35 ++++--- src/immer.js | 157 ++++++++++++++++++------------- src/proxy.js | 12 +-- src/scope.js | 38 ++++++++ yarn.lock | 231 ++++++++++++++++++++++++++++------------------ 6 files changed, 325 insertions(+), 180 deletions(-) create mode 100644 src/scope.js diff --git a/__tests__/base.js b/__tests__/base.js index c494f334..67a7a6f3 100644 --- a/__tests__/base.js +++ b/__tests__/base.js @@ -815,7 +815,7 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) { expect(next.obj).toBe(next.arr[0]) }) - it("can return an object with two references to any pristine draft", () => { + it("can return an object with two references to an unmodified draft", () => { const base = {a: {}} const next = produce(base, d => { return [d.a, d.a] @@ -833,6 +833,36 @@ function runBaseTest(name, useProxies, autoFreeze, useListener) { }) }) + describe("async recipe function", () => { + it("can modify the draft", async () => { + const base = {a: 0, b: 0} + const res = await produce(base, async d => { + d.a = 1 + await Promise.resolve() + d.b = 1 + }) + expect(res).not.toBe(base) + expect(res).toEqual({a: 1, b: 1}) + }) + + it("works with rejected promises", async () => { + let draft + const base = {a: 0, b: 0} + const err = new Error("passed") + try { + await produce(base, async d => { + draft = d + draft.b = 1 + await Promise.reject(err) + }) + throw "failed" + } catch (e) { + expect(e).toBe(err) + expect(() => draft.a).toThrowError(/revoked/) + } + }) + }) + it("throws when the draft is modified and another object is returned", () => { const base = {x: 3} expect(() => { diff --git a/src/es5.js b/src/es5.js index 05414f4b..117dee2b 100644 --- a/src/es5.js +++ b/src/es5.js @@ -1,6 +1,4 @@ "use strict" -// @ts-check - import { each, has, @@ -11,20 +9,20 @@ import { shallowCopy, DRAFT_STATE } from "./common" +import {ImmerScope} from "./scope" const descriptors = {} -// For nested produce calls: -export const scopes = [] -export const currentScope = () => scopes[scopes.length - 1] - -export function willFinalize(result, baseDraft, needPatches) { - const scope = currentScope() - scope.forEach(state => (state.finalizing = true)) - if (result === undefined || result === baseDraft) { - if (needPatches) markChangesRecursively(baseDraft) +export function willFinalize(scope, result, isReplaced) { + scope.drafts.forEach(draft => { + draft[DRAFT_STATE].finalizing = true + }) + if (!isReplaced) { + if (scope.patches) { + markChangesRecursively(scope.drafts[0]) + } // This is faster when we don't care about which attributes changed. - markChangesSweep(scope) + markChangesSweep(scope.drafts) } } @@ -36,8 +34,9 @@ export function createDraft(base, parent) { }) // See "proxy.js" for property documentation. + const scope = parent ? parent.scope : ImmerScope.current const state = { - scope: parent ? parent.scope : currentScope(), + scope, modified: false, finalizing: false, // es5 only finalized: false, @@ -51,7 +50,7 @@ export function createDraft(base, parent) { } createHiddenProperty(draft, DRAFT_STATE, state) - state.scope.push(state) + scope.drafts.push(draft) return draft } @@ -135,14 +134,14 @@ function assertUnrevoked(state) { } // This looks expensive, but only proxies are visited, and only objects without known changes are scanned. -function markChangesSweep(scope) { +function markChangesSweep(drafts) { // The natural order of drafts in the `scope` array is based on when they // were accessed. By processing drafts in reverse natural order, we have a // better chance of processing leaf nodes first. When a leaf node is known to // have changed, we can avoid any traversal of its ancestor nodes. - for (let i = scope.length - 1; i >= 0; i--) { - const state = scope[i] - if (state.modified === false) { + for (let i = drafts.length - 1; i >= 0; i--) { + const state = drafts[i][DRAFT_STATE] + if (!state.modified) { if (Array.isArray(state.base)) { if (hasArrayChanges(state)) markChanged(state) } else if (hasObjectChanges(state)) markChanged(state) diff --git a/src/immer.js b/src/immer.js index 7bea00ca..c10baca5 100644 --- a/src/immer.js +++ b/src/immer.js @@ -13,6 +13,7 @@ import { DRAFT_STATE, NOTHING } from "./common" +import {ImmerScope} from "./scope" function verifyMinified() {} @@ -51,62 +52,37 @@ export class Immer { } let result - // Only create proxies for plain objects/arrays. - if (!isDraftable(base)) { - result = recipe(base) - if (result === undefined) return base - } - // The given value must be proxied. - else { - this.scopes.push([]) + + // Only plain objects, arrays, and "immerable classes" are drafted. + if (isDraftable(base)) { + const scope = ImmerScope.enter() const baseDraft = this.createDraft(base) try { result = recipe.call(baseDraft, baseDraft) - this.willFinalize(result, baseDraft, !!patchListener) - - // Never generate patches when no listener exists. - var patches = patchListener && [], - inversePatches = patchListener && [] - - // Finalize the modified draft... - if (result === undefined || result === baseDraft) { - result = this.finalize( - baseDraft, - [], - patches, - inversePatches - ) - } - // ...or use a replacement value. - else { - // Users must never modify the draft _and_ return something else. - if (baseDraft[DRAFT_STATE].modified) - throw new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.") // prettier-ignore - - // Finalize the replacement in case it contains (or is) a subset of the draft. - if (isDraftable(result)) result = this.finalize(result) - - if (patchListener) { - patches.push({ - op: "replace", - path: [], - value: result - }) - inversePatches.push({ - op: "replace", - path: [], - value: base - }) + } catch (error) { + scope.revoke() + throw error + } + scope.leave() + if (result instanceof Promise) { + return result.then( + result => { + scope.usePatches(patchListener) + return this.processResult(result, scope) + }, + error => { + scope.revoke() + throw error } - } - } finally { - this.currentScope().forEach(state => state.revoke()) - this.scopes.pop() + ) } - patchListener && patchListener(patches, inversePatches) + scope.usePatches(patchListener) + return this.processResult(result, scope) + } else { + result = recipe(base) + if (result === undefined) return base + return result !== NOTHING ? result : undefined } - // Normalize the result. - return result === NOTHING ? undefined : result } setAutoFreeze(value) { this.autoFreeze = value @@ -123,25 +99,64 @@ export class Immer { // Otherwise, produce a copy of the base state. return this.produce(base, draft => applyPatches(draft, patches)) } + /** @internal */ + processResult(result, scope) { + const baseDraft = scope.drafts[0] + const isReplaced = result !== undefined && result !== baseDraft + this.willFinalize(scope, result, isReplaced) + if (isReplaced) { + if (baseDraft[DRAFT_STATE].modified) { + scope.revoke() + throw new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.") // prettier-ignore + } + if (isDraftable(result)) { + // Finalize the result in case it contains (or is) a subset of the draft. + result = this.finalize(result, null, scope) + } + if (scope.patches) { + scope.patches.push({ + op: "replace", + path: [], + value: result + }) + scope.inversePatches.push({ + op: "replace", + path: [], + value: baseDraft[DRAFT_STATE].base + }) + } + } else { + // Finalize the base draft. + result = this.finalize(baseDraft, [], scope) + } + scope.revoke() + if (scope.patches) { + scope.patchListener(scope.patches, scope.inversePatches) + } + return result !== NOTHING ? result : undefined + } /** * @internal * Finalize a draft, returning either the unmodified base state or a modified * copy of the base state. */ - finalize(draft, path, patches, inversePatches) { + finalize(draft, path, scope) { const state = draft[DRAFT_STATE] if (!state) { if (Object.isFrozen(draft)) return draft - return this.finalizeTree(draft) + return this.finalizeTree(draft, null, scope) } - // Never finalize drafts owned by an outer scope. - if (state.scope !== this.currentScope()) { + // Never finalize drafts owned by another scope. + if (state.scope !== scope) { return draft } - if (!state.modified) return state.base + if (!state.modified) { + return state.base + } if (!state.finalized) { state.finalized = true - this.finalizeTree(state.draft, path, patches, inversePatches) + this.finalizeTree(state.draft, path, scope) + if (this.onDelete) { // The `assigned` object is unreliable with ES5 drafts. if (this.useProxies) { @@ -156,15 +171,24 @@ export class Immer { }) } } - if (this.onCopy) this.onCopy(state) + if (this.onCopy) { + this.onCopy(state) + } // Nested producers must never auto-freeze their result, // because it may contain drafts from parent producers. - if (this.autoFreeze && this.scopes.length === 1) { + if (this.autoFreeze && !scope.parent) { Object.freeze(state.copy) } - if (patches) generatePatches(state, path, patches, inversePatches) + if (path && scope.patches) { + generatePatches( + state, + path, + scope.patches, + scope.inversePatches + ) + } } return state.copy } @@ -172,7 +196,7 @@ export class Immer { * @internal * Finalize all drafts in the given state tree. */ - finalizeTree(root, path, patches, inversePatches) { + finalizeTree(root, path, scope) { const state = root[DRAFT_STATE] if (state) { if (!this.useProxies) { @@ -193,11 +217,14 @@ export class Immer { const inDraft = !!state && parent === root if (isDraft(value)) { - value = - // Patches are never generated for assigned properties. - patches && inDraft && !state.assigned[prop] - ? this.finalize(value, path.concat(prop), patches, inversePatches) // prettier-ignore - : this.finalize(value) + const needPatches = + inDraft && path && scope.patches && !state.assigned[prop] + + value = this.finalize( + value, + needPatches ? path.concat(prop) : null, + scope + ) // Preserve non-enumerable properties. if (Array.isArray(parent) || isEnumerable(parent, prop)) { diff --git a/src/proxy.js b/src/proxy.js index 6aee2a64..cdd6a1f0 100644 --- a/src/proxy.js +++ b/src/proxy.js @@ -1,6 +1,4 @@ "use strict" -// @ts-check - import { assign, each, @@ -11,18 +9,16 @@ import { shallowCopy, DRAFT_STATE } from "./common" - -// For nested produce calls: -export const scopes = [] -export const currentScope = () => scopes[scopes.length - 1] +import {ImmerScope} from "./scope" // Do nothing before being finalized. export function willFinalize() {} export function createDraft(base, parent) { + const scope = parent ? parent.scope : ImmerScope.current const state = { // Track which produce call this is associated with. - scope: parent ? parent.scope : currentScope(), + scope, // True for both shallow and deep changes. modified: false, // Used during finalization. @@ -50,7 +46,7 @@ export function createDraft(base, parent) { state.draft = proxy state.revoke = revoke - state.scope.push(state) + scope.drafts.push(proxy) return proxy } diff --git a/src/scope.js b/src/scope.js new file mode 100644 index 00000000..11349728 --- /dev/null +++ b/src/scope.js @@ -0,0 +1,38 @@ +import {DRAFT_STATE} from "./common" + +/** Each scope represents a `produce` call. */ +export class ImmerScope { + constructor(parent) { + this.drafts = [] + this.parent = parent + + // To avoid prototype lookups: + this.patches = null + } + usePatches(patchListener) { + if (patchListener) { + this.patches = [] + this.inversePatches = [] + this.patchListener = patchListener + } + } + revoke() { + this.leave() + this.drafts.forEach(revoke) + this.drafts = null // Make draft-related methods throw. + } + leave() { + if (this === ImmerScope.current) { + ImmerScope.current = this.parent + } + } +} + +ImmerScope.current = null +ImmerScope.enter = function() { + return (this.current = new ImmerScope(this.current)) +} + +function revoke(draft) { + draft[DRAFT_STATE].revoke() +} diff --git a/yarn.lock b/yarn.lock index bdfdc2fe..ab72e47b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,14 +52,14 @@ acorn@^5.2.1, acorn@^5.5.3: integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" - integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg== + version "6.0.6" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.6.tgz#cd75181670d5b99bdb1b1c993941d3a239ab1f56" + integrity sha512-5M3G/A4uBSMIlfJ+h9W125vJvPFH/zirISsW5qfxF5YzEvXJCtolLoQvM5yZft0DvMcUrPGKPOlgEu55I6iUtA== ajv@^6.5.5: - version "6.6.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.1.tgz#6360f5ed0d80f232cc2b294c362d5dc2e538dd61" - integrity sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww== + version "6.7.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.7.0.tgz#e3ce7bb372d6577bb1839f1dfdfcbf5ad2948d96" + integrity sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -74,9 +74,9 @@ ansi-align@^2.0.0: string-width "^2.0.0" ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-regex@^2.0.0: version "2.1.1" @@ -165,6 +165,11 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-differ@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.0.3.tgz#0195bb00ccccf271106efee4a4786488b7180712" + integrity sha1-AZW7AMzM8nEQbv7kpHhkiLcYBxI= + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -185,6 +190,18 @@ array-reduce@~0.0.0: resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= +array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -1053,9 +1070,9 @@ camelcase@^4.0.0, camelcase@^4.1.0: integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= caniuse-lite@^1.0.30000844: - version "1.0.30000921" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz#7a607c1623444b22351d834e093aedda3c42fbe8" - integrity sha512-Bu09ciy0lMWLgpYC77I0YGuI8eFRBPPzaSOYJK1jTI64txCphYCqnWbxJYjHABYVt/TYX/p3jNjLBR87u1Bfpw== + version "1.0.30000933" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000933.tgz#5871ff54b3177675ae1c2a275b2aae7abf2b9222" + integrity sha512-d3QXv7eFTU40DSedSP81dV/ajcGSKpT+GW+uhtWmLvQm9bPk0KK++7i1e2NSW/CXGZhWFt2mFbFtCJ5I5bMuVA== capture-exit@^1.2.0: version "1.2.0" @@ -1081,9 +1098,9 @@ chalk@^1.1.3: supports-color "^2.0.0" chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1115,6 +1132,11 @@ ci-info@^1.5.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1224,9 +1246,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0, core-js@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.0.tgz#1e30793e9ee5782b307e37ffa22da0eacddd84d4" - integrity sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw== + version "2.6.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.3.tgz#4b70938bdffdaf64931e66e2db158f0892289c49" + integrity sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -1463,9 +1485,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.3.47: - version "1.3.92" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz#9027b5abaea400045edd652c0e4838675c814399" - integrity sha512-En051LMzMl3/asMWGZEtU808HOoVWIpmmZx1Ep8N+TT9e7z/X8RcLeBU2kLSNLGQ+5SuKELzMx+MVuTBXk6Q9w== + version "1.3.109" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.109.tgz#ee04a55a5157a5580a5ea88e526b02c84a3a7bc8" + integrity sha512-1qhgVZD9KIULMyeBkbjU/dWmm30zpPUfdWZfVO3nPhbtqMHJqHr4Ua5wBcWtAymVFrUCuAJxjMF1OhG+bR21Ow== end-of-stream@^1.1.0: version "1.4.1" @@ -1482,17 +1504,18 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.5.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== dependencies: - es-to-primitive "^1.1.1" + es-to-primitive "^1.2.0" function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" + has "^1.0.3" + is-callable "^1.1.4" is-regex "^1.0.4" + object-keys "^1.0.12" -es-to-primitive@^1.1.1: +es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== @@ -1833,9 +1856,9 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.0.0, fsevents@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== + version "1.2.7" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.7.tgz#4851b664a3783e52003b3c66eb0eee1074933aa4" + integrity sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw== dependencies: nan "^2.9.2" node-pre-gyp "^0.10.0" @@ -1915,7 +1938,7 @@ glob2base@^0.0.12: dependencies: find-index "^0.1.1" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -2036,7 +2059,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1: +has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -2073,15 +2096,15 @@ http-signature@~1.2.0: sshpk "^1.7.0" husky@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/husky/-/husky-1.2.1.tgz#33628f7013e345c1790a4dbe4642ad047f772dee" - integrity sha512-4Ylal3HWhnDvIszuiyLoVrSGI7QLg/ogkNCoHE34c+yZYzb9kBZNrlTOsdw92cGi3cJT8pPb6CdVfxFkLnc8Dg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/husky/-/husky-1.3.1.tgz#26823e399300388ca2afff11cfa8a86b0033fae0" + integrity sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg== dependencies: cosmiconfig "^5.0.7" execa "^1.0.0" find-up "^3.0.0" get-stdin "^6.0.0" - is-ci "^1.2.1" + is-ci "^2.0.0" pkg-dir "^3.0.0" please-upgrade-node "^3.1.1" read-pkg "^4.0.1" @@ -2163,6 +2186,11 @@ invert-kv@^1.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= +ip-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-3.0.0.tgz#0a934694b4066558c46294244a23cc33116bf732" + integrity sha512-T8wDtjy+Qf2TAPDQmBp0eGKJ8GavlWlUnamr3wRn6vvdZlKVuJXXMlSncYFRYgVHOM3If5NR1H4+OvVQU9Idvg== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -2201,18 +2229,25 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.3, is-callable@^1.1.4: +is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== -is-ci@^1.0.10, is-ci@^1.2.1: +is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== dependencies: ci-info "^1.5.0" +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2787,9 +2822,9 @@ js-tokens@^3.0.2: integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@^3.11.0, js-yaml@^3.7.0, js-yaml@^3.9.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -3031,9 +3066,9 @@ map-visit@^1.0.0: object-visit "^1.0.0" math-random@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== mem@^1.1.0: version "1.1.0" @@ -3162,9 +3197,9 @@ mkdirp@^0.5.0, mkdirp@^0.5.1: minimist "0.0.8" mri@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.1.tgz#85aa26d3daeeeedf80dc5984af95cc5ca5cad9f1" - integrity sha1-haom09ru7t+A3FmEr5XMXKXK2fE= + version "1.1.4" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" + integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== ms@2.0.0: version "2.0.0" @@ -3176,10 +3211,20 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +multimatch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b" + integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA== + dependencies: + array-differ "^2.0.3" + array-union "^1.0.2" + arrify "^1.0.1" + minimatch "^3.0.4" + nan@^2.9.2: - version "2.11.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== nanomatch@^1.2.9: version "1.2.13" @@ -3257,9 +3302,9 @@ nopt@^4.0.1: osenv "^0.1.4" normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== + version "2.4.2" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.2.tgz#6b2abd85774e51f7936f1395e45acb905dc849b2" + integrity sha512-YcMnjqeoUckXTPKZSAsPjUPLxH85XotbpqK3w4RyCwdFQSU5FxxBys8buehkSfg0j9fKvV1hn7O0+8reEgkAiw== dependencies: hosted-git-info "^2.1.4" is-builtin-module "^1.0.0" @@ -3279,9 +3324,9 @@ npm-bundled@^1.0.1: integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-packlist@^1.1.6: - version "1.1.12" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== + version "1.2.0" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.2.0.tgz#55a60e793e272f00862c7089274439a4cc31fc7f" + integrity sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -3443,9 +3488,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" + integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== dependencies: p-try "^2.0.0" @@ -3530,7 +3575,7 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.5: +path-parse@^1.0.5, 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== @@ -3613,9 +3658,9 @@ preserve@^0.2.0: integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= prettier@^1.9.2: - version "1.15.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" - integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== + version "1.16.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d" + integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw== pretty-format@^22.4.0, pretty-format@^22.4.3: version "22.4.3" @@ -3626,15 +3671,16 @@ pretty-format@^22.4.0, pretty-format@^22.4.3: ansi-styles "^3.2.0" pretty-quick@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-1.8.0.tgz#067ebe744ddb4e1ed4e1ee1af9648815121f78fc" - integrity sha512-qV25sQF/ivJpdZ5efwemQYkQJa7sp3HqT/Vf/7z5vGYMcq1VrT2lDpFKAxJPf6219N1YAdR8mGkIhPAZ1odTmQ== + version "1.10.0" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-1.10.0.tgz#d86cc46fe92ed8cfcfba6a082ec5949c53858198" + integrity sha512-uNvm2N3UWmnZRZrClyQI45hIbV20f5BpSyZY51Spbvn4APp9+XLyX4bCjWRGT3fGyVyQ/2/iw7dbQq1UUaq7SQ== dependencies: chalk "^2.3.0" execa "^0.8.0" find-up "^2.1.0" ignore "^3.3.7" mri "^1.1.0" + multimatch "^3.0.0" private@^0.1.6, private@^0.1.8: version "0.1.8" @@ -3910,11 +3956,11 @@ resolve@1.1.7: integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.1.6, resolve@^1.1.7, resolve@^1.4.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" ret@~0.1.10: version "0.1.15" @@ -3922,11 +3968,11 @@ ret@~0.1.10: integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: - glob "^7.0.5" + glob "^7.1.3" rollup-plugin-babel@^3.0.3: version "3.0.7" @@ -4173,9 +4219,9 @@ source-map-support@^0.4.15: source-map "^0.5.6" source-map-support@^0.5.0: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" + integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -4217,9 +4263,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz#a59efc09784c2a5bada13cfeaf5c75dd214044d2" - integrity sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" + integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -4234,9 +4280,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629" - integrity sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA== + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -4436,7 +4482,16 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -tough-cookie@>=2.3.3, tough-cookie@^2.3.4: +tough-cookie@>=2.3.3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.0.tgz#d2bceddebde633153ff20a52fa844a0dc71dacef" + integrity sha512-LHMvg+RBP/mAVNqVbOX8t+iJ+tqhBA/t49DuI7+IDAWHrASnesqSu1vWbKB7UrE2yk+HMFUBMadRGMkB4VCfog== + dependencies: + ip-regex "^3.0.0" + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -4698,9 +4753,9 @@ wrappy@1: integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" - integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== + version "2.4.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9" + integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4"