├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── lib ├── blueprint.js ├── file-require-transform.js ├── generate-snapshot-script.js ├── index.js └── transform-cache.js ├── package-lock.json ├── package.json └── test ├── fixtures ├── cyclic-require │ ├── a.js │ ├── b.js │ ├── c.js │ ├── d.js │ └── e.js ├── module-1 │ ├── dir │ │ ├── a.js │ │ ├── c.json │ │ └── subdir │ │ │ └── b.js │ ├── index.js │ └── node_modules │ │ └── a │ │ └── index.js └── module-2 │ └── index.js ├── samples ├── .gitignore ├── alias-global-function.js └── list-globals.js └── unit ├── file-require-transform.test.js └── generate-snapshot-script.test.js /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | env: 6 | CI: true 7 | 8 | jobs: 9 | Test: 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest] 13 | runs-on: ${{ matrix.os }} 14 | steps: 15 | - uses: actions/checkout@v1 16 | - uses: actions/setup-node@v2 17 | with: 18 | node-version: '14' 19 | - name: Install windows-build-tools 20 | if: ${{ matrix.os == 'windows-latest' }} 21 | run: npm config set msvs_version 2019 22 | - name: Install dependencies 23 | run: npm i 24 | - name: Run tests 25 | run: npm test 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | .DS_Store 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .npmrc 2 | .babelrc 3 | appveyor.yml 4 | test 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2017 GitHub Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) 2 | # electron-link 3 | 4 | electron-link is a node module that takes a JavaScript file (typically the entry point of an application) and a list of modules that need to be required lazily (see [Atom's build scripts](https://github.com/atom/atom/blob/d9ebd7e125d5f07def1a057a0a8278d4d9d7d23a/script/lib/generate-startup-snapshot.js#L19-L65) for an example). Then, starting from that file, it traverses the entire require graph and replaces all the forbidden `require` calls in each file with a function that will be called at runtime. The output is a single script containing the code for all the modules reachable from the entry point. This file can be then supplied to `mksnapshot` to generate a snapshot blob. 5 | 6 | It can also determine whether a module can be snapshotted or not. For instance, the following code can be snapshotted: 7 | 8 | ```js 9 | const path = require('path') 10 | 11 | module.exports = function () { 12 | return path.join('a', 'b', 'c') 13 | } 14 | ``` 15 | 16 | And generates the following code: 17 | 18 | ```js 19 | let path; 20 | function get_path () { 21 | return path || path = require('path'); 22 | } 23 | 24 | module.exports = function () { 25 | return get_path().join('a', 'b', 'c') 26 | } 27 | ``` 28 | 29 | You can notice that the above code is valid because the forbidden module (i.e. `path`) is used inside a function that doesn't get called when requiring the script. On the other hand, when trying to process the following code, electron-link will throw an error because it is trying to access a forbidden module right when it gets required: 30 | 31 | ```js 32 | const path = require('path') 33 | 34 | module.exports = path.join('a', 'b', 'c') 35 | ``` 36 | 37 | Being a tool based on static analysis, however, electron-link is unable to detect all the cases where a piece of code can't be included in a snapshot. Therefore, we recommend running the generated JavaScript file in an empty V8 context (similar to the one provided by `mksnapshot`) to catch any invalid code that might have slipped through. 38 | 39 | ## Installation 40 | 41 | ```bash 42 | npm install --save electron-link 43 | ``` 44 | 45 | ## Usage 46 | 47 | ```js 48 | const electronLink = require('electron-link') 49 | 50 | const snapshotScript = await electronLink({ 51 | baseDirPath: '/base/dir/path', 52 | mainPath: '/base/dir/path/main.js', 53 | cachePath: '/cache/path', 54 | shouldExcludeModule: (modulePath) => excludedModules.has(modulePath) 55 | }) 56 | 57 | const snapshotScriptPath = '/path/to/snapshot/script.js' 58 | fs.writeFileSync(snapshotScriptPath, snapshotScript) 59 | 60 | // Verify if we will be able to use this in `mksnapshot` 61 | vm.runInNewContext(snapshotScript, undefined, {filename: snapshotScriptPath, displayErrors: true}) 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /lib/blueprint.js: -------------------------------------------------------------------------------- 1 | var snapshotAuxiliaryData = {} 2 | 3 | function generateSnapshot () { 4 | const outerScope = this 5 | 6 | let process = {} 7 | Object.defineProperties(process, { 8 | 'platform': {value: 'processPlatform', enumerable: false}, 9 | 'argv': {value: [], enumerable: false}, 10 | 'env': {value: {'NODE_ENV': 'production'}, enumerable: false} 11 | }) 12 | function get_process () { 13 | return process 14 | } 15 | 16 | function createElement(_type) { 17 | return { 18 | innerHTML: '', 19 | style: {} 20 | } 21 | } 22 | 23 | let documentElement = { 24 | textContent: '', 25 | style: { 26 | cssFloat: '' 27 | } 28 | } 29 | let document = {} 30 | Object.defineProperties(document, { 31 | 'createElement': {value: createElement, enumerable: false}, 32 | 'addEventListener': {value: function() {}, enumerable: false}, 33 | 'documentElement': {value: documentElement, enumerable: false}, 34 | 'oninput': {value: {}, enumerable: false}, 35 | 'onchange': {value: {}, enumerable: false} 36 | }) 37 | function get_document () { 38 | return document 39 | } 40 | 41 | let global = {} 42 | Object.defineProperties(global, { 43 | 'document': {value: document, enumerable: false}, 44 | 'process': {value: process, enumerable: false}, 45 | 'WeakMap': {value: WeakMap, enumerable: false}, 46 | 'isGeneratingSnapshot': {value: true, enumerable: false} 47 | }) 48 | function get_global () { 49 | return global 50 | } 51 | 52 | // Globally visible function and constructor names that are available in an Electron renderer window, but not visible 53 | // during snapshot creation. 54 | // See test/samples/list-globals.js for the generation code. 55 | // - Manually remove "webkitURL" which is deprecated to avoid a warning on startup. 56 | const globalFunctionNames = [ 57 | "USBOutTransferResult", "USBIsochronousOutTransferResult", "USBIsochronousOutTransferPacket", 58 | "USBIsochronousInTransferResult", "USBIsochronousInTransferPacket", "USBInTransferResult", "USBInterface", 59 | "USBEndpoint", "USBDevice", "USBConnectionEvent", "USBConfiguration", "USBAlternateInterface", "USB", "NFC", 60 | "BluetoothUUID", "BluetoothRemoteGATTService", "BluetoothRemoteGATTServer", "BluetoothRemoteGATTDescriptor", 61 | "BluetoothRemoteGATTCharacteristic", "BluetoothDevice", "BluetoothCharacteristicProperties", "Bluetooth", 62 | "WebAuthentication", "PublicKeyCredential", "AuthenticatorResponse", "AuthenticatorAttestationResponse", 63 | "AuthenticatorAssertionResponse", "WebGLRenderingContext", "WebGL2RenderingContext", "Path2D", "CanvasPattern", 64 | "CanvasGradient", "TextDetector", "FaceDetector", "DetectedText", "DetectedFace", "DetectedBarcode", 65 | "BarcodeDetector", "NavigationPreloadManager", "SensorErrorEvent", "Sensor", "RelativeOrientationSensor", 66 | "OrientationSensor", "Magnetometer", "LinearAccelerationSensor", "Gyroscope", "AmbientLightSensor", "Accelerometer", 67 | "AbsoluteOrientationSensor", "webkitSpeechRecognitionEvent", "webkitSpeechRecognitionError", 68 | "webkitSpeechRecognition", "webkitSpeechGrammarList", "webkitSpeechGrammar", "SpeechSynthesisUtterance", 69 | "SpeechSynthesisEvent", "RemotePlayback", "RTCRtpSender", "PushSubscriptionOptions", "PushSubscription", 70 | "PushManager", "PresentationReceiver", "PresentationConnectionList", "PresentationRequest", 71 | "PresentationConnectionCloseEvent", "PresentationConnectionAvailableEvent", "PresentationConnection", 72 | "PresentationAvailability", "Presentation", "PermissionStatus", "Permissions", "PaymentResponse", 73 | "PaymentRequestUpdateEvent", "PaymentRequest", "PaymentAddress", "PaymentManager", "Notification", 74 | "VideoPlaybackQuality", "TrackDefaultList", "TrackDefault", "CanvasCaptureMediaStreamTrack", "PhotoCapabilities", 75 | "MediaSettingsRange", "ImageCapture", "IDBObserverChanges", "IDBObserver", "IDBObservation", "StorageManager", 76 | "CompositorWorker", "BudgetService", "BroadcastChannel", "SyncManager", "BackgroundFetchRegistration", 77 | "BackgroundFetchManager", "BackgroundFetchFetch", "AudioParamMap", "XSLTProcessor", "Worklet", "VTTRegion", 78 | "KeyframeEffectReadOnly", "KeyframeEffect", "DocumentTimeline", "AnimationTimeline", "AnimationPlaybackEvent", 79 | "AnimationEffectTimingReadOnly", "AnimationEffectTiming", "AnimationEffectReadOnly", "Animation", "VisualViewport", 80 | "SharedWorker", "PerformanceServerTiming", "SVGMPathElement", "SVGDiscardElement", "SVGAnimationElement", 81 | "ResizeObserverEntry", "ResizeObserver", "PerformancePaintTiming", "PerformanceObserverEntryList", 82 | "PerformanceObserver", "PerformanceNavigationTiming", "IntersectionObserverEntry", "IntersectionObserver", 83 | "StaticRange", "InputEvent", "DOMRectReadOnly", "DOMRect", "DOMQuad", "DOMPointReadOnly", "DOMPoint", 84 | "DOMMatrixReadOnly", "DOMMatrix", "ScrollTimeline", "StylePropertyMapReadonly", "StylePropertyMap", 85 | "CSSVariableReferenceValue", "CSSURLImageValue", "CSSUnparsedValue", "CSSUnitValue", "CSSTranslation", 86 | "CSSTransformValue", "CSSTransformComponent", "CSSStyleValue", "CSSSkew", "CSSScale", "CSSRotation", 87 | "CSSResourceValue", "CSSPositionValue", "CSSPerspective", "CSSNumericValue", "CSSMatrixComponent", 88 | "CSSKeywordValue", "CSSImageValue", "VideoTrackList", "VideoTrack", "AudioTrackList", "AudioTrack", 89 | "AccessibleNodeList", "AccessibleNode", "webkitRTCPeerConnection", "webkitMediaStream", "WebSocket", 90 | "WebGLVertexArrayObject", "WebGLUniformLocation", "WebGLTransformFeedback", "WebGLTexture", "WebGLSync", 91 | "WebGLShaderPrecisionFormat", "WebGLShader", "WebGLSampler", "WebGLRenderbuffer", "WebGLQuery", "WebGLProgram", 92 | "WebGLFramebuffer", "WebGLContextEvent", "WebGLBuffer", "WebGLActiveInfo", "WaveShaperNode", "TextEncoder", 93 | "TextDecoder", "SubtleCrypto", "StorageEvent", "Storage", "StereoPannerNode", "SourceBufferList", "SourceBuffer", 94 | "ServiceWorkerRegistration", "ServiceWorkerContainer", "ServiceWorker", "ScriptProcessorNode", "ScreenOrientation", 95 | "Response", "Request", "RTCStatsReport", "RTCSessionDescription", "RTCRtpReceiver", "RTCRtpContributingSource", 96 | "RTCPeerConnectionIceEvent", "RTCPeerConnection", "RTCIceCandidate", "RTCDataChannelEvent", "RTCDataChannel", 97 | "RTCCertificate", "Plugin", "PluginArray", "PeriodicWave", "PasswordCredential", "PannerNode", "OscillatorNode", 98 | "OfflineAudioContext", "OfflineAudioCompletionEvent", "NetworkInformation", "MimeType", "MimeTypeArray", 99 | "MediaStreamTrackEvent", "MediaStreamTrack", "MediaStreamEvent", "MediaStream", "MediaStreamAudioSourceNode", 100 | "MediaStreamAudioDestinationNode", "MediaSource", "MediaRecorder", "MediaKeys", "MediaKeySystemAccess", 101 | "MediaKeyStatusMap", "MediaKeySession", "MediaKeyMessageEvent", "MediaEncryptedEvent", 102 | "MediaElementAudioSourceNode", "MediaDevices", "MediaDeviceInfo", "MIDIPort", "MIDIOutputMap", "MIDIOutput", 103 | "MIDIMessageEvent", "MIDIInputMap", "MIDIInput", "MIDIConnectionEvent", "MIDIAccess", "ImageBitmapRenderingContext", 104 | "IIRFilterNode", "IDBVersionChangeEvent", "IDBTransaction", "IDBRequest", "IDBOpenDBRequest", "IDBObjectStore", 105 | "IDBKeyRange", "IDBIndex", "IDBFactory", "IDBDatabase", "IDBCursorWithValue", "IDBCursor", "Headers", 106 | "GamepadEvent", "Gamepad", "GamepadButton", "GainNode", "FederatedCredential", "EventSource", 107 | "DynamicsCompressorNode", "DeviceOrientationEvent", "DeviceMotionEvent", "DelayNode", "DOMError", "CryptoKey", 108 | "Crypto", "CredentialsContainer", "Credential", "ConvolverNode", "ConstantSourceNode", "CloseEvent", 109 | "ChannelSplitterNode", "ChannelMergerNode", "CanvasRenderingContext2D", "CacheStorage", "Cache", "BlobEvent", 110 | "BiquadFilterNode", "BeforeInstallPromptEvent", "BatteryManager", "BaseAudioContext", "AudioScheduledSourceNode", 111 | "AudioProcessingEvent", "AudioParam", "AudioNode", "AudioListener", "AudioDestinationNode", "AudioContext", 112 | "AudioBufferSourceNode", "AudioBuffer", "AppBannerPromptResult", "AnalyserNode", "postMessage", "blur", "focus", 113 | "close", "XPathResult", "XPathExpression", "XPathEvaluator", "XMLSerializer", "XMLHttpRequestUpload", 114 | "XMLHttpRequestEventTarget", "XMLHttpRequest", "XMLDocument", "Worker", "Window", "WheelEvent", "ValidityState", 115 | "VTTCue", "URLSearchParams", "URL", "UIEvent", "TreeWalker", "TransitionEvent", "TrackEvent", "TouchList", 116 | "TouchEvent", "Touch", "TimeRanges", "TextTrackList", "TextTrackCueList", "TextTrackCue", "TextTrack", 117 | "TextMetrics", "TextEvent", "Text", "TaskAttributionTiming", "StyleSheetList", "StyleSheet", "ShadowRoot", 118 | "Selection", "SecurityPolicyViolationEvent", "Screen", "SVGViewElement", "SVGUseElement", "SVGUnitTypes", 119 | "SVGTransformList", "SVGTransform", "SVGTitleElement", "SVGTextPositioningElement", "SVGTextPathElement", 120 | "SVGTextElement", "SVGTextContentElement", "SVGTSpanElement", "SVGSymbolElement", "SVGSwitchElement", 121 | "SVGStyleElement", "SVGStringList", "SVGStopElement", "SVGSetElement", "SVGScriptElement", "SVGSVGElement", 122 | "SVGRectElement", "SVGRect","SVGRadialGradientElement", "SVGPreserveAspectRatio", "SVGPolylineElement", 123 | "SVGPolygonElement", "SVGPointList", "SVGPoint", "SVGPatternElement", "SVGPathElement", "SVGNumberList", 124 | "SVGNumber", "SVGMetadataElement","SVGMatrix", "SVGMaskElement", "SVGMarkerElement", "SVGLinearGradientElement", 125 | "SVGLineElement", "SVGLengthList", "SVGLength", "SVGImageElement", "SVGGraphicsElement", "SVGGradientElement", 126 | "SVGGeometryElement", "SVGGElement", "SVGForeignObjectElement", "SVGFilterElement", "SVGFETurbulenceElement", 127 | "SVGFETileElement", "SVGFESpotLightElement", "SVGFESpecularLightingElement", "SVGFEPointLightElement", 128 | "SVGFEOffsetElement", "SVGFEMorphologyElement", "SVGFEMergeNodeElement", "SVGFEMergeElement", "SVGFEImageElement", 129 | "SVGFEGaussianBlurElement", "SVGFEFuncRElement", "SVGFEFuncGElement", "SVGFEFuncBElement", "SVGFEFuncAElement", 130 | "SVGFEFloodElement", "SVGFEDropShadowElement", "SVGFEDistantLightElement", "SVGFEDisplacementMapElement", 131 | "SVGFEDiffuseLightingElement", "SVGFEConvolveMatrixElement", "SVGFECompositeElement", 132 | "SVGFEComponentTransferElement", "SVGFEColorMatrixElement", "SVGFEBlendElement", "SVGEllipseElement", "SVGElement", 133 | "SVGDescElement", "SVGDefsElement", "SVGComponentTransferFunctionElement", "SVGClipPathElement", "SVGCircleElement", 134 | "SVGAnimatedTransformList", "SVGAnimatedString", "SVGAnimatedRect", "SVGAnimatedPreserveAspectRatio", 135 | "SVGAnimatedNumberList", "SVGAnimatedNumber", "SVGAnimatedLengthList", "SVGAnimatedLength", "SVGAnimatedInteger", 136 | "SVGAnimatedEnumeration", "SVGAnimatedBoolean", "SVGAnimatedAngle", "SVGAnimateTransformElement", 137 | "SVGAnimateMotionElement", "SVGAnimateElement", "SVGAngle", "SVGAElement", "Range", "RadioNodeList", 138 | "PromiseRejectionEvent", "ProgressEvent","ProcessingInstruction", "PopStateEvent", "PointerEvent", 139 | "PerformanceTiming", "PerformanceResourceTiming", "PerformanceNavigation", "PerformanceMeasure", "PerformanceMark", 140 | "PerformanceLongTaskTiming", "PerformanceEntry", "Performance", "PageTransitionEvent", "NodeList", "NodeIterator", 141 | "NodeFilter", "Node", "Navigator", "NamedNodeMap", "MutationRecord", "MutationObserver", "MutationEvent", 142 | "MouseEvent", "MessagePort", "MessageEvent", "MessageChannel", "MediaQueryListEvent", "MediaQueryList", "MediaList", 143 | "MediaError", "Location", "KeyboardEvent", "InputDeviceCapabilities", "ImageData", "ImageBitmap", "IdleDeadline", 144 | "History", "HashChangeEvent", "HTMLVideoElement", "HTMLUnknownElement", "HTMLUListElement", "HTMLTrackElement", 145 | "HTMLTitleElement", "HTMLTextAreaElement", "HTMLTemplateElement", "HTMLTableSectionElement", "HTMLTableRowElement", 146 | "HTMLTableElement", "HTMLTableColElement", "HTMLTableCellElement", "HTMLTableCaptionElement", "HTMLStyleElement", 147 | "HTMLSpanElement", "HTMLSourceElement", "HTMLSlotElement", "HTMLShadowElement", "HTMLSelectElement", 148 | "HTMLScriptElement", "HTMLQuoteElement", "HTMLProgressElement", "HTMLPreElement", "HTMLPictureElement", 149 | "HTMLParamElement", "HTMLParagraphElement", "HTMLOutputElement", "HTMLOptionsCollection", "Option", 150 | "HTMLOptionElement", "HTMLOptGroupElement", "HTMLObjectElement", "HTMLOListElement", "HTMLModElement", 151 | "HTMLMeterElement", "HTMLMetaElement", "HTMLMenuElement", "HTMLMediaElement", "HTMLMarqueeElement", 152 | "HTMLMapElement", "HTMLLinkElement", "HTMLLegendElement", "HTMLLabelElement", "HTMLLIElement", "HTMLInputElement", 153 | "Image", "HTMLImageElement", "HTMLIFrameElement", "HTMLHtmlElement", "HTMLHeadingElement", "HTMLHeadElement", 154 | "HTMLHRElement", "HTMLFrameSetElement", "HTMLFrameElement", "HTMLFormElement", "HTMLFormControlsCollection", 155 | "HTMLFontElement", "HTMLFieldSetElement", "HTMLEmbedElement", "HTMLElement", "HTMLDocument", "HTMLDivElement", 156 | "HTMLDirectoryElement", "HTMLDialogElement", "HTMLDetailsElement", "HTMLDataListElement", "HTMLDListElement", 157 | "HTMLContentElement", "HTMLCollection", "HTMLCanvasElement", "HTMLButtonElement", "HTMLBodyElement", 158 | "HTMLBaseElement", "HTMLBRElement", "Audio", "HTMLAudioElement", "HTMLAreaElement", "HTMLAnchorElement", 159 | "HTMLAllCollection", "FormData", "FontFaceSetLoadEvent", "FontFace", "FocusEvent", "FileReader", "FileList", "File", 160 | "EventTarget", "Event", "ErrorEvent", "Element", "DragEvent", "DocumentType", "DocumentFragment", "Document", 161 | "DataTransferItemList", "DataTransferItem", "DataTransfer", "DOMTokenList", "DOMStringMap", "DOMStringList", 162 | "DOMParser", "DOMImplementation", "DOMException", "CustomEvent", "CustomElementRegistry", "CompositionEvent", 163 | "Comment", "ClipboardEvent", "Clipboard", "CharacterData", "CSSViewportRule", "CSSSupportsRule", "CSSStyleSheet", 164 | "CSSStyleRule", "CSSStyleDeclaration", "CSSRuleList", "CSSRule", "CSSPageRule", "CSSNamespaceRule", "CSSMediaRule", 165 | "CSSKeyframesRule", "CSSKeyframeRule", "CSSImportRule", "CSSGroupingRule", "CSSFontFaceRule", "CSS", 166 | "CSSConditionRule", "CDATASection", "Blob", "BeforeUnloadEvent", "BarProp", "Attr", "ApplicationCacheErrorEvent", 167 | "ApplicationCache", "AnimationEvent", "WebKitCSSMatrix", "WebKitMutationObserver", 168 | "WebKitAnimationEvent", "WebKitTransitionEvent", "onerror", "onload", "stop", "open", "alert", "confirm", "prompt", 169 | "print", "requestAnimationFrame", "cancelAnimationFrame", "requestIdleCallback", "cancelIdleCallback", 170 | "captureEvents", "releaseEvents", "getComputedStyle", "matchMedia", "moveTo", "moveBy", "resizeTo", "resizeBy", 171 | "getSelection", "find", "getMatchedCSSRules", "webkitRequestAnimationFrame", "webkitCancelAnimationFrame", "btoa", 172 | "atob", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "createImageBitmap", "scroll", "scrollTo", 173 | "scrollBy", "fetch", "getComputedStyleMap", "webkitRequestFileSystem", "webkitResolveLocalFileSystemURL", 174 | "openDatabase", "SharedArrayBuffer", "Buffer", "setImmediate", "clearImmediate", "require", "BudgetState", 175 | "WebView", "measure", "profile", "dir", "dirxml", "profileEnd", "clear", "table", "keys", "values", "debug", 176 | "undebug", "monitor", "unmonitor", "inspect", "copy", "getEventListeners", "monitorEvents", "unmonitorEvents", "$", 177 | "$$", "$x", 178 | ] 179 | 180 | // During snapshot generation, this is null. 181 | // After snapshot load and setGlobals() is called, this is an object with global function names as keys and the real 182 | // global functions as values. 183 | let globalFunctionTrampoline = null 184 | 185 | // Create a placeholder function to install as a global in place of a function that may be available after snapshot 186 | // load, at runtime. Uses the current state of globalFunctionTrampoline to either call the real function or throw 187 | // an appropriate error for improper use. 188 | function makeGlobalPlaceholder(globalFunctionName) { 189 | return function() { 190 | if (globalFunctionTrampoline === null) { 191 | throw new Error(`Attempt to call ${globalFunctionName} during snapshot generation or before snapshotResult.setGlobals()`) 192 | } else if (globalFunctionTrampoline[globalFunctionName] === undefined) { 193 | throw new ReferenceError(`Global method ${globalFunctionName} was still not defined after the snapshot was loaded`) 194 | } else if (new.target === undefined) { 195 | // Not called as a constructor 196 | return globalFunctionTrampoline[globalFunctionName](...arguments) 197 | } else { 198 | // Called as a constructor 199 | return new globalFunctionTrampoline[globalFunctionName](...arguments) 200 | } 201 | } 202 | } 203 | 204 | // Install a placeholder function for each global function we expect to have access to at runtime. Placeholder 205 | // functions are set as properties on our "global" stand-in and also in this function's scope, so bare references 206 | // will also capture the placeholder function (`var a = setTimeout` and `var a = global.setTimeout`). 207 | for (const globalFunctionName of globalFunctionNames) { 208 | if (outerScope[globalFunctionName] !== undefined) { 209 | // This happens when the snapshot script is eval'd in tests. 210 | continue; 211 | } 212 | const placeholder = makeGlobalPlaceholder(globalFunctionName); 213 | Object.defineProperties(global, { 214 | [globalFunctionName]: {value: placeholder, enumerable: false}, 215 | }) 216 | outerScope[globalFunctionName] = placeholder; 217 | } 218 | 219 | let window = {} 220 | Object.defineProperties(window, { 221 | 'document': {value: document, enumerable: false}, 222 | 'location': {value: {href: ''}, enumerable: false}, 223 | 'addEventListener': {value: function(){}, enumerable: false}, 224 | 'screen': {value: {}, enumerable: false}, 225 | }) 226 | function get_window () { 227 | return window 228 | } 229 | 230 | let console = {} 231 | function consoleNoop () { 232 | throw new Error('Cannot use `console` functions in the snapshot.') 233 | } 234 | Object.defineProperties(console, { 235 | 'debug': {value: consoleNoop, enumerable: false}, 236 | 'error': {value: consoleNoop, enumerable: false}, 237 | 'info': {value: consoleNoop, enumerable: false}, 238 | 'log': {value: consoleNoop, enumerable: false}, 239 | 'warn': {value: consoleNoop, enumerable: false}, 240 | 'time': {value: consoleNoop, enumerable: false}, 241 | 'timeEnd': {value: consoleNoop, enumerable: false} 242 | }) 243 | function get_console () { 244 | return console 245 | } 246 | 247 | let require = (moduleName) => { 248 | throw new Error( 249 | `Cannot require module "${moduleName}".\n` + 250 | "To use Node's require you need to call `snapshotResult.setGlobals` first!" 251 | ) 252 | } 253 | 254 | function customRequire (modulePath) { 255 | let module = customRequire.cache[modulePath] 256 | if (!module) { 257 | module = {exports: {}} 258 | const dirname = modulePath.split('/').slice(0, -1).join('/') 259 | 260 | function define (callback) { 261 | callback(customRequire, module.exports, module) 262 | } 263 | 264 | if (customRequire.definitions.hasOwnProperty(modulePath)) { 265 | customRequire.cache[modulePath] = module 266 | customRequire.definitions[modulePath].apply(module.exports, [module.exports, module, modulePath, dirname, customRequire, define]) 267 | } else { 268 | module.exports = require(modulePath) 269 | customRequire.cache[modulePath] = module 270 | } 271 | } 272 | return module.exports 273 | } 274 | customRequire.extensions = {} 275 | customRequire.cache = {} 276 | customRequire.definitions = {} 277 | customRequire.resolve = function (mod) { 278 | return require.resolve(mod) 279 | } 280 | 281 | customRequire(mainModuleRequirePath) 282 | return { 283 | customRequire, 284 | setGlobals: function (newGlobal, newProcess, newWindow, newDocument, newConsole, nodeRequire) { 285 | // Populate the global function trampoline with the real global functions defined on newGlobal. 286 | globalFunctionTrampoline = newGlobal; 287 | 288 | for (let key of Object.keys(global)) { 289 | newGlobal[key] = global[key] 290 | } 291 | global = newGlobal 292 | 293 | for (let key of Object.keys(process)) { 294 | newProcess[key] = process[key] 295 | } 296 | process = newProcess 297 | 298 | for (let key of Object.keys(window)) { 299 | newWindow[key] = window[key] 300 | } 301 | window = newWindow 302 | 303 | for (let key of Object.keys(document)) { 304 | newDocument[key] = document[key] 305 | } 306 | document = newDocument 307 | 308 | for (let key of Object.keys(console)) { 309 | newConsole[key] = console[key] 310 | } 311 | console = newConsole 312 | 313 | require = nodeRequire 314 | }, 315 | translateSnapshotRow: function (row) { 316 | let low = 0 317 | let high = snapshotAuxiliaryData.snapshotSections.length - 1 318 | while (low <= high) { 319 | const mid = low + (high - low >> 1) 320 | const section = snapshotAuxiliaryData.snapshotSections[mid] 321 | if (row < section.startRow) { 322 | high = mid - 1 323 | } else if (row >= section.endRow) { 324 | low = mid + 1 325 | } else { 326 | return { 327 | relativePath: section.relativePath, 328 | row: row - section.startRow 329 | } 330 | } 331 | } 332 | 333 | return {relativePath: '', row: row} 334 | } 335 | } 336 | } 337 | 338 | snapshotAuxiliaryData.snapshotSections = [] 339 | var snapshotResult = generateSnapshot.call({}) 340 | // Delete the generateSnapshot function to prevent it from appearing in the 341 | // global scope and causing slowdowns when the function is particularly big. 342 | generateSnapshot = null 343 | -------------------------------------------------------------------------------- /lib/file-require-transform.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path') 3 | const recast = require('recast') 4 | const astUtil = require('ast-util-plus') 5 | const b = recast.types.builders 6 | const resolve = require('resolve') 7 | const acorn = require('recast/parsers/acorn') 8 | 9 | const GLOBALS = new Set(['global', 'window', 'process', 'document', 'console']) 10 | const NODE_CORE_MODULES = new Set([ 11 | 'assert', 'buffer', 'child_process', 'cluster', 'constants', 'crypto', 12 | 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 13 | 'os', 'path', 'punycode', 'querystring', 'readline', 'repl', 'stream', 14 | 'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib' 15 | ]) 16 | 17 | module.exports = class FileRequireTransform { 18 | constructor (options) { 19 | this.options = options 20 | } 21 | 22 | apply () { 23 | let source = this.options.source 24 | if (this.options.filePath && path.extname(this.options.filePath) === '.json') { 25 | // Replace line separator and paragraph separator character (which aren't 26 | // supported inside javascript strings) with escape unicode sequences. 27 | source = "module.exports = " + source.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029') 28 | } 29 | this.ast = recast.parse(source, { 30 | parser: { 31 | parse(source) { 32 | return acorn.parse(source, { 33 | ecmaVersion: 2020, 34 | sourceType: 'script' 35 | }) 36 | } 37 | } 38 | }) 39 | this.lazyRequireFunctionsByVariableName = new Map() 40 | this.replaceDeferredRequiresWithLazyFunctions() 41 | this.replaceReferencesToDeferredRequiresWithFunctionCalls() 42 | this.replaceReferencesToGlobalsWithFunctionCalls() 43 | return recast.print(this.ast).code 44 | } 45 | 46 | replaceDeferredRequiresWithLazyFunctions () { 47 | const self = this 48 | recast.types.visit(this.ast, { 49 | visitCallExpression: function (astPath) { 50 | if (isStaticRequire(astPath)) { 51 | const moduleName = astPath.node.arguments[0].value 52 | const absoluteModulePath = self.resolveModulePath(moduleName) 53 | if (absoluteModulePath) { 54 | let relativeModulePath = path.relative(self.options.baseDirPath, absoluteModulePath).replace(/\\/g, '/') 55 | if (!relativeModulePath.startsWith('.')) { 56 | relativeModulePath = './' + relativeModulePath 57 | } 58 | astPath.get('arguments', 0).replace(b.literal(relativeModulePath)) 59 | } 60 | 61 | const deferRequire = NODE_CORE_MODULES.has(moduleName) || self.options.didFindRequire(moduleName, absoluteModulePath || moduleName) 62 | if (deferRequire && isTopLevelASTPath(astPath)) { 63 | self.replaceAssignmentOrDeclarationWithLazyFunction(astPath) 64 | } 65 | } else if (isStaticRequireResolve(astPath)) { 66 | const moduleName = astPath.node.arguments[0].value 67 | const absoluteModulePath = self.resolveModulePath(moduleName) 68 | if (absoluteModulePath) { 69 | let relativeModulePath = path.relative(self.options.baseDirPath, absoluteModulePath).replace(/\\/g, '/') 70 | if (!relativeModulePath.startsWith('.')) { 71 | relativeModulePath = './' + relativeModulePath 72 | } 73 | astPath.get('arguments', 0).replace(b.literal(relativeModulePath)) 74 | } 75 | } 76 | this.traverse(astPath) 77 | } 78 | }) 79 | 80 | let foundReferenceToLazyRequire = true 81 | while (foundReferenceToLazyRequire) { 82 | foundReferenceToLazyRequire = false 83 | recast.types.visit(this.ast, { 84 | visitIdentifier: function (astPath) { 85 | if (isTopLevelASTPath(astPath) && self.isReferenceToLazyRequire(astPath)) { 86 | astPath.replace(b.callExpression(b.identifier(self.lazyRequireFunctionsByVariableName.get(astPath.node.name)), [])) 87 | self.replaceAssignmentOrDeclarationWithLazyFunction(astPath) 88 | foundReferenceToLazyRequire = true 89 | this.abort() 90 | } else { 91 | this.traverse(astPath) 92 | } 93 | } 94 | }) 95 | } 96 | } 97 | 98 | replaceReferencesToDeferredRequiresWithFunctionCalls () { 99 | const self = this 100 | recast.types.visit(this.ast, { 101 | visitIdentifier: function (astPath) { 102 | if (!isTopLevelASTPath(astPath) && self.isReferenceToLazyRequire(astPath) && !isReferenceToShadowedVariable(astPath)) { 103 | astPath.replace(b.callExpression(b.identifier(self.lazyRequireFunctionsByVariableName.get(astPath.node.name)), [])) 104 | } 105 | this.traverse(astPath) 106 | } 107 | }) 108 | } 109 | 110 | replaceReferencesToGlobalsWithFunctionCalls () { 111 | recast.types.visit(this.ast, { 112 | visitIdentifier: function (astPath) { 113 | if (astUtil.isReference(astPath) && !isReferenceToShadowedVariable(astPath) && GLOBALS.has(astPath.node.name)) { 114 | astPath.replace(b.callExpression(b.identifier(`get_${astPath.node.name}`), [])) 115 | } 116 | this.traverse(astPath) 117 | } 118 | }) 119 | } 120 | 121 | replaceAssignmentOrDeclarationWithLazyFunction (astPath) { 122 | let parentPath = astPath.parent 123 | while (parentPath != null && parentPath.scope === astPath.scope) { 124 | const parentNode = parentPath.node 125 | if (parentNode.type === 'AssignmentExpression') { 126 | const lazyRequireFunctionName = `get_${parentNode.left.name}` 127 | 128 | let ifStatementPath = parentPath.parent 129 | while (ifStatementPath && ifStatementPath.node.type !== 'IfStatement') { 130 | ifStatementPath = ifStatementPath.parent 131 | } 132 | 133 | 134 | let assignmentLhs = parentNode.left 135 | while (assignmentLhs.type === 'MemberExpression') { 136 | assignmentLhs = assignmentLhs.object 137 | } 138 | assert.equal(assignmentLhs.type, 'Identifier') 139 | 140 | if (["module", "exports"].includes(assignmentLhs.name)) { 141 | console.warn(`##[warning] The reference to the module is replaced with the lazy function, but it is assigned to "module" or "exports". In some cases the bundle might not work, which you should fix manually: \n ${this.options.filePath} \n`); 142 | return // don't replace anything (module.exports = get_name) 143 | } 144 | 145 | // Ensure we're assigning to a variable declared in this scope. 146 | assert( 147 | astPath.scope.declares(assignmentLhs.name), 148 | `${this.options.filePath}\nAssigning a deferred module to a variable that was not declared in this scope is not supported!` 149 | ) 150 | 151 | // Replace assignment with lazy function 152 | let replacement = null 153 | if (ifStatementPath) { 154 | if (!this.lazyRequireFunctionsByVariableName.has(parentNode.left.name)) { 155 | ifStatementPath.insertBefore(b.variableDeclaration( 156 | 'let', 157 | [b.variableDeclarator(b.identifier(lazyRequireFunctionName), null)] 158 | )) 159 | } 160 | 161 | replacement = b.assignmentExpression('=', b.identifier(lazyRequireFunctionName), b.functionExpression(null, [], b.blockStatement([ 162 | b.returnStatement( 163 | b.assignmentExpression('=', parentNode.left, b.logicalExpression('||', parentNode.left, parentNode.right)) 164 | ) 165 | ]))) 166 | } else { 167 | replacement = b.functionDeclaration(b.identifier(lazyRequireFunctionName), [], b.blockStatement([ 168 | b.returnStatement( 169 | b.assignmentExpression('=', parentNode.left, b.logicalExpression('||', parentNode.left, parentNode.right)) 170 | ) 171 | ])) 172 | } 173 | 174 | if (parentPath.parent.node.type === 'SequenceExpression') { 175 | const sequenceExpressionPath = parentPath.parent 176 | const expressionContainerPath = sequenceExpressionPath.parent 177 | if (sequenceExpressionPath.node.expressions.length === 1) { 178 | expressionContainerPath.replace(replacement) 179 | } else { 180 | expressionContainerPath.insertBefore(replacement) 181 | parentPath.replace() 182 | } 183 | } else { 184 | parentPath.replace(replacement) 185 | } 186 | 187 | this.lazyRequireFunctionsByVariableName.set(parentNode.left.name, lazyRequireFunctionName) 188 | return 189 | } else if (parentNode.type === 'VariableDeclarator') { 190 | // Replace variable declaration with lazy function 191 | const variableDeclarationPath = parentPath.parent 192 | const variableDeclarationNode = variableDeclarationPath.node 193 | if (variableDeclarationNode.kind === 'const') { 194 | variableDeclarationNode.kind = 'let' 195 | } 196 | 197 | if (parentNode.id.type === 'ObjectPattern') { 198 | parentPath.replace(b.variableDeclarator(parentNode.id, b.objectExpression([]))) 199 | for (const property of parentNode.id.properties.slice().reverse()) { 200 | const lazyRequireFunctionName = `get_${property.key.name}` 201 | variableDeclarationPath.insertAfter(b.functionDeclaration(b.identifier(lazyRequireFunctionName), [], b.blockStatement([ 202 | b.returnStatement( 203 | b.assignmentExpression('=', property.key, b.logicalExpression('||', property.key, b.memberExpression(parentNode.init, property.key))) 204 | ) 205 | ]))) 206 | this.lazyRequireFunctionsByVariableName.set(property.key.name, lazyRequireFunctionName) 207 | } 208 | } else { 209 | parentPath.replace(b.variableDeclarator(parentNode.id, null)) 210 | const lazyRequireFunctionName = `get_${parentNode.id.name}` 211 | variableDeclarationPath.insertAfter(b.functionDeclaration(b.identifier(lazyRequireFunctionName), [], b.blockStatement([ 212 | b.returnStatement( 213 | b.assignmentExpression('=', parentNode.id, b.logicalExpression('||', parentNode.id, parentNode.init)) 214 | ) 215 | ]))) 216 | this.lazyRequireFunctionsByVariableName.set(parentNode.id.name, lazyRequireFunctionName) 217 | } 218 | 219 | return 220 | } 221 | parentPath = parentPath.parent 222 | } 223 | console.warn(`##[warning] The reference to the module is replaced with the lazy function, but it was not in an assignment expression or a variable declaration. In some cases the bundle might not work, which you should fix manually: \n ${this.options.filePath} `); 224 | return // just call the reference it directly 225 | } 226 | 227 | isReferenceToLazyRequire (astPath) { 228 | const scope = astPath.scope 229 | const lazyRequireFunctionName = this.lazyRequireFunctionsByVariableName.get(astPath.node.name) 230 | if (lazyRequireFunctionName != null && 231 | (scope.node.type !== 'FunctionDeclaration' || lazyRequireFunctionName !== astPath.scope.node.id.name) && 232 | (scope.node.type !== 'FunctionExpression' || scope.path.parent.node.type !== 'AssignmentExpression' || lazyRequireFunctionName !== scope.path.parent.node.left.name) && 233 | (astPath.parent.node.type !== 'Property' || astPath.parent.parent.node.type !== 'ObjectPattern') ) { 234 | if (astPath.parent.node.type === 'AssignmentExpression') { 235 | return astPath.name === "right" && astUtil.isReference(astPath) // e.g module.exports = a_reference; 236 | } else { 237 | return astUtil.isReference(astPath) 238 | } 239 | 240 | } 241 | } 242 | 243 | resolveModulePath (moduleName) { 244 | try { 245 | const absolutePath = resolve.sync(moduleName, {basedir: path.dirname(this.options.filePath), extensions: ['.js', '.json']}) 246 | const isCoreNodeModule = absolutePath.indexOf(path.sep) === -1 247 | return isCoreNodeModule ? null : absolutePath 248 | } catch (e) { 249 | return null 250 | } 251 | } 252 | } 253 | 254 | function isReferenceToShadowedVariable (astPath) { 255 | const referenceName = astPath.node.name 256 | let scope = astPath.scope 257 | let foundDeclaration = GLOBALS.has(referenceName) 258 | while (scope) { 259 | if (scope.declares(referenceName)) { 260 | if (foundDeclaration) { 261 | return true 262 | } else { 263 | foundDeclaration = true 264 | } 265 | } 266 | scope = scope.parent 267 | } 268 | return false 269 | } 270 | 271 | function isStaticRequire (astPath) { 272 | const node = astPath.node 273 | return ( 274 | node.callee.name === 'require' && 275 | node.arguments.length === 1 && 276 | node.arguments[0].type === 'Literal' 277 | ) 278 | } 279 | 280 | function isStaticRequireResolve (astPath) { 281 | const node = astPath.node 282 | return ( 283 | node.callee.type === 'MemberExpression' && 284 | node.callee.object.name === 'require' && 285 | node.callee.property.name === 'resolve' && 286 | node.arguments.length === 1 && 287 | node.arguments[0].type === 'Literal' 288 | ) 289 | } 290 | 291 | function isTopLevelASTPath (astPath) { 292 | if (astPath.scope.isGlobal) { 293 | return true 294 | } else if (astPath.scope.depth === 1) { 295 | while (astPath) { 296 | const node = astPath.node 297 | if (node.type === 'FunctionExpression') { 298 | const parentNode = astPath.parent.node 299 | const grandparentNode = astPath.parent.parent.node 300 | const parentIsCallExpression = parentNode.type === 'CallExpression' && parentNode.arguments.indexOf(node) === -1 301 | const grandparentIsCallExpression = grandparentNode.type === 'CallExpression' 302 | if (parentIsCallExpression || grandparentIsCallExpression) { 303 | return true 304 | } 305 | } 306 | astPath = astPath.parent 307 | } 308 | return false 309 | } else { 310 | return false 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /lib/generate-snapshot-script.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | const FileRequireTransform = require('./file-require-transform') 6 | const indentString = require('indent-string') 7 | const {SourceMapGenerator} = require('source-map') 8 | 9 | module.exports = async function (cache, options) { 10 | // Phase 1: Starting at the main module, traverse all requires, transforming 11 | // all module references to paths relative to the base directory path and 12 | // collecting abstract syntax trees for use in generating the script in 13 | // phase 2. 14 | const moduleASTs = {} 15 | const requiredModulePaths = [options.mainPath] 16 | const includedFilePaths = new Set(requiredModulePaths) 17 | 18 | while (requiredModulePaths.length > 0) { 19 | const filePath = requiredModulePaths.shift() 20 | let relativeFilePath = path.relative(options.baseDirPath, filePath).replace(/\\/g, '/') 21 | if (!relativeFilePath.startsWith('.')) { 22 | relativeFilePath = './' + relativeFilePath 23 | } 24 | if (!moduleASTs[relativeFilePath]) { 25 | const source = fs.readFileSync(filePath, 'utf8') 26 | let foundRequires = [] 27 | const transform = new FileRequireTransform({ 28 | filePath, 29 | source, 30 | baseDirPath: options.baseDirPath, 31 | didFindRequire: (unresolvedPath, resolvedPath) => { 32 | if (options.shouldExcludeModule({requiringModulePath: filePath, requiredModulePath: resolvedPath})) { 33 | return true 34 | } else { 35 | foundRequires.push({unresolvedPath, resolvedPath}) 36 | return false 37 | } 38 | } 39 | }) 40 | 41 | const cachedTransform = await cache.get({filePath, content: source}) 42 | const useCachedTransform = 43 | cachedTransform ? 44 | cachedTransform.requires.every(r => (transform.resolveModulePath(r.unresolvedPath) || r.unresolvedPath) === r.resolvedPath) : 45 | false 46 | 47 | let transformedSource, requires 48 | if (useCachedTransform) { 49 | transformedSource = cachedTransform.source 50 | foundRequires = cachedTransform.requires 51 | } else { 52 | try { 53 | transformedSource = indentString(transform.apply(), 2) 54 | } catch (e) { 55 | console.error(`Unable to transform source code for module ${filePath}.`) 56 | if (e.index) { 57 | const before = source.slice(e.index - 100, e.index) 58 | const after = source.slice(e.index, e.index + 100) 59 | console.error(`\n${before}==>${after}\n`) 60 | } 61 | throw e 62 | } 63 | await cache.put({filePath, original: source, transformed: transformedSource, requires: foundRequires}) 64 | } 65 | 66 | moduleASTs[relativeFilePath] = `function (exports, module, __filename, __dirname, require, define) {\n${transformedSource}\n}` 67 | 68 | const resolvedRequirePaths = foundRequires.map(r => r.resolvedPath) 69 | for (let i = 0; i < foundRequires.length; i++) { 70 | const {resolvedPath} = foundRequires[i] 71 | requiredModulePaths.push(resolvedPath) 72 | includedFilePaths.add(resolvedPath) 73 | } 74 | } 75 | } 76 | 77 | await cache.deleteUnusedEntries() 78 | 79 | // Phase 2: Now use the data we gathered during phase 1 to build a snapshot 80 | // script based on `./blueprint.js`. 81 | let snapshotScript = fs.readFileSync(path.join(__dirname, 'blueprint.js'), 'utf8') 82 | 83 | // Replace `require(main)` with a require of the relativized main module path. 84 | let relativeFilePath = path.relative(options.baseDirPath, options.mainPath).replace(/\\/g, '/') 85 | if (!relativeFilePath.startsWith('.')) { 86 | relativeFilePath = './' + relativeFilePath 87 | } 88 | snapshotScript = snapshotScript.replace('mainModuleRequirePath', JSON.stringify(relativeFilePath)) 89 | 90 | // Assign the current platform to `process.platform` so that it can be used 91 | // even while creating the snapshot. 92 | snapshotScript = snapshotScript.replace('processPlatform', process.platform) 93 | 94 | // Assign the current platform's path separator so that custom require works 95 | // correctly on both Windows and Unix systems. 96 | snapshotScript = snapshotScript.replace('const pathSeparator = null', `const pathSeparator = ${JSON.stringify(path.sep)}`) 97 | 98 | const auxiliaryData = JSON.stringify(options.auxiliaryData || {}) 99 | const auxiliaryDataAssignment = 'var snapshotAuxiliaryData = {}' 100 | const auxiliaryDataAssignmentStartIndex = snapshotScript.indexOf(auxiliaryDataAssignment) 101 | const auxiliaryDataAssignmentEndIndex = auxiliaryDataAssignmentStartIndex + auxiliaryDataAssignment.length 102 | snapshotScript = 103 | snapshotScript.slice(0, auxiliaryDataAssignmentStartIndex) + 104 | `var snapshotAuxiliaryData = ${auxiliaryData};` + 105 | snapshotScript.slice(auxiliaryDataAssignmentEndIndex) 106 | 107 | // Replace `require.definitions = {}` with an assignment of the actual definitions 108 | // of all the modules. 109 | const definitionsAssignment = 'customRequire.definitions = {}' 110 | const definitionsAssignmentStartIndex = snapshotScript.indexOf(definitionsAssignment) 111 | const definitionsAssignmentEndIndex = definitionsAssignmentStartIndex + definitionsAssignment.length 112 | const sections = [] 113 | let sectionStartRow = getLineCount(snapshotScript.slice(0, definitionsAssignmentStartIndex)) + 1 114 | let definitions = '' 115 | const moduleFilePaths = Object.keys(moduleASTs) 116 | for (let i = 0; i < moduleFilePaths.length; i++) { 117 | const relativePath = moduleFilePaths[i] 118 | const source = moduleASTs[relativePath] 119 | const lineCount = getLineCount(source) 120 | sections.push({relativePath, startRow: sectionStartRow, endRow: (sectionStartRow + lineCount) - 2}) 121 | definitions += indentString(`${JSON.stringify(relativePath)}: ${source}`, 4) + ',\n' 122 | sectionStartRow += lineCount 123 | } 124 | 125 | snapshotScript = 126 | snapshotScript.slice(0, definitionsAssignmentStartIndex) + 127 | `customRequire.definitions = {\n${definitions}\n };` + 128 | snapshotScript.slice(definitionsAssignmentEndIndex) 129 | 130 | // The following code to generate metadata to map line numbers in the snapshot 131 | // must remain at the end of this function to ensure all the embedded code is 132 | // accounted for. 133 | const sectionsAssignment = 'snapshotAuxiliaryData.snapshotSections = []' 134 | const sectionsAssignmentStartIndex = snapshotScript.indexOf(sectionsAssignment) 135 | const sectionsAssignmentEndIndex = sectionsAssignmentStartIndex + sectionsAssignment.length 136 | snapshotScript = 137 | snapshotScript.slice(0, sectionsAssignmentStartIndex) + 138 | `snapshotAuxiliaryData.snapshotSections = ${JSON.stringify(sections)}` + 139 | snapshotScript.slice(sectionsAssignmentEndIndex) 140 | 141 | return {snapshotScript, includedFilePaths} 142 | } 143 | 144 | function getLineCount (text) { 145 | let lineCount = 1 146 | for (let i = 0; i < text.length; i++) { 147 | if (text[i] === '\n') lineCount++ 148 | } 149 | return lineCount 150 | } 151 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const TransformCache = require('./transform-cache') 2 | const generateSnapshotScript = require('./generate-snapshot-script') 3 | 4 | module.exports = async function (options) { 5 | const cacheInvalidationKey = options.shouldExcludeModule.toString() + require('../package.json').version 6 | const cache = new TransformCache(options.cachePath, cacheInvalidationKey) 7 | await cache.loadOrCreate() 8 | delete options.cachePath 9 | 10 | const result = await generateSnapshotScript(cache, options) 11 | await cache.dispose() 12 | return result 13 | } 14 | -------------------------------------------------------------------------------- /lib/transform-cache.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto') 2 | const levelup = require('levelup') 3 | const encode = require('encoding-down') 4 | const leveldown = require('leveldown') 5 | 6 | module.exports = class TransformCache { 7 | constructor (filePath, invalidationKey) { 8 | this.filePath = filePath 9 | this.invalidationKey = invalidationKey 10 | this.db = null 11 | this.usedKeys = new Set() 12 | } 13 | 14 | async loadOrCreate () { 15 | await this._initialize() 16 | const oldKey = await this._get('invalidation-key') 17 | const newKey = crypto.createHash('sha1').update(this.invalidationKey).digest('hex') 18 | if (oldKey !== newKey) { 19 | const keys = await this._allKeys() 20 | const deleteOperations = Array.from(keys).map((key) => { return {key, type: 'del'} }) 21 | await this._batch(deleteOperations) 22 | await this._put('invalidation-key', newKey) 23 | } 24 | } 25 | 26 | dispose () { 27 | return new Promise((resolve, reject) => { 28 | this.db.close((error) => { 29 | if (error) { 30 | reject(error) 31 | } else { 32 | resolve() 33 | } 34 | }) 35 | }) 36 | } 37 | 38 | async put ({filePath, original, transformed, requires}) { 39 | const key = crypto.createHash('sha1').update(original).digest('hex') 40 | await this._put(filePath + ':' + key + ':source', transformed) 41 | await this._put(filePath + ':' + key + ':requires', JSON.stringify(requires)) 42 | } 43 | 44 | async get ({filePath, content}) { 45 | const key = crypto.createHash('sha1').update(content).digest('hex') 46 | const source = await this._get(filePath + ':' + key + ':source') 47 | const requires = await this._get(filePath + ':' + key + ':requires') 48 | if (source && requires) { 49 | return {source, requires: JSON.parse(requires)} 50 | } else { 51 | return null 52 | } 53 | } 54 | 55 | async deleteUnusedEntries () { 56 | const unusedKeys = await this._allKeys() 57 | for (const key of this.usedKeys) { 58 | unusedKeys.delete(key) 59 | } 60 | 61 | const deleteOperations = Array.from(unusedKeys).map((key) => { return {key, type: 'del'} }) 62 | await this._batch(deleteOperations) 63 | } 64 | 65 | _initialize () { 66 | return new Promise((resolve, reject) => { 67 | levelup(encode(leveldown(this.filePath)), {}, (error, db) => { 68 | if (error) { 69 | reject(error) 70 | } else { 71 | this.db = db 72 | resolve() 73 | } 74 | }) 75 | }) 76 | } 77 | 78 | _put (key, value) { 79 | return new Promise((resolve, reject) => { 80 | this.db.put(key, value, {}, (error) => { 81 | if (error) { 82 | reject(error) 83 | } else { 84 | this.usedKeys.add(key) 85 | resolve() 86 | } 87 | }) 88 | }) 89 | } 90 | 91 | _get (key) { 92 | return new Promise((resolve, reject) => { 93 | this.db.get(key, {}, (error, value) => { 94 | if (error) { 95 | if (error.notFound) { 96 | resolve(null) 97 | } else { 98 | reject(error) 99 | } 100 | } else { 101 | this.usedKeys.add(key) 102 | resolve(value) 103 | } 104 | }) 105 | }) 106 | } 107 | 108 | _allKeys () { 109 | return new Promise((resolve, reject) => { 110 | const keys = new Set() 111 | const stream = this.db.createKeyStream() 112 | stream.on('data', (key) => { keys.add(key) }) 113 | stream.on('error', (error) => { reject(error) }) 114 | stream.on('close', () => { resolve(keys) }) 115 | }) 116 | } 117 | 118 | _batch (operations) { 119 | return new Promise((resolve, reject) => { 120 | this.db.batch(operations, {}, (error) => { 121 | if (error) { 122 | reject(error) 123 | } else { 124 | resolve() 125 | } 126 | }) 127 | }) 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-link", 3 | "version": "0.6.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@electron/get": { 8 | "version": "1.12.2", 9 | "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.2.tgz", 10 | "integrity": "sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg==", 11 | "dev": true, 12 | "requires": { 13 | "debug": "^4.1.1", 14 | "env-paths": "^2.2.0", 15 | "fs-extra": "^8.1.0", 16 | "global-agent": "^2.0.2", 17 | "global-tunnel-ng": "^2.7.1", 18 | "got": "^9.6.0", 19 | "progress": "^2.0.3", 20 | "sanitize-filename": "^1.6.2", 21 | "sumchecker": "^3.0.1" 22 | }, 23 | "dependencies": { 24 | "debug": { 25 | "version": "4.3.1", 26 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 27 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 28 | "dev": true, 29 | "requires": { 30 | "ms": "2.1.2" 31 | } 32 | }, 33 | "ms": { 34 | "version": "2.1.2", 35 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 36 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 37 | "dev": true 38 | } 39 | } 40 | }, 41 | "@sindresorhus/is": { 42 | "version": "0.14.0", 43 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 44 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 45 | "dev": true 46 | }, 47 | "@szmarczak/http-timer": { 48 | "version": "1.1.2", 49 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 50 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 51 | "dev": true, 52 | "requires": { 53 | "defer-to-connect": "^1.0.1" 54 | } 55 | }, 56 | "@types/node": { 57 | "version": "12.19.8", 58 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.8.tgz", 59 | "integrity": "sha512-D4k2kNi0URNBxIRCb1khTnkWNHv8KSL1owPmS/K5e5t8B2GzMReY7AsJIY1BnP5KdlgC4rj9jk2IkDMasIE7xg==", 60 | "dev": true 61 | }, 62 | "@ungap/promise-all-settled": { 63 | "version": "1.1.2", 64 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 65 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 66 | "dev": true 67 | }, 68 | "abstract-leveldown": { 69 | "version": "6.3.0", 70 | "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz", 71 | "integrity": "sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==", 72 | "requires": { 73 | "buffer": "^5.5.0", 74 | "immediate": "^3.2.3", 75 | "level-concat-iterator": "~2.0.0", 76 | "level-supports": "~1.0.0", 77 | "xtend": "~4.0.0" 78 | } 79 | }, 80 | "acorn": { 81 | "version": "8.0.4", 82 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", 83 | "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==" 84 | }, 85 | "ansi-colors": { 86 | "version": "4.1.1", 87 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 88 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 89 | "dev": true 90 | }, 91 | "ansi-regex": { 92 | "version": "3.0.0", 93 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 94 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 95 | "dev": true 96 | }, 97 | "ansi-styles": { 98 | "version": "3.2.1", 99 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 100 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 101 | "dev": true, 102 | "requires": { 103 | "color-convert": "^1.9.0" 104 | } 105 | }, 106 | "argparse": { 107 | "version": "1.0.10", 108 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 109 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 110 | "dev": true, 111 | "requires": { 112 | "sprintf-js": "~1.0.2" 113 | }, 114 | "dependencies": { 115 | "sprintf-js": { 116 | "version": "1.0.3", 117 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 118 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 119 | "dev": true 120 | } 121 | } 122 | }, 123 | "ast-types": { 124 | "version": "0.14.1", 125 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.1.tgz", 126 | "integrity": "sha512-pfSiukbt23P1qMhNnsozLzhMLBs7EEeXqPyvPmnuZM+RMfwfqwDbSVKYflgGuVI7/VehR4oMks0igzdNAg4VeQ==", 127 | "requires": { 128 | "tslib": "^2.0.1" 129 | } 130 | }, 131 | "ast-util-plus": { 132 | "version": "0.7.1", 133 | "resolved": "https://registry.npmjs.org/ast-util-plus/-/ast-util-plus-0.7.1.tgz", 134 | "integrity": "sha512-j5CjjuBgNUz7lequJ11bboMSOz3WbpUIKDtscmN37bn5WWsxzn7zb3kOCO+jXhvGY9C5IVwssKlG6BA5yqav7w==", 135 | "requires": { 136 | "ast-types": "0.14.1", 137 | "private": "0.1.8" 138 | } 139 | }, 140 | "at-least-node": { 141 | "version": "1.0.0", 142 | "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", 143 | "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", 144 | "dev": true 145 | }, 146 | "balanced-match": { 147 | "version": "1.0.0", 148 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 149 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 150 | "dev": true 151 | }, 152 | "base64-js": { 153 | "version": "1.3.1", 154 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 155 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 156 | }, 157 | "boolean": { 158 | "version": "3.0.2", 159 | "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz", 160 | "integrity": "sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g==", 161 | "dev": true, 162 | "optional": true 163 | }, 164 | "brace-expansion": { 165 | "version": "1.1.8", 166 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 167 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 168 | "dev": true, 169 | "requires": { 170 | "balanced-match": "^1.0.0", 171 | "concat-map": "0.0.1" 172 | } 173 | }, 174 | "browser-stdout": { 175 | "version": "1.3.1", 176 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 177 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 178 | "dev": true 179 | }, 180 | "buffer": { 181 | "version": "5.6.0", 182 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", 183 | "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", 184 | "requires": { 185 | "base64-js": "^1.0.2", 186 | "ieee754": "^1.1.4" 187 | } 188 | }, 189 | "buffer-crc32": { 190 | "version": "0.2.13", 191 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 192 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 193 | "dev": true 194 | }, 195 | "buffer-from": { 196 | "version": "1.1.1", 197 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 198 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 199 | "dev": true 200 | }, 201 | "cacheable-request": { 202 | "version": "6.1.0", 203 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 204 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 205 | "dev": true, 206 | "requires": { 207 | "clone-response": "^1.0.2", 208 | "get-stream": "^5.1.0", 209 | "http-cache-semantics": "^4.0.0", 210 | "keyv": "^3.0.0", 211 | "lowercase-keys": "^2.0.0", 212 | "normalize-url": "^4.1.0", 213 | "responselike": "^1.0.2" 214 | }, 215 | "dependencies": { 216 | "get-stream": { 217 | "version": "5.2.0", 218 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 219 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 220 | "dev": true, 221 | "requires": { 222 | "pump": "^3.0.0" 223 | } 224 | }, 225 | "lowercase-keys": { 226 | "version": "2.0.0", 227 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 228 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 229 | "dev": true 230 | } 231 | } 232 | }, 233 | "camelcase": { 234 | "version": "5.3.1", 235 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 236 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 237 | "dev": true 238 | }, 239 | "chokidar": { 240 | "version": "3.4.3", 241 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 242 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 243 | "dev": true, 244 | "requires": { 245 | "anymatch": "~3.1.1", 246 | "braces": "~3.0.2", 247 | "fsevents": "~2.1.2", 248 | "glob-parent": "~5.1.0", 249 | "is-binary-path": "~2.1.0", 250 | "is-glob": "~4.0.1", 251 | "normalize-path": "~3.0.0", 252 | "readdirp": "~3.5.0" 253 | }, 254 | "dependencies": { 255 | "anymatch": { 256 | "version": "3.1.1", 257 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 258 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 259 | "dev": true, 260 | "requires": { 261 | "normalize-path": "^3.0.0", 262 | "picomatch": "^2.0.4" 263 | } 264 | }, 265 | "binary-extensions": { 266 | "version": "2.1.0", 267 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 268 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 269 | "dev": true 270 | }, 271 | "braces": { 272 | "version": "3.0.2", 273 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 274 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 275 | "dev": true, 276 | "requires": { 277 | "fill-range": "^7.0.1" 278 | } 279 | }, 280 | "fill-range": { 281 | "version": "7.0.1", 282 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 283 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 284 | "dev": true, 285 | "requires": { 286 | "to-regex-range": "^5.0.1" 287 | } 288 | }, 289 | "glob-parent": { 290 | "version": "5.1.1", 291 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 292 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 293 | "dev": true, 294 | "requires": { 295 | "is-glob": "^4.0.1" 296 | } 297 | }, 298 | "is-binary-path": { 299 | "version": "2.1.0", 300 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 301 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 302 | "dev": true, 303 | "requires": { 304 | "binary-extensions": "^2.0.0" 305 | } 306 | }, 307 | "is-number": { 308 | "version": "7.0.0", 309 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 310 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 311 | "dev": true 312 | }, 313 | "readdirp": { 314 | "version": "3.5.0", 315 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 316 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 317 | "dev": true, 318 | "requires": { 319 | "picomatch": "^2.2.1" 320 | } 321 | }, 322 | "to-regex-range": { 323 | "version": "5.0.1", 324 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 325 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 326 | "dev": true, 327 | "requires": { 328 | "is-number": "^7.0.0" 329 | } 330 | } 331 | } 332 | }, 333 | "cliui": { 334 | "version": "5.0.0", 335 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 336 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 337 | "dev": true, 338 | "requires": { 339 | "string-width": "^3.1.0", 340 | "strip-ansi": "^5.2.0", 341 | "wrap-ansi": "^5.1.0" 342 | }, 343 | "dependencies": { 344 | "ansi-regex": { 345 | "version": "4.1.0", 346 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 347 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 348 | "dev": true 349 | }, 350 | "string-width": { 351 | "version": "3.1.0", 352 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 353 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 354 | "dev": true, 355 | "requires": { 356 | "emoji-regex": "^7.0.1", 357 | "is-fullwidth-code-point": "^2.0.0", 358 | "strip-ansi": "^5.1.0" 359 | } 360 | }, 361 | "strip-ansi": { 362 | "version": "5.2.0", 363 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 364 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 365 | "dev": true, 366 | "requires": { 367 | "ansi-regex": "^4.1.0" 368 | } 369 | } 370 | } 371 | }, 372 | "clone-response": { 373 | "version": "1.0.2", 374 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 375 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 376 | "dev": true, 377 | "requires": { 378 | "mimic-response": "^1.0.0" 379 | } 380 | }, 381 | "color-convert": { 382 | "version": "1.9.3", 383 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 384 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 385 | "dev": true, 386 | "requires": { 387 | "color-name": "1.1.3" 388 | } 389 | }, 390 | "color-name": { 391 | "version": "1.1.3", 392 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 393 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 394 | "dev": true 395 | }, 396 | "concat-map": { 397 | "version": "0.0.1", 398 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 399 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 400 | "dev": true 401 | }, 402 | "concat-stream": { 403 | "version": "1.6.2", 404 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 405 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 406 | "dev": true, 407 | "requires": { 408 | "buffer-from": "^1.0.0", 409 | "inherits": "^2.0.3", 410 | "readable-stream": "^2.2.2", 411 | "typedarray": "^0.0.6" 412 | } 413 | }, 414 | "config-chain": { 415 | "version": "1.1.12", 416 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", 417 | "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", 418 | "dev": true, 419 | "optional": true, 420 | "requires": { 421 | "ini": "^1.3.4", 422 | "proto-list": "~1.2.1" 423 | } 424 | }, 425 | "core-js": { 426 | "version": "3.8.1", 427 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.1.tgz", 428 | "integrity": "sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==", 429 | "dev": true, 430 | "optional": true 431 | }, 432 | "core-util-is": { 433 | "version": "1.0.2", 434 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 435 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 436 | "dev": true 437 | }, 438 | "debug": { 439 | "version": "2.6.9", 440 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 441 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 442 | "dev": true, 443 | "requires": { 444 | "ms": "2.0.0" 445 | } 446 | }, 447 | "decamelize": { 448 | "version": "1.2.0", 449 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 450 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 451 | "dev": true 452 | }, 453 | "decompress-response": { 454 | "version": "3.3.0", 455 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 456 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 457 | "dev": true, 458 | "requires": { 459 | "mimic-response": "^1.0.0" 460 | } 461 | }, 462 | "dedent": { 463 | "version": "0.7.0", 464 | "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", 465 | "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", 466 | "dev": true 467 | }, 468 | "defer-to-connect": { 469 | "version": "1.1.3", 470 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 471 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 472 | "dev": true 473 | }, 474 | "deferred-leveldown": { 475 | "version": "5.3.0", 476 | "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz", 477 | "integrity": "sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==", 478 | "requires": { 479 | "abstract-leveldown": "~6.2.1", 480 | "inherits": "^2.0.3" 481 | }, 482 | "dependencies": { 483 | "abstract-leveldown": { 484 | "version": "6.2.3", 485 | "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", 486 | "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", 487 | "requires": { 488 | "buffer": "^5.5.0", 489 | "immediate": "^3.2.3", 490 | "level-concat-iterator": "~2.0.0", 491 | "level-supports": "~1.0.0", 492 | "xtend": "~4.0.0" 493 | } 494 | } 495 | } 496 | }, 497 | "define-properties": { 498 | "version": "1.1.3", 499 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 500 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 501 | "dev": true, 502 | "optional": true, 503 | "requires": { 504 | "object-keys": "^1.0.12" 505 | } 506 | }, 507 | "detect-node": { 508 | "version": "2.0.4", 509 | "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", 510 | "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", 511 | "dev": true, 512 | "optional": true 513 | }, 514 | "diff": { 515 | "version": "4.0.2", 516 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 517 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 518 | "dev": true 519 | }, 520 | "duplexer3": { 521 | "version": "0.1.4", 522 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 523 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 524 | "dev": true 525 | }, 526 | "electron": { 527 | "version": "9.3.5", 528 | "resolved": "https://registry.npmjs.org/electron/-/electron-9.3.5.tgz", 529 | "integrity": "sha512-EPmDsp7sO0UPtw7nLD1ufse/nBskP+ifXzBgUg9psCUlapkzuwYi6pmLAzKLW/bVjwgyUKwh1OKWILWfOeLGcQ==", 530 | "dev": true, 531 | "requires": { 532 | "@electron/get": "^1.0.1", 533 | "@types/node": "^12.0.12", 534 | "extract-zip": "^1.0.3" 535 | } 536 | }, 537 | "electron-mocha": { 538 | "version": "10.0.0", 539 | "resolved": "https://registry.npmjs.org/electron-mocha/-/electron-mocha-10.0.0.tgz", 540 | "integrity": "sha512-eCIAPlhSi10wPcwYnZWxRAKoEGKX+UQyco3gjWcWPD6csfwCLT5CTvA1bId8Q8Gb0ss8Rj8y8kuK9eLCJtr0DQ==", 541 | "dev": true, 542 | "requires": { 543 | "ansi-colors": "^4.1.1", 544 | "electron-window": "^0.8.0", 545 | "fs-extra": "^9.0.1", 546 | "log-symbols": "^4.0.0", 547 | "mocha": "^8.2.1", 548 | "which": "^2.0.2", 549 | "yargs": "^16.1.1" 550 | }, 551 | "dependencies": { 552 | "fs-extra": { 553 | "version": "9.0.1", 554 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", 555 | "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", 556 | "dev": true, 557 | "requires": { 558 | "at-least-node": "^1.0.0", 559 | "graceful-fs": "^4.2.0", 560 | "jsonfile": "^6.0.1", 561 | "universalify": "^1.0.0" 562 | } 563 | }, 564 | "jsonfile": { 565 | "version": "6.1.0", 566 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 567 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 568 | "dev": true, 569 | "requires": { 570 | "graceful-fs": "^4.1.6", 571 | "universalify": "^2.0.0" 572 | }, 573 | "dependencies": { 574 | "universalify": { 575 | "version": "2.0.0", 576 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 577 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 578 | "dev": true 579 | } 580 | } 581 | }, 582 | "universalify": { 583 | "version": "1.0.0", 584 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", 585 | "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", 586 | "dev": true 587 | } 588 | } 589 | }, 590 | "electron-window": { 591 | "version": "0.8.1", 592 | "resolved": "https://registry.npmjs.org/electron-window/-/electron-window-0.8.1.tgz", 593 | "integrity": "sha1-FsoYfrSHCwZ5J0/IKZxZYOarLF4=", 594 | "dev": true, 595 | "requires": { 596 | "is-electron-renderer": "^2.0.0" 597 | } 598 | }, 599 | "emoji-regex": { 600 | "version": "7.0.3", 601 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 602 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 603 | "dev": true 604 | }, 605 | "encodeurl": { 606 | "version": "1.0.2", 607 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 608 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 609 | "dev": true, 610 | "optional": true 611 | }, 612 | "encoding-down": { 613 | "version": "6.3.0", 614 | "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", 615 | "integrity": "sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==", 616 | "requires": { 617 | "abstract-leveldown": "^6.2.1", 618 | "inherits": "^2.0.3", 619 | "level-codec": "^9.0.0", 620 | "level-errors": "^2.0.0" 621 | } 622 | }, 623 | "end-of-stream": { 624 | "version": "1.4.4", 625 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 626 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 627 | "dev": true, 628 | "requires": { 629 | "once": "^1.4.0" 630 | } 631 | }, 632 | "env-paths": { 633 | "version": "2.2.0", 634 | "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", 635 | "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", 636 | "dev": true 637 | }, 638 | "errno": { 639 | "version": "0.1.7", 640 | "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", 641 | "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", 642 | "requires": { 643 | "prr": "~1.0.1" 644 | } 645 | }, 646 | "es6-error": { 647 | "version": "4.1.1", 648 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 649 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 650 | "dev": true, 651 | "optional": true 652 | }, 653 | "escalade": { 654 | "version": "3.1.1", 655 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 656 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 657 | "dev": true 658 | }, 659 | "esprima": { 660 | "version": "4.0.1", 661 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 662 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 663 | }, 664 | "extract-zip": { 665 | "version": "1.7.0", 666 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", 667 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", 668 | "dev": true, 669 | "requires": { 670 | "concat-stream": "^1.6.2", 671 | "debug": "^2.6.9", 672 | "mkdirp": "^0.5.4", 673 | "yauzl": "^2.10.0" 674 | } 675 | }, 676 | "fd-slicer": { 677 | "version": "1.1.0", 678 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 679 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 680 | "dev": true, 681 | "requires": { 682 | "pend": "~1.2.0" 683 | } 684 | }, 685 | "flat": { 686 | "version": "5.0.2", 687 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 688 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 689 | "dev": true 690 | }, 691 | "fs-extra": { 692 | "version": "8.1.0", 693 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", 694 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", 695 | "dev": true, 696 | "requires": { 697 | "graceful-fs": "^4.2.0", 698 | "jsonfile": "^4.0.0", 699 | "universalify": "^0.1.0" 700 | } 701 | }, 702 | "fs.realpath": { 703 | "version": "1.0.0", 704 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 705 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 706 | "dev": true 707 | }, 708 | "fsevents": { 709 | "version": "2.1.3", 710 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 711 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 712 | "dev": true, 713 | "optional": true 714 | }, 715 | "function-bind": { 716 | "version": "1.1.1", 717 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 718 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 719 | }, 720 | "get-caller-file": { 721 | "version": "2.0.5", 722 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 723 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 724 | "dev": true 725 | }, 726 | "get-stream": { 727 | "version": "4.1.0", 728 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 729 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 730 | "dev": true, 731 | "requires": { 732 | "pump": "^3.0.0" 733 | } 734 | }, 735 | "glob": { 736 | "version": "7.1.6", 737 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 738 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 739 | "dev": true, 740 | "requires": { 741 | "fs.realpath": "^1.0.0", 742 | "inflight": "^1.0.4", 743 | "inherits": "2", 744 | "minimatch": "^3.0.4", 745 | "once": "^1.3.0", 746 | "path-is-absolute": "^1.0.0" 747 | } 748 | }, 749 | "global-agent": { 750 | "version": "2.1.12", 751 | "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz", 752 | "integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==", 753 | "dev": true, 754 | "optional": true, 755 | "requires": { 756 | "boolean": "^3.0.1", 757 | "core-js": "^3.6.5", 758 | "es6-error": "^4.1.1", 759 | "matcher": "^3.0.0", 760 | "roarr": "^2.15.3", 761 | "semver": "^7.3.2", 762 | "serialize-error": "^7.0.1" 763 | }, 764 | "dependencies": { 765 | "semver": { 766 | "version": "7.3.4", 767 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 768 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 769 | "dev": true, 770 | "optional": true, 771 | "requires": { 772 | "lru-cache": "^6.0.0" 773 | } 774 | } 775 | } 776 | }, 777 | "global-tunnel-ng": { 778 | "version": "2.7.1", 779 | "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", 780 | "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", 781 | "dev": true, 782 | "optional": true, 783 | "requires": { 784 | "encodeurl": "^1.0.2", 785 | "lodash": "^4.17.10", 786 | "npm-conf": "^1.1.3", 787 | "tunnel": "^0.0.6" 788 | } 789 | }, 790 | "globalthis": { 791 | "version": "1.0.1", 792 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", 793 | "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", 794 | "dev": true, 795 | "optional": true, 796 | "requires": { 797 | "define-properties": "^1.1.3" 798 | } 799 | }, 800 | "got": { 801 | "version": "9.6.0", 802 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 803 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 804 | "dev": true, 805 | "requires": { 806 | "@sindresorhus/is": "^0.14.0", 807 | "@szmarczak/http-timer": "^1.1.2", 808 | "cacheable-request": "^6.0.0", 809 | "decompress-response": "^3.3.0", 810 | "duplexer3": "^0.1.4", 811 | "get-stream": "^4.1.0", 812 | "lowercase-keys": "^1.0.1", 813 | "mimic-response": "^1.0.1", 814 | "p-cancelable": "^1.0.0", 815 | "to-readable-stream": "^1.0.0", 816 | "url-parse-lax": "^3.0.0" 817 | } 818 | }, 819 | "graceful-fs": { 820 | "version": "4.2.4", 821 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 822 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 823 | "dev": true 824 | }, 825 | "growl": { 826 | "version": "1.10.5", 827 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 828 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 829 | "dev": true 830 | }, 831 | "has": { 832 | "version": "1.0.3", 833 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 834 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 835 | "requires": { 836 | "function-bind": "^1.1.1" 837 | } 838 | }, 839 | "he": { 840 | "version": "1.2.0", 841 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 842 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 843 | "dev": true 844 | }, 845 | "http-cache-semantics": { 846 | "version": "4.1.0", 847 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 848 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 849 | "dev": true 850 | }, 851 | "ieee754": { 852 | "version": "1.1.13", 853 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 854 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 855 | }, 856 | "immediate": { 857 | "version": "3.3.0", 858 | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", 859 | "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" 860 | }, 861 | "indent-string": { 862 | "version": "4.0.0", 863 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 864 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" 865 | }, 866 | "inflight": { 867 | "version": "1.0.6", 868 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 869 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 870 | "dev": true, 871 | "requires": { 872 | "once": "^1.3.0", 873 | "wrappy": "1" 874 | } 875 | }, 876 | "inherits": { 877 | "version": "2.0.3", 878 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 879 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 880 | }, 881 | "ini": { 882 | "version": "1.3.7", 883 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", 884 | "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", 885 | "dev": true, 886 | "optional": true 887 | }, 888 | "is-core-module": { 889 | "version": "2.2.0", 890 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", 891 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", 892 | "requires": { 893 | "has": "^1.0.3" 894 | } 895 | }, 896 | "is-electron-renderer": { 897 | "version": "2.0.1", 898 | "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", 899 | "integrity": "sha1-pGnQVvl1aXxYyYxgI+sKp5r4laI=", 900 | "dev": true 901 | }, 902 | "is-extglob": { 903 | "version": "2.1.1", 904 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 905 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 906 | "dev": true 907 | }, 908 | "is-fullwidth-code-point": { 909 | "version": "2.0.0", 910 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 911 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 912 | "dev": true 913 | }, 914 | "is-glob": { 915 | "version": "4.0.1", 916 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 917 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 918 | "dev": true, 919 | "requires": { 920 | "is-extglob": "^2.1.1" 921 | } 922 | }, 923 | "is-plain-obj": { 924 | "version": "2.1.0", 925 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 926 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 927 | "dev": true 928 | }, 929 | "isarray": { 930 | "version": "1.0.0", 931 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 932 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 933 | "dev": true 934 | }, 935 | "isexe": { 936 | "version": "2.0.0", 937 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 938 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 939 | "dev": true 940 | }, 941 | "js-yaml": { 942 | "version": "3.14.0", 943 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 944 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 945 | "dev": true, 946 | "requires": { 947 | "argparse": "^1.0.7", 948 | "esprima": "^4.0.0" 949 | } 950 | }, 951 | "json-buffer": { 952 | "version": "3.0.0", 953 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 954 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 955 | "dev": true 956 | }, 957 | "json-stringify-safe": { 958 | "version": "5.0.1", 959 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 960 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", 961 | "dev": true, 962 | "optional": true 963 | }, 964 | "jsonfile": { 965 | "version": "4.0.0", 966 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 967 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 968 | "dev": true, 969 | "requires": { 970 | "graceful-fs": "^4.1.6" 971 | } 972 | }, 973 | "keyv": { 974 | "version": "3.1.0", 975 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 976 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 977 | "dev": true, 978 | "requires": { 979 | "json-buffer": "3.0.0" 980 | } 981 | }, 982 | "level-codec": { 983 | "version": "9.0.2", 984 | "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.2.tgz", 985 | "integrity": "sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ==", 986 | "requires": { 987 | "buffer": "^5.6.0" 988 | } 989 | }, 990 | "level-concat-iterator": { 991 | "version": "2.0.1", 992 | "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz", 993 | "integrity": "sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw==" 994 | }, 995 | "level-errors": { 996 | "version": "2.0.1", 997 | "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-2.0.1.tgz", 998 | "integrity": "sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw==", 999 | "requires": { 1000 | "errno": "~0.1.1" 1001 | } 1002 | }, 1003 | "level-iterator-stream": { 1004 | "version": "4.0.2", 1005 | "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz", 1006 | "integrity": "sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q==", 1007 | "requires": { 1008 | "inherits": "^2.0.4", 1009 | "readable-stream": "^3.4.0", 1010 | "xtend": "^4.0.2" 1011 | }, 1012 | "dependencies": { 1013 | "inherits": { 1014 | "version": "2.0.4", 1015 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1016 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1017 | }, 1018 | "readable-stream": { 1019 | "version": "3.6.0", 1020 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1021 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1022 | "requires": { 1023 | "inherits": "^2.0.3", 1024 | "string_decoder": "^1.1.1", 1025 | "util-deprecate": "^1.0.1" 1026 | } 1027 | }, 1028 | "safe-buffer": { 1029 | "version": "5.2.1", 1030 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1031 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1032 | }, 1033 | "string_decoder": { 1034 | "version": "1.3.0", 1035 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1036 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1037 | "requires": { 1038 | "safe-buffer": "~5.2.0" 1039 | } 1040 | } 1041 | } 1042 | }, 1043 | "level-supports": { 1044 | "version": "1.0.1", 1045 | "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", 1046 | "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", 1047 | "requires": { 1048 | "xtend": "^4.0.2" 1049 | } 1050 | }, 1051 | "leveldown": { 1052 | "version": "5.6.0", 1053 | "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", 1054 | "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", 1055 | "requires": { 1056 | "abstract-leveldown": "~6.2.1", 1057 | "napi-macros": "~2.0.0", 1058 | "node-gyp-build": "~4.1.0" 1059 | }, 1060 | "dependencies": { 1061 | "abstract-leveldown": { 1062 | "version": "6.2.3", 1063 | "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz", 1064 | "integrity": "sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==", 1065 | "requires": { 1066 | "buffer": "^5.5.0", 1067 | "immediate": "^3.2.3", 1068 | "level-concat-iterator": "~2.0.0", 1069 | "level-supports": "~1.0.0", 1070 | "xtend": "~4.0.0" 1071 | } 1072 | } 1073 | } 1074 | }, 1075 | "levelup": { 1076 | "version": "4.4.0", 1077 | "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", 1078 | "integrity": "sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==", 1079 | "requires": { 1080 | "deferred-leveldown": "~5.3.0", 1081 | "level-errors": "~2.0.0", 1082 | "level-iterator-stream": "~4.0.0", 1083 | "level-supports": "~1.0.0", 1084 | "xtend": "~4.0.0" 1085 | } 1086 | }, 1087 | "lodash": { 1088 | "version": "4.17.20", 1089 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 1090 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 1091 | "dev": true, 1092 | "optional": true 1093 | }, 1094 | "log-symbols": { 1095 | "version": "4.0.0", 1096 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 1097 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 1098 | "dev": true, 1099 | "requires": { 1100 | "chalk": "^4.0.0" 1101 | }, 1102 | "dependencies": { 1103 | "ansi-styles": { 1104 | "version": "4.3.0", 1105 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1106 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1107 | "dev": true, 1108 | "requires": { 1109 | "color-convert": "^2.0.1" 1110 | } 1111 | }, 1112 | "chalk": { 1113 | "version": "4.1.0", 1114 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 1115 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 1116 | "dev": true, 1117 | "requires": { 1118 | "ansi-styles": "^4.1.0", 1119 | "supports-color": "^7.1.0" 1120 | } 1121 | }, 1122 | "color-convert": { 1123 | "version": "2.0.1", 1124 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1125 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1126 | "dev": true, 1127 | "requires": { 1128 | "color-name": "~1.1.4" 1129 | } 1130 | }, 1131 | "color-name": { 1132 | "version": "1.1.4", 1133 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1134 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1135 | "dev": true 1136 | }, 1137 | "has-flag": { 1138 | "version": "4.0.0", 1139 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1140 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1141 | "dev": true 1142 | }, 1143 | "supports-color": { 1144 | "version": "7.2.0", 1145 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1146 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1147 | "dev": true, 1148 | "requires": { 1149 | "has-flag": "^4.0.0" 1150 | } 1151 | } 1152 | } 1153 | }, 1154 | "lowercase-keys": { 1155 | "version": "1.0.1", 1156 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1157 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1158 | "dev": true 1159 | }, 1160 | "lru-cache": { 1161 | "version": "6.0.0", 1162 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1163 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1164 | "dev": true, 1165 | "optional": true, 1166 | "requires": { 1167 | "yallist": "^4.0.0" 1168 | } 1169 | }, 1170 | "matcher": { 1171 | "version": "3.0.0", 1172 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 1173 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 1174 | "dev": true, 1175 | "optional": true, 1176 | "requires": { 1177 | "escape-string-regexp": "^4.0.0" 1178 | }, 1179 | "dependencies": { 1180 | "escape-string-regexp": { 1181 | "version": "4.0.0", 1182 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1183 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1184 | "dev": true, 1185 | "optional": true 1186 | } 1187 | } 1188 | }, 1189 | "mimic-response": { 1190 | "version": "1.0.1", 1191 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1192 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1193 | "dev": true 1194 | }, 1195 | "minimatch": { 1196 | "version": "3.0.4", 1197 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1198 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1199 | "dev": true, 1200 | "requires": { 1201 | "brace-expansion": "^1.1.7" 1202 | } 1203 | }, 1204 | "minimist": { 1205 | "version": "1.2.5", 1206 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1207 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1208 | "dev": true 1209 | }, 1210 | "mkdirp": { 1211 | "version": "0.5.5", 1212 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1213 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1214 | "dev": true, 1215 | "requires": { 1216 | "minimist": "^1.2.5" 1217 | } 1218 | }, 1219 | "mocha": { 1220 | "version": "8.2.1", 1221 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", 1222 | "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", 1223 | "dev": true, 1224 | "requires": { 1225 | "@ungap/promise-all-settled": "1.1.2", 1226 | "ansi-colors": "4.1.1", 1227 | "browser-stdout": "1.3.1", 1228 | "chokidar": "3.4.3", 1229 | "debug": "4.2.0", 1230 | "diff": "4.0.2", 1231 | "escape-string-regexp": "4.0.0", 1232 | "find-up": "5.0.0", 1233 | "glob": "7.1.6", 1234 | "growl": "1.10.5", 1235 | "he": "1.2.0", 1236 | "js-yaml": "3.14.0", 1237 | "log-symbols": "4.0.0", 1238 | "minimatch": "3.0.4", 1239 | "ms": "2.1.2", 1240 | "nanoid": "3.1.12", 1241 | "serialize-javascript": "5.0.1", 1242 | "strip-json-comments": "3.1.1", 1243 | "supports-color": "7.2.0", 1244 | "which": "2.0.2", 1245 | "wide-align": "1.1.3", 1246 | "workerpool": "6.0.2", 1247 | "yargs": "13.3.2", 1248 | "yargs-parser": "13.1.2", 1249 | "yargs-unparser": "2.0.0" 1250 | }, 1251 | "dependencies": { 1252 | "ansi-regex": { 1253 | "version": "4.1.0", 1254 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1255 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1256 | "dev": true 1257 | }, 1258 | "debug": { 1259 | "version": "4.2.0", 1260 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 1261 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 1262 | "dev": true, 1263 | "requires": { 1264 | "ms": "2.1.2" 1265 | } 1266 | }, 1267 | "escape-string-regexp": { 1268 | "version": "4.0.0", 1269 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1270 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1271 | "dev": true 1272 | }, 1273 | "find-up": { 1274 | "version": "5.0.0", 1275 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1276 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1277 | "dev": true, 1278 | "requires": { 1279 | "locate-path": "^6.0.0", 1280 | "path-exists": "^4.0.0" 1281 | } 1282 | }, 1283 | "has-flag": { 1284 | "version": "4.0.0", 1285 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1286 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1287 | "dev": true 1288 | }, 1289 | "locate-path": { 1290 | "version": "6.0.0", 1291 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1292 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1293 | "dev": true, 1294 | "requires": { 1295 | "p-locate": "^5.0.0" 1296 | } 1297 | }, 1298 | "ms": { 1299 | "version": "2.1.2", 1300 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1301 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1302 | "dev": true 1303 | }, 1304 | "p-limit": { 1305 | "version": "3.1.0", 1306 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1307 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1308 | "dev": true, 1309 | "requires": { 1310 | "yocto-queue": "^0.1.0" 1311 | } 1312 | }, 1313 | "p-locate": { 1314 | "version": "5.0.0", 1315 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1316 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1317 | "dev": true, 1318 | "requires": { 1319 | "p-limit": "^3.0.2" 1320 | } 1321 | }, 1322 | "path-exists": { 1323 | "version": "4.0.0", 1324 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1325 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1326 | "dev": true 1327 | }, 1328 | "string-width": { 1329 | "version": "3.1.0", 1330 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1331 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1332 | "dev": true, 1333 | "requires": { 1334 | "emoji-regex": "^7.0.1", 1335 | "is-fullwidth-code-point": "^2.0.0", 1336 | "strip-ansi": "^5.1.0" 1337 | } 1338 | }, 1339 | "strip-ansi": { 1340 | "version": "5.2.0", 1341 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1342 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1343 | "dev": true, 1344 | "requires": { 1345 | "ansi-regex": "^4.1.0" 1346 | } 1347 | }, 1348 | "supports-color": { 1349 | "version": "7.2.0", 1350 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1351 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1352 | "dev": true, 1353 | "requires": { 1354 | "has-flag": "^4.0.0" 1355 | } 1356 | }, 1357 | "yargs": { 1358 | "version": "13.3.2", 1359 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 1360 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 1361 | "dev": true, 1362 | "requires": { 1363 | "cliui": "^5.0.0", 1364 | "find-up": "^3.0.0", 1365 | "get-caller-file": "^2.0.1", 1366 | "require-directory": "^2.1.1", 1367 | "require-main-filename": "^2.0.0", 1368 | "set-blocking": "^2.0.0", 1369 | "string-width": "^3.0.0", 1370 | "which-module": "^2.0.0", 1371 | "y18n": "^4.0.0", 1372 | "yargs-parser": "^13.1.2" 1373 | }, 1374 | "dependencies": { 1375 | "find-up": { 1376 | "version": "3.0.0", 1377 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1378 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1379 | "dev": true, 1380 | "requires": { 1381 | "locate-path": "^3.0.0" 1382 | } 1383 | }, 1384 | "locate-path": { 1385 | "version": "3.0.0", 1386 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1387 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1388 | "dev": true, 1389 | "requires": { 1390 | "p-locate": "^3.0.0", 1391 | "path-exists": "^3.0.0" 1392 | } 1393 | }, 1394 | "p-limit": { 1395 | "version": "2.3.0", 1396 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1397 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1398 | "dev": true, 1399 | "requires": { 1400 | "p-try": "^2.0.0" 1401 | } 1402 | }, 1403 | "p-locate": { 1404 | "version": "3.0.0", 1405 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1406 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1407 | "dev": true, 1408 | "requires": { 1409 | "p-limit": "^2.0.0" 1410 | } 1411 | }, 1412 | "path-exists": { 1413 | "version": "3.0.0", 1414 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1415 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1416 | "dev": true 1417 | } 1418 | } 1419 | } 1420 | } 1421 | }, 1422 | "ms": { 1423 | "version": "2.0.0", 1424 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1425 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1426 | "dev": true 1427 | }, 1428 | "nanoid": { 1429 | "version": "3.1.12", 1430 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", 1431 | "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", 1432 | "dev": true 1433 | }, 1434 | "napi-macros": { 1435 | "version": "2.0.0", 1436 | "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz", 1437 | "integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==" 1438 | }, 1439 | "node-gyp-build": { 1440 | "version": "4.1.1", 1441 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", 1442 | "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==" 1443 | }, 1444 | "normalize-path": { 1445 | "version": "3.0.0", 1446 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1447 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1448 | "dev": true 1449 | }, 1450 | "normalize-url": { 1451 | "version": "4.5.0", 1452 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", 1453 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", 1454 | "dev": true 1455 | }, 1456 | "npm-conf": { 1457 | "version": "1.1.3", 1458 | "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", 1459 | "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", 1460 | "dev": true, 1461 | "optional": true, 1462 | "requires": { 1463 | "config-chain": "^1.1.11", 1464 | "pify": "^3.0.0" 1465 | }, 1466 | "dependencies": { 1467 | "pify": { 1468 | "version": "3.0.0", 1469 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1470 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", 1471 | "dev": true, 1472 | "optional": true 1473 | } 1474 | } 1475 | }, 1476 | "object-keys": { 1477 | "version": "1.1.1", 1478 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1479 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1480 | "dev": true, 1481 | "optional": true 1482 | }, 1483 | "once": { 1484 | "version": "1.4.0", 1485 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1486 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1487 | "dev": true, 1488 | "requires": { 1489 | "wrappy": "1" 1490 | } 1491 | }, 1492 | "p-cancelable": { 1493 | "version": "1.1.0", 1494 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 1495 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 1496 | "dev": true 1497 | }, 1498 | "p-try": { 1499 | "version": "2.2.0", 1500 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1501 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1502 | "dev": true 1503 | }, 1504 | "path-is-absolute": { 1505 | "version": "1.0.1", 1506 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1507 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1508 | "dev": true 1509 | }, 1510 | "path-parse": { 1511 | "version": "1.0.6", 1512 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1513 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 1514 | }, 1515 | "pend": { 1516 | "version": "1.2.0", 1517 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1518 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", 1519 | "dev": true 1520 | }, 1521 | "picomatch": { 1522 | "version": "2.2.2", 1523 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1524 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1525 | "dev": true 1526 | }, 1527 | "prepend-http": { 1528 | "version": "2.0.0", 1529 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1530 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 1531 | "dev": true 1532 | }, 1533 | "private": { 1534 | "version": "0.1.8", 1535 | "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", 1536 | "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" 1537 | }, 1538 | "process-nextick-args": { 1539 | "version": "2.0.1", 1540 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1541 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1542 | "dev": true 1543 | }, 1544 | "progress": { 1545 | "version": "2.0.3", 1546 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1547 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1548 | "dev": true 1549 | }, 1550 | "proto-list": { 1551 | "version": "1.2.4", 1552 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 1553 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", 1554 | "dev": true, 1555 | "optional": true 1556 | }, 1557 | "prr": { 1558 | "version": "1.0.1", 1559 | "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", 1560 | "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" 1561 | }, 1562 | "pump": { 1563 | "version": "3.0.0", 1564 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1565 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1566 | "dev": true, 1567 | "requires": { 1568 | "end-of-stream": "^1.1.0", 1569 | "once": "^1.3.1" 1570 | } 1571 | }, 1572 | "randombytes": { 1573 | "version": "2.1.0", 1574 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1575 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1576 | "dev": true, 1577 | "requires": { 1578 | "safe-buffer": "^5.1.0" 1579 | } 1580 | }, 1581 | "readable-stream": { 1582 | "version": "2.3.7", 1583 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1584 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1585 | "dev": true, 1586 | "requires": { 1587 | "core-util-is": "~1.0.0", 1588 | "inherits": "~2.0.3", 1589 | "isarray": "~1.0.0", 1590 | "process-nextick-args": "~2.0.0", 1591 | "safe-buffer": "~5.1.1", 1592 | "string_decoder": "~1.1.1", 1593 | "util-deprecate": "~1.0.1" 1594 | } 1595 | }, 1596 | "recast": { 1597 | "version": "0.20.4", 1598 | "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.4.tgz", 1599 | "integrity": "sha512-6qLIBGGRcwjrTZGIiBpJVC/NeuXpogXNyRQpqU1zWPUigCphvApoCs9KIwDYh1eDuJ6dAFlQoi/QUyE5KQ6RBQ==", 1600 | "requires": { 1601 | "ast-types": "0.14.2", 1602 | "esprima": "~4.0.0", 1603 | "source-map": "~0.6.1", 1604 | "tslib": "^2.0.1" 1605 | }, 1606 | "dependencies": { 1607 | "ast-types": { 1608 | "version": "0.14.2", 1609 | "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", 1610 | "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", 1611 | "requires": { 1612 | "tslib": "^2.0.1" 1613 | } 1614 | }, 1615 | "source-map": { 1616 | "version": "0.6.1", 1617 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1618 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1619 | } 1620 | } 1621 | }, 1622 | "require-directory": { 1623 | "version": "2.1.1", 1624 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1625 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1626 | "dev": true 1627 | }, 1628 | "require-main-filename": { 1629 | "version": "2.0.0", 1630 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1631 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1632 | "dev": true 1633 | }, 1634 | "resolve": { 1635 | "version": "1.19.0", 1636 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", 1637 | "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", 1638 | "requires": { 1639 | "is-core-module": "^2.1.0", 1640 | "path-parse": "^1.0.6" 1641 | } 1642 | }, 1643 | "responselike": { 1644 | "version": "1.0.2", 1645 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1646 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1647 | "dev": true, 1648 | "requires": { 1649 | "lowercase-keys": "^1.0.0" 1650 | } 1651 | }, 1652 | "rimraf": { 1653 | "version": "3.0.2", 1654 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1655 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1656 | "dev": true, 1657 | "requires": { 1658 | "glob": "^7.1.3" 1659 | } 1660 | }, 1661 | "roarr": { 1662 | "version": "2.15.4", 1663 | "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", 1664 | "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", 1665 | "dev": true, 1666 | "optional": true, 1667 | "requires": { 1668 | "boolean": "^3.0.1", 1669 | "detect-node": "^2.0.4", 1670 | "globalthis": "^1.0.1", 1671 | "json-stringify-safe": "^5.0.1", 1672 | "semver-compare": "^1.0.0", 1673 | "sprintf-js": "^1.1.2" 1674 | } 1675 | }, 1676 | "safe-buffer": { 1677 | "version": "5.1.2", 1678 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1679 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1680 | "dev": true 1681 | }, 1682 | "sanitize-filename": { 1683 | "version": "1.6.3", 1684 | "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", 1685 | "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", 1686 | "dev": true, 1687 | "requires": { 1688 | "truncate-utf8-bytes": "^1.0.0" 1689 | } 1690 | }, 1691 | "semver-compare": { 1692 | "version": "1.0.0", 1693 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 1694 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 1695 | "dev": true, 1696 | "optional": true 1697 | }, 1698 | "serialize-error": { 1699 | "version": "7.0.1", 1700 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", 1701 | "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", 1702 | "dev": true, 1703 | "optional": true, 1704 | "requires": { 1705 | "type-fest": "^0.13.1" 1706 | } 1707 | }, 1708 | "serialize-javascript": { 1709 | "version": "5.0.1", 1710 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 1711 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 1712 | "dev": true, 1713 | "requires": { 1714 | "randombytes": "^2.1.0" 1715 | } 1716 | }, 1717 | "set-blocking": { 1718 | "version": "2.0.0", 1719 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1720 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1721 | "dev": true 1722 | }, 1723 | "source-map": { 1724 | "version": "0.7.3", 1725 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", 1726 | "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" 1727 | }, 1728 | "sprintf-js": { 1729 | "version": "1.1.2", 1730 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 1731 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", 1732 | "dev": true, 1733 | "optional": true 1734 | }, 1735 | "string-width": { 1736 | "version": "2.1.1", 1737 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1738 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1739 | "dev": true, 1740 | "requires": { 1741 | "is-fullwidth-code-point": "^2.0.0", 1742 | "strip-ansi": "^4.0.0" 1743 | } 1744 | }, 1745 | "string_decoder": { 1746 | "version": "1.1.1", 1747 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1748 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1749 | "dev": true, 1750 | "requires": { 1751 | "safe-buffer": "~5.1.0" 1752 | } 1753 | }, 1754 | "strip-ansi": { 1755 | "version": "4.0.0", 1756 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1757 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1758 | "dev": true, 1759 | "requires": { 1760 | "ansi-regex": "^3.0.0" 1761 | } 1762 | }, 1763 | "strip-json-comments": { 1764 | "version": "3.1.1", 1765 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1766 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1767 | "dev": true 1768 | }, 1769 | "sumchecker": { 1770 | "version": "3.0.1", 1771 | "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", 1772 | "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", 1773 | "dev": true, 1774 | "requires": { 1775 | "debug": "^4.1.0" 1776 | }, 1777 | "dependencies": { 1778 | "debug": { 1779 | "version": "4.3.1", 1780 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1781 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1782 | "dev": true, 1783 | "requires": { 1784 | "ms": "2.1.2" 1785 | } 1786 | }, 1787 | "ms": { 1788 | "version": "2.1.2", 1789 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1790 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1791 | "dev": true 1792 | } 1793 | } 1794 | }, 1795 | "temp": { 1796 | "version": "0.9.4", 1797 | "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", 1798 | "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", 1799 | "dev": true, 1800 | "requires": { 1801 | "mkdirp": "^0.5.1", 1802 | "rimraf": "~2.6.2" 1803 | }, 1804 | "dependencies": { 1805 | "rimraf": { 1806 | "version": "2.6.3", 1807 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1808 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1809 | "dev": true, 1810 | "requires": { 1811 | "glob": "^7.1.3" 1812 | } 1813 | } 1814 | } 1815 | }, 1816 | "to-readable-stream": { 1817 | "version": "1.0.0", 1818 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 1819 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 1820 | "dev": true 1821 | }, 1822 | "truncate-utf8-bytes": { 1823 | "version": "1.0.2", 1824 | "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", 1825 | "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", 1826 | "dev": true, 1827 | "requires": { 1828 | "utf8-byte-length": "^1.0.1" 1829 | } 1830 | }, 1831 | "tslib": { 1832 | "version": "2.0.1", 1833 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", 1834 | "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" 1835 | }, 1836 | "tunnel": { 1837 | "version": "0.0.6", 1838 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 1839 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 1840 | "dev": true, 1841 | "optional": true 1842 | }, 1843 | "type-fest": { 1844 | "version": "0.13.1", 1845 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", 1846 | "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", 1847 | "dev": true, 1848 | "optional": true 1849 | }, 1850 | "typedarray": { 1851 | "version": "0.0.6", 1852 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1853 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1854 | "dev": true 1855 | }, 1856 | "universalify": { 1857 | "version": "0.1.2", 1858 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", 1859 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", 1860 | "dev": true 1861 | }, 1862 | "url-parse-lax": { 1863 | "version": "3.0.0", 1864 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1865 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1866 | "dev": true, 1867 | "requires": { 1868 | "prepend-http": "^2.0.0" 1869 | } 1870 | }, 1871 | "utf8-byte-length": { 1872 | "version": "1.0.4", 1873 | "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", 1874 | "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", 1875 | "dev": true 1876 | }, 1877 | "util-deprecate": { 1878 | "version": "1.0.2", 1879 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1880 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1881 | }, 1882 | "which": { 1883 | "version": "2.0.2", 1884 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1885 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1886 | "dev": true, 1887 | "requires": { 1888 | "isexe": "^2.0.0" 1889 | } 1890 | }, 1891 | "which-module": { 1892 | "version": "2.0.0", 1893 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1894 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1895 | "dev": true 1896 | }, 1897 | "wide-align": { 1898 | "version": "1.1.3", 1899 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1900 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1901 | "dev": true, 1902 | "requires": { 1903 | "string-width": "^1.0.2 || 2" 1904 | } 1905 | }, 1906 | "workerpool": { 1907 | "version": "6.0.2", 1908 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", 1909 | "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", 1910 | "dev": true 1911 | }, 1912 | "wrap-ansi": { 1913 | "version": "5.1.0", 1914 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 1915 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 1916 | "dev": true, 1917 | "requires": { 1918 | "ansi-styles": "^3.2.0", 1919 | "string-width": "^3.0.0", 1920 | "strip-ansi": "^5.0.0" 1921 | }, 1922 | "dependencies": { 1923 | "ansi-regex": { 1924 | "version": "4.1.0", 1925 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1926 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1927 | "dev": true 1928 | }, 1929 | "string-width": { 1930 | "version": "3.1.0", 1931 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1932 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1933 | "dev": true, 1934 | "requires": { 1935 | "emoji-regex": "^7.0.1", 1936 | "is-fullwidth-code-point": "^2.0.0", 1937 | "strip-ansi": "^5.1.0" 1938 | } 1939 | }, 1940 | "strip-ansi": { 1941 | "version": "5.2.0", 1942 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1943 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1944 | "dev": true, 1945 | "requires": { 1946 | "ansi-regex": "^4.1.0" 1947 | } 1948 | } 1949 | } 1950 | }, 1951 | "wrappy": { 1952 | "version": "1.0.2", 1953 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1954 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1955 | "dev": true 1956 | }, 1957 | "xtend": { 1958 | "version": "4.0.2", 1959 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1960 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1961 | }, 1962 | "y18n": { 1963 | "version": "4.0.1", 1964 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 1965 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", 1966 | "dev": true 1967 | }, 1968 | "yallist": { 1969 | "version": "4.0.0", 1970 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1971 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1972 | "dev": true, 1973 | "optional": true 1974 | }, 1975 | "yargs": { 1976 | "version": "16.2.0", 1977 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1978 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1979 | "dev": true, 1980 | "requires": { 1981 | "cliui": "^7.0.2", 1982 | "escalade": "^3.1.1", 1983 | "get-caller-file": "^2.0.5", 1984 | "require-directory": "^2.1.1", 1985 | "string-width": "^4.2.0", 1986 | "y18n": "^5.0.5", 1987 | "yargs-parser": "^20.2.2" 1988 | }, 1989 | "dependencies": { 1990 | "ansi-regex": { 1991 | "version": "5.0.0", 1992 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 1993 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 1994 | "dev": true 1995 | }, 1996 | "ansi-styles": { 1997 | "version": "4.3.0", 1998 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1999 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2000 | "dev": true, 2001 | "requires": { 2002 | "color-convert": "^2.0.1" 2003 | } 2004 | }, 2005 | "cliui": { 2006 | "version": "7.0.4", 2007 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 2008 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 2009 | "dev": true, 2010 | "requires": { 2011 | "string-width": "^4.2.0", 2012 | "strip-ansi": "^6.0.0", 2013 | "wrap-ansi": "^7.0.0" 2014 | } 2015 | }, 2016 | "color-convert": { 2017 | "version": "2.0.1", 2018 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2019 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2020 | "dev": true, 2021 | "requires": { 2022 | "color-name": "~1.1.4" 2023 | } 2024 | }, 2025 | "color-name": { 2026 | "version": "1.1.4", 2027 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2028 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2029 | "dev": true 2030 | }, 2031 | "emoji-regex": { 2032 | "version": "8.0.0", 2033 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2034 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2035 | "dev": true 2036 | }, 2037 | "is-fullwidth-code-point": { 2038 | "version": "3.0.0", 2039 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2040 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2041 | "dev": true 2042 | }, 2043 | "string-width": { 2044 | "version": "4.2.0", 2045 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 2046 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 2047 | "dev": true, 2048 | "requires": { 2049 | "emoji-regex": "^8.0.0", 2050 | "is-fullwidth-code-point": "^3.0.0", 2051 | "strip-ansi": "^6.0.0" 2052 | } 2053 | }, 2054 | "strip-ansi": { 2055 | "version": "6.0.0", 2056 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2057 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2058 | "dev": true, 2059 | "requires": { 2060 | "ansi-regex": "^5.0.0" 2061 | } 2062 | }, 2063 | "wrap-ansi": { 2064 | "version": "7.0.0", 2065 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2066 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2067 | "dev": true, 2068 | "requires": { 2069 | "ansi-styles": "^4.0.0", 2070 | "string-width": "^4.1.0", 2071 | "strip-ansi": "^6.0.0" 2072 | } 2073 | }, 2074 | "y18n": { 2075 | "version": "5.0.5", 2076 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", 2077 | "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", 2078 | "dev": true 2079 | }, 2080 | "yargs-parser": { 2081 | "version": "20.2.4", 2082 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 2083 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 2084 | "dev": true 2085 | } 2086 | } 2087 | }, 2088 | "yargs-parser": { 2089 | "version": "13.1.2", 2090 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 2091 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 2092 | "dev": true, 2093 | "requires": { 2094 | "camelcase": "^5.0.0", 2095 | "decamelize": "^1.2.0" 2096 | } 2097 | }, 2098 | "yargs-unparser": { 2099 | "version": "2.0.0", 2100 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 2101 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 2102 | "dev": true, 2103 | "requires": { 2104 | "camelcase": "^6.0.0", 2105 | "decamelize": "^4.0.0", 2106 | "flat": "^5.0.2", 2107 | "is-plain-obj": "^2.1.0" 2108 | }, 2109 | "dependencies": { 2110 | "camelcase": { 2111 | "version": "6.2.0", 2112 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 2113 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 2114 | "dev": true 2115 | }, 2116 | "decamelize": { 2117 | "version": "4.0.0", 2118 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 2119 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 2120 | "dev": true 2121 | } 2122 | } 2123 | }, 2124 | "yauzl": { 2125 | "version": "2.10.0", 2126 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 2127 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 2128 | "dev": true, 2129 | "requires": { 2130 | "buffer-crc32": "~0.2.3", 2131 | "fd-slicer": "~1.1.0" 2132 | } 2133 | }, 2134 | "yocto-queue": { 2135 | "version": "0.1.0", 2136 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2137 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2138 | "dev": true 2139 | } 2140 | } 2141 | } 2142 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-link", 3 | "version": "0.6.0", 4 | "description": "Generates scripts to pass to V8's `mksnapshot` tool.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "mocha test/**/*.test.js --ui=tdd", 8 | "tdd": "electron-mocha test/**/*.test.js --ui=tdd --renderer --interactive" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "dedent": "0.7.0", 14 | "electron": "^9", 15 | "electron-mocha": "^10.0.0", 16 | "mocha": "^8.2.1", 17 | "rimraf": "3.0.2", 18 | "temp": "0.9.4" 19 | }, 20 | "dependencies": { 21 | "acorn": "^8.0.4", 22 | "ast-util-plus": "^0.7.1", 23 | "encoding-down": "^6.3.0", 24 | "indent-string": "^4.0.0", 25 | "leveldown": "^5.6.0", 26 | "levelup": "^4.4.0", 27 | "recast": "^0.20.4", 28 | "resolve": "^1.19.0", 29 | "source-map": "^0.7.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/fixtures/cyclic-require/a.js: -------------------------------------------------------------------------------- 1 | const b = require('./b') 2 | 3 | global.cyclicRequire = function () { 4 | return {a: 'a', b: b.value, d: require('./d'), e: require('./e')} 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/cyclic-require/b.js: -------------------------------------------------------------------------------- 1 | require('./a') 2 | require('./c') 3 | 4 | exports.value = 'b' 5 | -------------------------------------------------------------------------------- /test/fixtures/cyclic-require/c.js: -------------------------------------------------------------------------------- 1 | require('./b') 2 | -------------------------------------------------------------------------------- /test/fixtures/cyclic-require/d.js: -------------------------------------------------------------------------------- 1 | require('./e') 2 | 3 | module.exports = 'd' 4 | -------------------------------------------------------------------------------- /test/fixtures/cyclic-require/e.js: -------------------------------------------------------------------------------- 1 | require('./d') 2 | 3 | module.exports = 'e' 4 | -------------------------------------------------------------------------------- /test/fixtures/module-1/dir/a.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = function () { 4 | return 'a' + require('./subdir/b').b + path.join('x', 'y') 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/module-1/dir/c.json: -------------------------------------------------------------------------------- 1 | {"d": "d"} 2 | -------------------------------------------------------------------------------- /test/fixtures/module-1/dir/subdir/b.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | this.b = 'b' 3 | }).call(this) 4 | -------------------------------------------------------------------------------- /test/fixtures/module-1/index.js: -------------------------------------------------------------------------------- 1 | const a = require('./dir/a') 2 | const b = require('./dir/subdir/b').b 3 | const c = require('./dir/c') 4 | 5 | global.initialize = function () { 6 | global.moduleInitialized = true 7 | return a() + b + require('a') + c.d 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/module-1/node_modules/a/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'A' 2 | -------------------------------------------------------------------------------- /test/fixtures/module-2/index.js: -------------------------------------------------------------------------------- 1 | global.module2 = {platform: process.platform} 2 | -------------------------------------------------------------------------------- /test/samples/.gitignore: -------------------------------------------------------------------------------- 1 | link-cache/ 2 | *.linked.js 3 | -------------------------------------------------------------------------------- /test/samples/alias-global-function.js: -------------------------------------------------------------------------------- 1 | // Create an alias to a globally-defined function, but don't call it until runtime. 2 | // This is a common occurrence in minimized source. 3 | // 4 | // Run with: npx @smashwilson/run-in-snapshot --link test/samples/alias-global-function.js 5 | 6 | const localSetTimeout = setTimeout; 7 | 8 | // This is invalid and should fail snapshot creation. 9 | // localSetTimeout(() => {}, 1000); 10 | 11 | const LocalBuffer = Buffer; 12 | 13 | // DOMPoint is only available in renderer processes 14 | const LocalDOMPoint = DOMPoint; 15 | 16 | // This is invalid and should fail snapshot creation. 17 | // new Buffer(0, 0, 0, 0); 18 | 19 | async function main() { 20 | // React does feature gating with "if (typeof localSetTimeout !== 'function') {}" gates. 21 | console.log(`typeof localSetTimeout = ${typeof localSetTimeout}`) 22 | 23 | console.log('calling setTimeout directly at runtime') 24 | await new Promise(resolve => setTimeout(resolve, 1000)) 25 | 26 | console.log('calling setTimeout through captured alias at runtime') 27 | await new Promise(resolve => localSetTimeout(resolve, 1000)) 28 | 29 | console.log('calling Buffer constructor directly at runtime') 30 | const b0 = new Buffer('first', 'utf8') 31 | console.log(`buffer 0 = ${b0.toString()}`) 32 | 33 | console.log('calling LocalBuffer constructor directly at runtime') 34 | const b1 = new LocalBuffer('second', 'utf8') 35 | console.log(`buffer 1 = ${b1.toString()}`) 36 | 37 | console.log('attempt to construct a DOMPoint with its constructor') 38 | try { 39 | new DOMPoint(0, 0, 0, 0) 40 | console.log('point was constructed!') 41 | } catch (e) { 42 | console.log('expected error caught: ok') 43 | } 44 | 45 | console.log('attempt to construct a DOMPoint through its aliased constructor') 46 | try { 47 | new LocalDOMPoint(0, 0, 0, 0) 48 | console.log('point was constructed!') 49 | } catch(e) { 50 | console.log('expected error caught: ok') 51 | } 52 | 53 | console.log('ok') 54 | 55 | return null; 56 | } 57 | 58 | exports.main = main; 59 | -------------------------------------------------------------------------------- /test/samples/list-globals.js: -------------------------------------------------------------------------------- 1 | // Identify global functions that are present in an Electron runtime, but not at snapshot generation time. 2 | // The resulting list is used in blueprint.js to create shim functions. 3 | // 4 | // Run with: npx @smashwilson/run-in-snapshot test/samples/list-globals.js 5 | 6 | /* 7 | This Array is generated by opening this project with "atom --safe" and running the following in a dev console: 8 | 9 | const editor = atom.workspace.getActiveTextEditor() 10 | let globalNames = Object 11 | .getOwnPropertyNames(global) 12 | .filter(globalName => typeof global[globalName] === 'function') 13 | .map(globalName => `"${globalName}"`) 14 | .join(', ') 15 | editor.insertText(`const globalNames = [${globalNames}]`) 16 | */ 17 | const globalNames = [ 18 | "Object", "Function", "Array", "Number", "parseFloat", "parseInt", "Boolean", "String", "Symbol", "Date", "Promise", 19 | "RegExp", "Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", "ArrayBuffer", 20 | "Uint8Array", "Int8Array", "Uint16Array", "Int16Array", "Uint32Array", "Int32Array", "Float32Array", "Float64Array", 21 | "Uint8ClampedArray", "DataView", "Map", "Set", "WeakMap", "WeakSet", "Proxy", "decodeURI", "decodeURIComponent", 22 | "encodeURI", "encodeURIComponent", "escape", "unescape", "eval", "isFinite", "isNaN", "ByteLengthQueuingStrategy", 23 | "CountQueuingStrategy", "ReadableStream", "WritableStream", "USBOutTransferResult", "USBIsochronousOutTransferResult", 24 | "USBIsochronousOutTransferPacket", "USBIsochronousInTransferResult", "USBIsochronousInTransferPacket", 25 | "USBInTransferResult", "USBInterface", "USBEndpoint", "USBDevice", "USBConnectionEvent", "USBConfiguration", 26 | "USBAlternateInterface", "USB", "NFC", "BluetoothUUID", "BluetoothRemoteGATTService", "BluetoothRemoteGATTServer", 27 | "BluetoothRemoteGATTDescriptor", "BluetoothRemoteGATTCharacteristic", "BluetoothDevice", 28 | "BluetoothCharacteristicProperties", "Bluetooth", "WebAuthentication", "PublicKeyCredential", "AuthenticatorResponse", 29 | "AuthenticatorAttestationResponse", "AuthenticatorAssertionResponse", "WebGLRenderingContext", 30 | "WebGL2RenderingContext", "Path2D", "CanvasPattern", "CanvasGradient", "TextDetector", "FaceDetector", "DetectedText", 31 | "DetectedFace", "DetectedBarcode", "BarcodeDetector", "NavigationPreloadManager", "SensorErrorEvent", "Sensor", 32 | "RelativeOrientationSensor", "OrientationSensor", "Magnetometer", "LinearAccelerationSensor", "Gyroscope", 33 | "AmbientLightSensor", "Accelerometer", "AbsoluteOrientationSensor", "webkitSpeechRecognitionEvent", 34 | "webkitSpeechRecognitionError", "webkitSpeechRecognition", "webkitSpeechGrammarList", "webkitSpeechGrammar", 35 | "SpeechSynthesisUtterance", "SpeechSynthesisEvent", "RemotePlayback", "RTCRtpSender", "PushSubscriptionOptions", 36 | "PushSubscription", "PushManager", "PresentationReceiver", "PresentationConnectionList", "PresentationRequest", 37 | "PresentationConnectionCloseEvent", "PresentationConnectionAvailableEvent", "PresentationConnection", 38 | "PresentationAvailability", "Presentation", "PermissionStatus", "Permissions", "PaymentResponse", 39 | "PaymentRequestUpdateEvent", "PaymentRequest", "PaymentAddress", "PaymentManager", "Notification", 40 | "VideoPlaybackQuality", "TrackDefaultList", "TrackDefault", "CanvasCaptureMediaStreamTrack", "PhotoCapabilities", 41 | "MediaSettingsRange", "ImageCapture", "IDBObserverChanges", "IDBObserver", "IDBObservation", "StorageManager", 42 | "CompositorWorker", "BudgetService", "BroadcastChannel", "SyncManager", "BackgroundFetchRegistration", 43 | "BackgroundFetchManager", "BackgroundFetchFetch", "AudioParamMap", "XSLTProcessor", "Worklet", "VTTRegion", 44 | "KeyframeEffectReadOnly", "KeyframeEffect", "DocumentTimeline", "AnimationTimeline", "AnimationPlaybackEvent", 45 | "AnimationEffectTimingReadOnly", "AnimationEffectTiming", "AnimationEffectReadOnly", "Animation", "VisualViewport", 46 | "SharedWorker", "PerformanceServerTiming", "SVGMPathElement", "SVGDiscardElement", "SVGAnimationElement", 47 | "ResizeObserverEntry", "ResizeObserver", "PerformancePaintTiming", "PerformanceObserverEntryList", 48 | "PerformanceObserver", "PerformanceNavigationTiming", "IntersectionObserverEntry", "IntersectionObserver", 49 | "StaticRange", "InputEvent", "DOMRectReadOnly", "DOMRect", "DOMQuad", "DOMPointReadOnly", "DOMPoint", 50 | "DOMMatrixReadOnly", "DOMMatrix", "ScrollTimeline", "StylePropertyMapReadonly", "StylePropertyMap", 51 | "CSSVariableReferenceValue", "CSSURLImageValue", "CSSUnparsedValue", "CSSUnitValue", "CSSTranslation", 52 | "CSSTransformValue", "CSSTransformComponent", "CSSStyleValue", "CSSSkew", "CSSScale", "CSSRotation", 53 | "CSSResourceValue", "CSSPositionValue", "CSSPerspective", "CSSNumericValue", "CSSMatrixComponent", "CSSKeywordValue", 54 | "CSSImageValue", "VideoTrackList", "VideoTrack", "AudioTrackList", "AudioTrack", "AccessibleNodeList", 55 | "AccessibleNode", "webkitRTCPeerConnection", "webkitMediaStream", "WebSocket", "WebGLVertexArrayObject", 56 | "WebGLUniformLocation", "WebGLTransformFeedback", "WebGLTexture", "WebGLSync", "WebGLShaderPrecisionFormat", 57 | "WebGLShader", "WebGLSampler", "WebGLRenderbuffer", "WebGLQuery", "WebGLProgram", "WebGLFramebuffer", 58 | "WebGLContextEvent", "WebGLBuffer", "WebGLActiveInfo", "WaveShaperNode", "TextEncoder", "TextDecoder", "SubtleCrypto", 59 | "StorageEvent", "Storage", "StereoPannerNode", "SourceBufferList", "SourceBuffer", "ServiceWorkerRegistration", 60 | "ServiceWorkerContainer", "ServiceWorker", "ScriptProcessorNode", "ScreenOrientation", "Response", "Request", 61 | "RTCStatsReport", "RTCSessionDescription", "RTCRtpReceiver", "RTCRtpContributingSource", "RTCPeerConnectionIceEvent", 62 | "RTCPeerConnection", "RTCIceCandidate", "RTCDataChannelEvent", "RTCDataChannel", "RTCCertificate", "Plugin", 63 | "PluginArray", "PeriodicWave", "PasswordCredential", "PannerNode", "OscillatorNode", "OfflineAudioContext", 64 | "OfflineAudioCompletionEvent", "NetworkInformation", "MimeType", "MimeTypeArray", "MediaStreamTrackEvent", 65 | "MediaStreamTrack", "MediaStreamEvent", "MediaStream", "MediaStreamAudioSourceNode", 66 | "MediaStreamAudioDestinationNode", "MediaSource", "MediaRecorder", "MediaKeys", "MediaKeySystemAccess", 67 | "MediaKeyStatusMap", "MediaKeySession", "MediaKeyMessageEvent", "MediaEncryptedEvent", "MediaElementAudioSourceNode", 68 | "MediaDevices", "MediaDeviceInfo", "MIDIPort", "MIDIOutputMap", "MIDIOutput", "MIDIMessageEvent", "MIDIInputMap", 69 | "MIDIInput", "MIDIConnectionEvent", "MIDIAccess", "ImageBitmapRenderingContext", "IIRFilterNode", 70 | "IDBVersionChangeEvent", "IDBTransaction", "IDBRequest", "IDBOpenDBRequest", "IDBObjectStore", "IDBKeyRange", 71 | "IDBIndex", "IDBFactory", "IDBDatabase", "IDBCursorWithValue", "IDBCursor", "Headers", "GamepadEvent", "Gamepad", 72 | "GamepadButton", "GainNode", "FederatedCredential", "EventSource", "DynamicsCompressorNode", "DeviceOrientationEvent", 73 | "DeviceMotionEvent", "DelayNode", "DOMError", "CryptoKey", "Crypto", "CredentialsContainer", "Credential", 74 | "ConvolverNode", "ConstantSourceNode", "CloseEvent", "ChannelSplitterNode", "ChannelMergerNode", 75 | "CanvasRenderingContext2D", "CacheStorage", "Cache", "BlobEvent", "BiquadFilterNode", "BeforeInstallPromptEvent", 76 | "BatteryManager", "BaseAudioContext", "AudioScheduledSourceNode", "AudioProcessingEvent", "AudioParam", "AudioNode", 77 | "AudioListener", "AudioDestinationNode", "AudioContext", "AudioBufferSourceNode", "AudioBuffer", 78 | "AppBannerPromptResult", "AnalyserNode", "postMessage", "blur", "focus", "close", "XPathResult", "XPathExpression", 79 | "XPathEvaluator", "XMLSerializer", "XMLHttpRequestUpload", "XMLHttpRequestEventTarget", "XMLHttpRequest", 80 | "XMLDocument", "Worker", "Window", "WheelEvent", "ValidityState", "VTTCue", "URLSearchParams", "URL", "UIEvent", 81 | "TreeWalker", "TransitionEvent", "TrackEvent", "TouchList", "TouchEvent", "Touch", "TimeRanges", "TextTrackList", 82 | "TextTrackCueList", "TextTrackCue", "TextTrack", "TextMetrics", "TextEvent", "Text", "TaskAttributionTiming", 83 | "StyleSheetList", "StyleSheet", "ShadowRoot", "Selection", "SecurityPolicyViolationEvent", "Screen", "SVGViewElement", 84 | "SVGUseElement", "SVGUnitTypes", "SVGTransformList", "SVGTransform", "SVGTitleElement", "SVGTextPositioningElement", 85 | "SVGTextPathElement", "SVGTextElement", "SVGTextContentElement", "SVGTSpanElement", "SVGSymbolElement", 86 | "SVGSwitchElement", "SVGStyleElement", "SVGStringList", "SVGStopElement", "SVGSetElement", "SVGScriptElement", 87 | "SVGSVGElement", "SVGRectElement", "SVGRect", "SVGRadialGradientElement", "SVGPreserveAspectRatio", 88 | "SVGPolylineElement", "SVGPolygonElement", "SVGPointList", "SVGPoint", "SVGPatternElement", "SVGPathElement", 89 | "SVGNumberList", "SVGNumber", "SVGMetadataElement", "SVGMatrix", "SVGMaskElement", "SVGMarkerElement", 90 | "SVGLinearGradientElement", "SVGLineElement", "SVGLengthList", "SVGLength", "SVGImageElement", "SVGGraphicsElement", 91 | "SVGGradientElement", "SVGGeometryElement", "SVGGElement", "SVGForeignObjectElement", "SVGFilterElement", 92 | "SVGFETurbulenceElement", "SVGFETileElement", "SVGFESpotLightElement", "SVGFESpecularLightingElement", 93 | "SVGFEPointLightElement", "SVGFEOffsetElement", "SVGFEMorphologyElement", "SVGFEMergeNodeElement", 94 | "SVGFEMergeElement", "SVGFEImageElement", "SVGFEGaussianBlurElement", "SVGFEFuncRElement", "SVGFEFuncGElement", 95 | "SVGFEFuncBElement", "SVGFEFuncAElement", "SVGFEFloodElement", "SVGFEDropShadowElement", "SVGFEDistantLightElement", 96 | "SVGFEDisplacementMapElement", "SVGFEDiffuseLightingElement", "SVGFEConvolveMatrixElement", "SVGFECompositeElement", 97 | "SVGFEComponentTransferElement", "SVGFEColorMatrixElement", "SVGFEBlendElement", "SVGEllipseElement", "SVGElement", 98 | "SVGDescElement", "SVGDefsElement", "SVGComponentTransferFunctionElement", "SVGClipPathElement", "SVGCircleElement", 99 | "SVGAnimatedTransformList", "SVGAnimatedString", "SVGAnimatedRect", "SVGAnimatedPreserveAspectRatio", 100 | "SVGAnimatedNumberList", "SVGAnimatedNumber", "SVGAnimatedLengthList", "SVGAnimatedLength", "SVGAnimatedInteger", 101 | "SVGAnimatedEnumeration", "SVGAnimatedBoolean", "SVGAnimatedAngle", "SVGAnimateTransformElement", 102 | "SVGAnimateMotionElement", "SVGAnimateElement", "SVGAngle", "SVGAElement", "Range", "RadioNodeList", 103 | "PromiseRejectionEvent", "ProgressEvent", "ProcessingInstruction", "PopStateEvent", "PointerEvent", 104 | "PerformanceTiming", "PerformanceResourceTiming", "PerformanceNavigation", "PerformanceMeasure", "PerformanceMark", 105 | "PerformanceLongTaskTiming", "PerformanceEntry", "Performance", "PageTransitionEvent", "NodeList", "NodeIterator", 106 | "NodeFilter", "Node", "Navigator", "NamedNodeMap", "MutationRecord", "MutationObserver", "MutationEvent", 107 | "MouseEvent", "MessagePort", "MessageEvent", "MessageChannel", "MediaQueryListEvent", "MediaQueryList", "MediaList", 108 | "MediaError", "Location", "KeyboardEvent", "InputDeviceCapabilities", "ImageData", "ImageBitmap", "IdleDeadline", 109 | "History", "HashChangeEvent", "HTMLVideoElement", "HTMLUnknownElement", "HTMLUListElement", "HTMLTrackElement", 110 | "HTMLTitleElement", "HTMLTextAreaElement", "HTMLTemplateElement", "HTMLTableSectionElement", "HTMLTableRowElement", 111 | "HTMLTableElement", "HTMLTableColElement", "HTMLTableCellElement", "HTMLTableCaptionElement", "HTMLStyleElement", 112 | "HTMLSpanElement", "HTMLSourceElement", "HTMLSlotElement", "HTMLShadowElement", "HTMLSelectElement", 113 | "HTMLScriptElement", "HTMLQuoteElement", "HTMLProgressElement", "HTMLPreElement", "HTMLPictureElement", 114 | "HTMLParamElement", "HTMLParagraphElement", "HTMLOutputElement", "HTMLOptionsCollection", "Option", 115 | "HTMLOptionElement", "HTMLOptGroupElement", "HTMLObjectElement", "HTMLOListElement", "HTMLModElement", 116 | "HTMLMeterElement", "HTMLMetaElement", "HTMLMenuElement", "HTMLMediaElement", "HTMLMarqueeElement", "HTMLMapElement", 117 | "HTMLLinkElement", "HTMLLegendElement", "HTMLLabelElement", "HTMLLIElement", "HTMLInputElement", "Image", 118 | "HTMLImageElement", "HTMLIFrameElement", "HTMLHtmlElement", "HTMLHeadingElement", "HTMLHeadElement", "HTMLHRElement", 119 | "HTMLFrameSetElement", "HTMLFrameElement", "HTMLFormElement", "HTMLFormControlsCollection", "HTMLFontElement", 120 | "HTMLFieldSetElement", "HTMLEmbedElement", "HTMLElement", "HTMLDocument", "HTMLDivElement", "HTMLDirectoryElement", 121 | "HTMLDialogElement", "HTMLDetailsElement", "HTMLDataListElement", "HTMLDListElement", "HTMLContentElement", 122 | "HTMLCollection", "HTMLCanvasElement", "HTMLButtonElement", "HTMLBodyElement", "HTMLBaseElement", "HTMLBRElement", 123 | "Audio", "HTMLAudioElement", "HTMLAreaElement", "HTMLAnchorElement", "HTMLAllCollection", "FormData", 124 | "FontFaceSetLoadEvent", "FontFace", "FocusEvent", "FileReader", "FileList", "File", "EventTarget", "Event", 125 | "ErrorEvent", "Element", "DragEvent", "DocumentType", "DocumentFragment", "Document", "DataTransferItemList", 126 | "DataTransferItem", "DataTransfer", "DOMTokenList", "DOMStringMap", "DOMStringList", "DOMParser", "DOMImplementation", 127 | "DOMException", "CustomEvent", "CustomElementRegistry", "CompositionEvent", "Comment", "ClipboardEvent", "Clipboard", 128 | "CharacterData", "CSSViewportRule", "CSSSupportsRule", "CSSStyleSheet", "CSSStyleRule", "CSSStyleDeclaration", 129 | "CSSRuleList", "CSSRule", "CSSPageRule", "CSSNamespaceRule", "CSSMediaRule", "CSSKeyframesRule", "CSSKeyframeRule", 130 | "CSSImportRule", "CSSGroupingRule", "CSSFontFaceRule", "CSS", "CSSConditionRule", "CDATASection", "Blob", 131 | "BeforeUnloadEvent", "BarProp", "Attr", "ApplicationCacheErrorEvent", "ApplicationCache", "AnimationEvent", 132 | "WebKitCSSMatrix", "WebKitMutationObserver", "webkitURL", "WebKitAnimationEvent", "WebKitTransitionEvent", "onerror", 133 | "onload", "stop", "open", "alert", "confirm", "prompt", "print", "requestAnimationFrame", "cancelAnimationFrame", 134 | "requestIdleCallback", "cancelIdleCallback", "captureEvents", "releaseEvents", "getComputedStyle", "matchMedia", 135 | "moveTo", "moveBy", "resizeTo", "resizeBy", "getSelection", "find", "getMatchedCSSRules", 136 | "webkitRequestAnimationFrame", "webkitCancelAnimationFrame", "btoa", "atob", "setTimeout", "clearTimeout", 137 | "setInterval", "clearInterval", "createImageBitmap", "scroll", "scrollTo", "scrollBy", "fetch", "getComputedStyleMap", 138 | "webkitRequestFileSystem", "webkitResolveLocalFileSystemURL", "openDatabase", "SharedArrayBuffer", "Buffer", 139 | "setImmediate", "clearImmediate", "require", "BudgetState", "WebView", "measure", "profile", "dir", "dirxml", 140 | "profileEnd", "clear", "table", "keys", "values", "debug", "undebug", "monitor", "unmonitor", "inspect", "copy", 141 | "getEventListeners", "monitorEvents", "unmonitorEvents", "$", "$$", "$x" 142 | ] 143 | 144 | const report = globalNames.reduce((r, globalName) => { 145 | try { 146 | eval(globalName); 147 | r.existing.push(globalName); 148 | } catch (e) { 149 | // Not defined at mksnapshot time 150 | r.missing.push(globalName); 151 | } 152 | return r; 153 | }, {existing: [], missing: []}); 154 | 155 | async function main() { 156 | return report.existing.map(each => `"${each}"`).join(', '); 157 | } 158 | -------------------------------------------------------------------------------- /test/unit/file-require-transform.test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const assert = require('assert') 4 | const dedent = require('dedent') 5 | const path = require('path') 6 | const recast = require('recast') 7 | const FileRequireTransform = require('../../lib/file-require-transform') 8 | 9 | suite('FileRequireTransform', () => { 10 | test('simple require', () => { 11 | const source = dedent` 12 | const a = require('a') 13 | const b = require('b') 14 | function main () { 15 | const c = {a: b, b: a} 16 | return a + b 17 | } 18 | ` 19 | assert.equal( 20 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'a'}).apply(), 21 | dedent` 22 | let a; 23 | 24 | function get_a() { 25 | return a = a || require('a'); 26 | } 27 | 28 | const b = require('b') 29 | function main () { 30 | const c = {a: b, b: get_a()} 31 | return get_a() + b; 32 | } 33 | ` 34 | ) 35 | }) 36 | 37 | test('conditional requires', () => { 38 | const source = dedent` 39 | let a, b; 40 | if (condition) { 41 | a = require('a') 42 | b = require('b') 43 | } else { 44 | a = require('c') 45 | b = require('d') 46 | } 47 | 48 | function main () { 49 | return a + b 50 | } 51 | ` 52 | assert.equal( 53 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'a' || mod === 'c'}).apply(), 54 | dedent` 55 | let a, b; 56 | let get_a; 57 | if (condition) { 58 | get_a = function() { 59 | return a = a || require('a'); 60 | } 61 | b = require('b') 62 | } else { 63 | get_a = function() { 64 | return a = a || require('c'); 65 | } 66 | b = require('d') 67 | } 68 | 69 | function main () { 70 | return get_a() + b; 71 | } 72 | ` 73 | ) 74 | }) 75 | 76 | test('top-level variables assignments that depend on previous requires', () => { 77 | const source = dedent` 78 | const a = require('a') 79 | const b = require('b') 80 | const c = require('c').foo.bar 81 | const d = c.X | c.Y | c.Z 82 | var e 83 | e = c.e 84 | const f = b.f 85 | function main () { 86 | c.qux() 87 | console.log(d) 88 | e() 89 | } 90 | ` 91 | assert.equal( 92 | new FileRequireTransform({source, didFindRequire: (mod) => ['a', 'c'].indexOf(mod) >= 0}).apply(), 93 | dedent` 94 | let a; 95 | 96 | function get_a() { 97 | return a = a || require('a'); 98 | } 99 | 100 | const b = require('b') 101 | let c; 102 | 103 | function get_c() { 104 | return c = c || require('c').foo.bar; 105 | } 106 | 107 | let d; 108 | 109 | function get_d() { 110 | return d = d || get_c().X | get_c().Y | get_c().Z; 111 | } 112 | 113 | var e 114 | function get_e() { 115 | return e = e || get_c().e; 116 | }; 117 | const f = b.f 118 | function main () { 119 | get_c().qux() 120 | get_console().log(get_d()) 121 | get_e()() 122 | } 123 | `) 124 | }) 125 | 126 | test('requires that appear in a closure wrapper defined in the top-level scope (e.g. CoffeeScript)', () => { 127 | const source = dedent` 128 | (function () { 129 | const a = require('a') 130 | const b = require('b') 131 | function main () { 132 | return a + b 133 | } 134 | }).call(this) 135 | 136 | (function () { 137 | const a = require('a') 138 | const b = require('b') 139 | function main () { 140 | return a + b 141 | } 142 | })() 143 | 144 | foo(function () { 145 | const b = require('b') 146 | const c = require('c') 147 | function main () { 148 | return b + c 149 | } 150 | }) 151 | ` 152 | assert.equal( 153 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'a' || mod === 'c'}).apply(), 154 | dedent` 155 | (function () { 156 | let a; 157 | 158 | function get_a() { 159 | return a = a || require('a'); 160 | } 161 | 162 | const b = require('b') 163 | function main () { 164 | return get_a() + b; 165 | } 166 | }).call(this) 167 | 168 | (function () { 169 | let a; 170 | 171 | function get_a() { 172 | return a = a || require('a'); 173 | } 174 | 175 | const b = require('b') 176 | function main () { 177 | return get_a() + b; 178 | } 179 | })() 180 | 181 | foo(function () { 182 | const b = require('b') 183 | const c = require('c') 184 | function main () { 185 | return b + c 186 | } 187 | }) 188 | ` 189 | ) 190 | }) 191 | 192 | test('references to shadowed variables', () => { 193 | const source = dedent` 194 | const a = require('a') 195 | function outer () { 196 | console.log(a) 197 | function inner () { 198 | console.log(a) 199 | } 200 | let a = [] 201 | } 202 | 203 | function other () { 204 | console.log(a) 205 | function inner () { 206 | let a = [] 207 | console.log(a) 208 | } 209 | } 210 | ` 211 | assert.equal( 212 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'a'}).apply(), 213 | dedent` 214 | let a; 215 | 216 | function get_a() { 217 | return a = a || require('a'); 218 | } 219 | 220 | function outer () { 221 | get_console().log(a) 222 | function inner () { 223 | get_console().log(a) 224 | } 225 | let a = [] 226 | } 227 | 228 | function other () { 229 | get_console().log(get_a()) 230 | function inner () { 231 | let a = [] 232 | get_console().log(a) 233 | } 234 | } 235 | ` 236 | ) 237 | }) 238 | 239 | test('references to globals', () => { 240 | const source = dedent` 241 | global.a = 1 242 | process.b = 2 243 | window.c = 3 244 | document.d = 4 245 | 246 | function inner () { 247 | const window = {} 248 | global.e = 4 249 | process.f = 5 250 | window.g = 6 251 | document.h = 7 252 | } 253 | ` 254 | assert.equal( 255 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'a'}).apply(), 256 | dedent` 257 | get_global().a = 1 258 | get_process().b = 2 259 | get_window().c = 3 260 | get_document().d = 4 261 | 262 | function inner () { 263 | const window = {} 264 | get_global().e = 4 265 | get_process().f = 5 266 | window.g = 6 267 | get_document().h = 7 268 | } 269 | ` 270 | ) 271 | }) 272 | 273 | test('multiple assignments separated by commas referencing deferred modules', () => { 274 | const source = dedent` 275 | let a, b, c, d, e, f; 276 | a = 1, b = 2, c = 3; 277 | d = require("d"), e = d.e, f = e.f; 278 | ` 279 | assert.equal( 280 | new FileRequireTransform({source, didFindRequire: () => true}).apply(), 281 | dedent` 282 | let a, b, c, d, e, f; 283 | a = 1, b = 2, c = 3; 284 | 285 | function get_d() { 286 | return d = d || require("d"); 287 | } 288 | 289 | function get_e() { 290 | return e = e || get_d().e; 291 | } 292 | 293 | function get_f() { 294 | return f = f || get_e().f; 295 | } 296 | ` 297 | ) 298 | }) 299 | 300 | test('require with destructuring assignment', () => { 301 | const source = dedent` 302 | const {a, b, c} = require('module').foo 303 | 304 | function main() { 305 | a.bar() 306 | } 307 | ` 308 | assert.equal( 309 | new FileRequireTransform({source, didFindRequire: () => true}).apply(), 310 | dedent` 311 | let {a, b, c} = {}; 312 | 313 | function get_a() { 314 | return a = a || require('module').foo.a; 315 | } 316 | 317 | function get_b() { 318 | return b = b || require('module').foo.b; 319 | } 320 | 321 | function get_c() { 322 | return c = c || require('module').foo.c; 323 | } 324 | 325 | function main() { 326 | get_a().bar() 327 | } 328 | ` 329 | ) 330 | }) 331 | 332 | test('JSON source', () => { 333 | const filePath = 'something.json' 334 | const source = '{"a": 1, "b": 2}' 335 | assert.equal( 336 | new FileRequireTransform({filePath, source, didFindRequire: () => false}).apply(), 337 | dedent` 338 | module.exports = {"a": 1, "b": 2} 339 | ` 340 | ) 341 | }) 342 | 343 | test('Object spread properties', () => { 344 | const source = 'let {a, b, ...rest} = {a: 1, b: 2, c: 3}' 345 | assert.equal( 346 | new FileRequireTransform({source, didFindRequire: () => false}).apply(), 347 | dedent` 348 | let {a, b, ...rest} = {a: 1, b: 2, c: 3} 349 | ` 350 | ) 351 | }) 352 | 353 | test('path resolution', () => { 354 | const baseDirPath = path.resolve(__dirname, '..', 'fixtures', 'module-1') 355 | const filePath = path.join(baseDirPath, 'dir', 'entry.js') 356 | const source = dedent` 357 | const a = require('a') 358 | const b = require('./subdir/b') 359 | const c = require('c') 360 | const fs = require('fs') 361 | 362 | function inner () { 363 | require('./subdir/b') 364 | require.resolve('a') 365 | require.resolve('d') 366 | require('d') 367 | } 368 | ` 369 | const requiredModules = [] 370 | assert.equal( 371 | new FileRequireTransform({baseDirPath, filePath, source, didFindRequire: (unresolvedPath, resolvedPath) => { 372 | requiredModules.push({unresolvedPath, resolvedPath}) 373 | return true 374 | }}).apply(), 375 | dedent` 376 | let a; 377 | 378 | function get_a() { 379 | return a = a || require("./node_modules/a/index.js"); 380 | } 381 | 382 | let b; 383 | 384 | function get_b() { 385 | return b = b || require("./dir/subdir/b.js"); 386 | } 387 | 388 | let c; 389 | 390 | function get_c() { 391 | return c = c || require('c'); 392 | } 393 | 394 | let fs; 395 | 396 | function get_fs() { 397 | return fs = fs || require('fs'); 398 | } 399 | 400 | function inner () { 401 | require("./dir/subdir/b.js") 402 | require.resolve("./node_modules/a/index.js") 403 | require.resolve('d') 404 | require('d') 405 | } 406 | ` 407 | ) 408 | assert.deepEqual(requiredModules, [ 409 | {unresolvedPath: 'a' , resolvedPath: path.join(baseDirPath, 'node_modules', 'a', 'index.js')}, 410 | {unresolvedPath: './subdir/b' , resolvedPath: path.join(baseDirPath, 'dir', 'subdir', 'b.js')}, 411 | {unresolvedPath: 'c' , resolvedPath: 'c'}, 412 | {unresolvedPath: './subdir/b' , resolvedPath: path.join(baseDirPath, 'dir', 'subdir', 'b.js')}, 413 | {unresolvedPath: 'd' , resolvedPath: 'd'}, 414 | ]) 415 | }) 416 | 417 | test('use reference directly', () => { 418 | const source = dedent` 419 | var pack = require('pack') 420 | 421 | const x = console.log(pack); 422 | if (condition) { 423 | pack 424 | } else { 425 | Object.keys(pack).forEach(function (prop) { 426 | exports[prop] = pack[prop] 427 | }) 428 | } 429 | ` 430 | assert.equal( 431 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'pack'}).apply(), 432 | dedent` 433 | var pack 434 | 435 | function get_pack() { 436 | return pack = pack || require('pack'); 437 | } 438 | 439 | let x; 440 | 441 | function get_x() { 442 | return x = x || get_console().log(get_pack()); 443 | } 444 | 445 | if (condition) { 446 | get_pack() 447 | } else { 448 | Object.keys(get_pack()).forEach(function (prop) { 449 | exports[prop] = get_pack()[prop] 450 | }) 451 | } 452 | ` 453 | ) 454 | }) 455 | test('assign to `module` or `exports`', () => { 456 | const source = dedent` 457 | var pack = require('pack') 458 | if (condition) { 459 | module.exports.pack = pack 460 | module.exports = pack 461 | exports.pack = pack 462 | exports = pack 463 | } 464 | ` 465 | assert.equal( 466 | new FileRequireTransform({source, didFindRequire: (mod) => mod === 'pack'}).apply(), 467 | dedent` 468 | var pack 469 | 470 | function get_pack() { 471 | return pack = pack || require('pack'); 472 | } 473 | 474 | if (condition) { 475 | module.exports.pack = get_pack() 476 | module.exports = get_pack() 477 | exports.pack = get_pack() 478 | exports = get_pack() 479 | } 480 | ` 481 | ) 482 | }) 483 | 484 | 485 | }) 486 | -------------------------------------------------------------------------------- /test/unit/generate-snapshot-script.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const fs = require('fs') 3 | const generateSnapshotScript = require('../../lib/generate-snapshot-script') 4 | const Module = require('module') 5 | const path = require('path') 6 | const temp = require('temp').track() 7 | const TransformCache = require('../../lib/transform-cache') 8 | const {SourceMapConsumer} = require('source-map') 9 | const {beforeEach, afterEach} = require("mocha") 10 | 11 | suite('generateSnapshotScript({baseDirPath, mainPath})', () => { 12 | let previousRequire 13 | 14 | beforeEach(() => { 15 | previousRequire = Module.prototype.require 16 | }) 17 | 18 | afterEach(() => { 19 | Module.prototype.require = previousRequire 20 | temp.cleanupSync() 21 | }) 22 | 23 | test('simple integration test', async () => { 24 | const baseDirPath = __dirname 25 | const mainPath = path.resolve(baseDirPath, '..', 'fixtures', 'module-1', 'index.js') 26 | const cachePath = temp.mkdirSync() 27 | 28 | { 29 | const cache = new TransformCache(cachePath, 'invalidation-key') 30 | await cache.loadOrCreate() 31 | const {snapshotScript, includedFilePaths} = await generateSnapshotScript(cache, { 32 | baseDirPath, 33 | mainPath, 34 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('b.js') 35 | }) 36 | eval(snapshotScript) 37 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 38 | assert(!global.moduleInitialized) 39 | assert.equal(global.initialize(), 'abx/ybAd') 40 | assert(global.moduleInitialized) 41 | 42 | assert.deepEqual(Array.from(includedFilePaths), [ 43 | path.resolve(baseDirPath, '../fixtures/module-1/index.js'), 44 | path.resolve(baseDirPath, '../fixtures/module-1/dir/a.js'), 45 | path.resolve(baseDirPath, '../fixtures/module-1/dir/c.json'), 46 | path.resolve(baseDirPath, '../fixtures/module-1/node_modules/a/index.js') 47 | ]) 48 | assert.equal((await cache._allKeys()).size, 9) 49 | await cache.dispose() 50 | } 51 | 52 | { 53 | const cache = new TransformCache(cachePath, 'invalidation-key') 54 | await cache.loadOrCreate() 55 | await cache.put({ 56 | filePath: mainPath, 57 | original: fs.readFileSync(mainPath, 'utf8'), 58 | transformed: 'global.initialize = () => "cached"', 59 | requires: [] 60 | }) 61 | const {snapshotScript, includedFilePaths} = await generateSnapshotScript(cache, { 62 | baseDirPath, 63 | mainPath, 64 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('b.js') 65 | }) 66 | eval(snapshotScript) 67 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 68 | assert.equal(global.initialize(), 'cached') 69 | 70 | assert.deepEqual(Array.from(includedFilePaths), [ 71 | path.resolve(baseDirPath, '../fixtures/module-1/index.js') 72 | ]) 73 | assert.equal((await cache._allKeys()).size, 3) 74 | await cache.dispose() 75 | } 76 | 77 | { 78 | const cache = new TransformCache(cachePath, 'a-new-invalidation-key') 79 | await cache.loadOrCreate() 80 | const {snapshotScript, includedFilePaths} = await generateSnapshotScript(cache, { 81 | baseDirPath, 82 | mainPath, 83 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('b.js') 84 | }) 85 | eval(snapshotScript) 86 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 87 | assert.equal(global.initialize(), 'abx/ybAd') 88 | 89 | assert.deepEqual(Array.from(includedFilePaths), [ 90 | path.resolve(baseDirPath, '../fixtures/module-1/index.js'), 91 | path.resolve(baseDirPath, '../fixtures/module-1/dir/a.js'), 92 | path.resolve(baseDirPath, '../fixtures/module-1/dir/c.json'), 93 | path.resolve(baseDirPath, '../fixtures/module-1/node_modules/a/index.js') 94 | ]) 95 | assert.equal((await cache._allKeys()).size, 9) 96 | await cache.dispose() 97 | } 98 | 99 | { 100 | const cache = new TransformCache(cachePath, 'a-new-invalidation-key') 101 | await cache.loadOrCreate() 102 | const {includedFilePaths} = await generateSnapshotScript(cache, { 103 | baseDirPath, 104 | mainPath, 105 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('b.js') 106 | }) 107 | 108 | assert.deepEqual(Array.from(includedFilePaths), [ 109 | path.resolve(baseDirPath, '../fixtures/module-1/index.js'), 110 | path.resolve(baseDirPath, '../fixtures/module-1/dir/a.js'), 111 | path.resolve(baseDirPath, '../fixtures/module-1/dir/c.json'), 112 | path.resolve(baseDirPath, '../fixtures/module-1/node_modules/a/index.js') 113 | ]) 114 | await cache.dispose() 115 | } 116 | }) 117 | 118 | test('cyclic requires', async () => { 119 | const baseDirPath = __dirname 120 | const mainPath = path.resolve(baseDirPath, '..', 'fixtures', 'cyclic-require', 'a.js') 121 | const cachePath = temp.mkdirSync() 122 | 123 | { 124 | const cache = new TransformCache(cachePath, 'invalidation-key') 125 | await cache.loadOrCreate() 126 | const {snapshotScript, includedFilePaths} = await generateSnapshotScript(cache, { 127 | baseDirPath, 128 | mainPath, 129 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('d.js') || requiredModulePath.endsWith('e.js') 130 | }) 131 | eval(snapshotScript) 132 | const cachedRequires = [] 133 | const uncachedRequires = [] 134 | Module.prototype.require = function (module) { 135 | if (module.includes('babel')) { 136 | return previousRequire(module) 137 | } else { 138 | const absoluteFilePath = Module._resolveFilename(module, this, false) 139 | const relativeFilePath = path.relative(mainPath, absoluteFilePath) 140 | let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] 141 | if (cachedModule) { 142 | cachedRequires.push(relativeFilePath) 143 | } else { 144 | uncachedRequires.push(relativeFilePath) 145 | cachedModule = {exports: Module._load(module, this, false)} 146 | snapshotResult.customRequire.cache[relativeFilePath] = cachedModule 147 | } 148 | 149 | return cachedModule.exports 150 | } 151 | } 152 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 153 | assert.deepEqual(global.cyclicRequire(), {a: 'a', b: 'b', d: 'd', e: 'e'}) 154 | assert.deepEqual(uncachedRequires, ['../d.js', '../e.js', '../d.js']) 155 | assert.deepEqual(cachedRequires, ['../e.js']) 156 | 157 | assert.deepEqual(Array.from(includedFilePaths), [ 158 | path.resolve(baseDirPath, '../fixtures/cyclic-require/a.js'), 159 | path.resolve(baseDirPath, '../fixtures/cyclic-require/b.js'), 160 | path.resolve(baseDirPath, '../fixtures/cyclic-require/c.js') 161 | ]) 162 | await cache.dispose() 163 | } 164 | }) 165 | 166 | test('auxiliary data', async () => { 167 | const cache = new TransformCache(temp.mkdirSync(), 'invalidation-key') 168 | await cache.loadOrCreate() 169 | const auxiliaryData = { 170 | a: 1, 171 | b: '2', 172 | c: [3, 4, 5], 173 | d: { 174 | e: 6, 175 | f: [7], 176 | g: null, 177 | h: '' 178 | } 179 | } 180 | const {snapshotScript} = await generateSnapshotScript(cache, { 181 | baseDirPath: __dirname, 182 | mainPath: path.resolve(__dirname, '..', 'fixtures', 'module-1', 'index.js'), 183 | auxiliaryData, 184 | shouldExcludeModule: () => false 185 | }) 186 | eval(snapshotScript) 187 | delete snapshotAuxiliaryData.snapshotSections 188 | assert.deepEqual(snapshotAuxiliaryData, auxiliaryData) 189 | await cache.dispose() 190 | }) 191 | 192 | test('process.platform', async () => { 193 | const baseDirPath = __dirname 194 | const mainPath = path.resolve(baseDirPath, '..', 'fixtures', 'module-2', 'index.js') 195 | const cache = new TransformCache(temp.mkdirSync(), 'invalidation-key') 196 | await cache.loadOrCreate() 197 | const {snapshotScript} = await generateSnapshotScript(cache, { 198 | baseDirPath, 199 | mainPath, 200 | shouldExcludeModule: () => false 201 | }) 202 | eval(snapshotScript) 203 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 204 | assert.deepEqual(global.module2, {platform: process.platform}) 205 | await cache.dispose() 206 | }) 207 | 208 | test('row translation', async () => { 209 | const baseDirPath = __dirname 210 | const mainPath = path.resolve(baseDirPath, '..', 'fixtures', 'module-1', 'index.js') 211 | const cache = new TransformCache(temp.mkdirSync(), 'invalidation-key') 212 | await cache.loadOrCreate() 213 | const {snapshotScript} = await generateSnapshotScript(cache, { 214 | baseDirPath, 215 | mainPath, 216 | shouldExcludeModule: ({requiredModulePath}) => requiredModulePath.endsWith('b.js') 217 | }) 218 | eval(snapshotScript) 219 | snapshotResult.setGlobals(global, process, {}, {}, console, require) 220 | 221 | assert.deepEqual(snapshotResult.translateSnapshotRow(10), {relativePath: '', row: 10}) 222 | assert.deepEqual(snapshotResult.translateSnapshotRow(276), {relativePath: '', row: 276}) 223 | assert.deepEqual(snapshotResult.translateSnapshotRow(277), {relativePath: '../fixtures/module-1/index.js', row: 0}) 224 | assert.deepEqual(snapshotResult.translateSnapshotRow(290), {relativePath: '../fixtures/module-1/index.js', row: 13}) 225 | assert.deepEqual(snapshotResult.translateSnapshotRow(291), {relativePath: '', row: 291}) 226 | assert.deepEqual(snapshotResult.translateSnapshotRow(298), {relativePath: '../fixtures/module-1/dir/a.js', row: 5}) 227 | assert.deepEqual(snapshotResult.translateSnapshotRow(309), {relativePath: '../fixtures/module-1/node_modules/a/index.js', row: 0}) 228 | assert.deepEqual(snapshotResult.translateSnapshotRow(311), {relativePath: '', row: 311}) 229 | 230 | await cache.dispose() 231 | }) 232 | }) 233 | --------------------------------------------------------------------------------