From e275570a4eeb160a8841fb63c7235fda835fa7a5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 17:20:49 +0100 Subject: [PATCH] Remove blob store and native module cache --- spec/file-system-blob-store-spec.coffee | 108 ------------------ spec/fixtures/native-cache/file-1.js | 1 - spec/fixtures/native-cache/file-2.js | 1 - spec/fixtures/native-cache/file-3.js | 1 - spec/fixtures/native-cache/file-4.js | 1 - spec/native-compile-cache-spec.coffee | 104 ------------------ src/file-system-blob-store.js | 133 ----------------------- src/initialize-application-window.coffee | 5 +- src/initialize-test-window.coffee | 3 +- src/native-compile-cache.js | 118 -------------------- static/index.js | 6 +- 11 files changed, 5 insertions(+), 476 deletions(-) delete mode 100644 spec/file-system-blob-store-spec.coffee delete mode 100644 spec/fixtures/native-cache/file-1.js delete mode 100644 spec/fixtures/native-cache/file-2.js delete mode 100644 spec/fixtures/native-cache/file-3.js delete mode 100644 spec/fixtures/native-cache/file-4.js delete mode 100644 spec/native-compile-cache-spec.coffee delete mode 100644 src/file-system-blob-store.js delete mode 100644 src/native-compile-cache.js diff --git a/spec/file-system-blob-store-spec.coffee b/spec/file-system-blob-store-spec.coffee deleted file mode 100644 index a2ed39014..000000000 --- a/spec/file-system-blob-store-spec.coffee +++ /dev/null @@ -1,108 +0,0 @@ -temp = require('temp').track() -path = require 'path' -fs = require 'fs-plus' -FileSystemBlobStore = require '../src/file-system-blob-store' - -describe "FileSystemBlobStore", -> - [storageDirectory, blobStore] = [] - - beforeEach -> - storageDirectory = temp.path('atom-spec-filesystemblobstore') - blobStore = FileSystemBlobStore.load(storageDirectory) - - afterEach -> - fs.removeSync(storageDirectory) - - it "is empty when the file doesn't exist", -> - expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined() - expect(blobStore.get("bar", "invalidation-key-2")).toBeUndefined() - - it "allows to read and write buffers from/to memory without persisting them", -> - blobStore.set("foo", "invalidation-key-1", new Buffer("foo")) - blobStore.set("bar", "invalidation-key-2", new Buffer("bar")) - - expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo")) - expect(blobStore.get("bar", "invalidation-key-2")).toEqual(new Buffer("bar")) - - expect(blobStore.get("foo", "unexisting-key")).toBeUndefined() - expect(blobStore.get("bar", "unexisting-key")).toBeUndefined() - - it "persists buffers when saved and retrieves them on load, giving priority to in-memory ones", -> - blobStore.set("foo", "invalidation-key-1", new Buffer("foo")) - blobStore.set("bar", "invalidation-key-2", new Buffer("bar")) - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - - expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo")) - expect(blobStore.get("bar", "invalidation-key-2")).toEqual(new Buffer("bar")) - expect(blobStore.get("foo", "unexisting-key")).toBeUndefined() - expect(blobStore.get("bar", "unexisting-key")).toBeUndefined() - - blobStore.set("foo", "new-key", new Buffer("changed")) - - expect(blobStore.get("foo", "new-key")).toEqual(new Buffer("changed")) - expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined() - - it "persists both in-memory and previously stored buffers when saved", -> - blobStore.set("foo", "invalidation-key-1", new Buffer("foo")) - blobStore.set("bar", "invalidation-key-2", new Buffer("bar")) - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - blobStore.set("bar", "invalidation-key-3", new Buffer("changed")) - blobStore.set("qux", "invalidation-key-4", new Buffer("qux")) - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - - expect(blobStore.get("foo", "invalidation-key-1")).toEqual(new Buffer("foo")) - expect(blobStore.get("bar", "invalidation-key-3")).toEqual(new Buffer("changed")) - expect(blobStore.get("qux", "invalidation-key-4")).toEqual(new Buffer("qux")) - expect(blobStore.get("foo", "unexisting-key")).toBeUndefined() - expect(blobStore.get("bar", "invalidation-key-2")).toBeUndefined() - expect(blobStore.get("qux", "unexisting-key")).toBeUndefined() - - it "allows to delete keys from both memory and stored buffers", -> - blobStore.set("a", "invalidation-key-1", new Buffer("a")) - blobStore.set("b", "invalidation-key-2", new Buffer("b")) - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - - blobStore.set("b", "invalidation-key-3", new Buffer("b")) - blobStore.set("c", "invalidation-key-4", new Buffer("c")) - blobStore.delete("b") - blobStore.delete("c") - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - - expect(blobStore.get("a", "invalidation-key-1")).toEqual(new Buffer("a")) - expect(blobStore.get("b", "invalidation-key-2")).toBeUndefined() - expect(blobStore.get("b", "invalidation-key-3")).toBeUndefined() - expect(blobStore.get("c", "invalidation-key-4")).toBeUndefined() - - it "ignores errors when loading an invalid blob store", -> - blobStore.set("a", "invalidation-key-1", new Buffer("a")) - blobStore.set("b", "invalidation-key-2", new Buffer("b")) - blobStore.save() - - # Simulate corruption - fs.writeFileSync(path.join(storageDirectory, "MAP"), new Buffer([0])) - fs.writeFileSync(path.join(storageDirectory, "INVKEYS"), new Buffer([0])) - fs.writeFileSync(path.join(storageDirectory, "BLOB"), new Buffer([0])) - - blobStore = FileSystemBlobStore.load(storageDirectory) - - expect(blobStore.get("a", "invalidation-key-1")).toBeUndefined() - expect(blobStore.get("b", "invalidation-key-2")).toBeUndefined() - - blobStore.set("a", "invalidation-key-1", new Buffer("x")) - blobStore.set("b", "invalidation-key-2", new Buffer("y")) - blobStore.save() - - blobStore = FileSystemBlobStore.load(storageDirectory) - - expect(blobStore.get("a", "invalidation-key-1")).toEqual(new Buffer("x")) - expect(blobStore.get("b", "invalidation-key-2")).toEqual(new Buffer("y")) diff --git a/spec/fixtures/native-cache/file-1.js b/spec/fixtures/native-cache/file-1.js deleted file mode 100644 index ce195a18e..000000000 --- a/spec/fixtures/native-cache/file-1.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = function () { return 1; } diff --git a/spec/fixtures/native-cache/file-2.js b/spec/fixtures/native-cache/file-2.js deleted file mode 100644 index e0cdf1485..000000000 --- a/spec/fixtures/native-cache/file-2.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = function () { return 2; } diff --git a/spec/fixtures/native-cache/file-3.js b/spec/fixtures/native-cache/file-3.js deleted file mode 100644 index 36ca6e14a..000000000 --- a/spec/fixtures/native-cache/file-3.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = function () { return 3; } diff --git a/spec/fixtures/native-cache/file-4.js b/spec/fixtures/native-cache/file-4.js deleted file mode 100644 index 1b8fd4e15..000000000 --- a/spec/fixtures/native-cache/file-4.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = function () { return "file-4" } diff --git a/spec/native-compile-cache-spec.coffee b/spec/native-compile-cache-spec.coffee deleted file mode 100644 index 1531deaf9..000000000 --- a/spec/native-compile-cache-spec.coffee +++ /dev/null @@ -1,104 +0,0 @@ -fs = require 'fs' -path = require 'path' -Module = require 'module' - -describe "NativeCompileCache", -> - nativeCompileCache = require '../src/native-compile-cache' - [fakeCacheStore, cachedFiles] = [] - - beforeEach -> - cachedFiles = [] - fakeCacheStore = jasmine.createSpyObj("cache store", ["set", "get", "has", "delete"]) - fakeCacheStore.has.andCallFake (cacheKey, invalidationKey) -> - fakeCacheStore.get(cacheKey, invalidationKey)? - fakeCacheStore.get.andCallFake (cacheKey, invalidationKey) -> - for entry in cachedFiles by -1 - continue if entry.cacheKey isnt cacheKey - continue if entry.invalidationKey isnt invalidationKey - return entry.cacheBuffer - return - fakeCacheStore.set.andCallFake (cacheKey, invalidationKey, cacheBuffer) -> - cachedFiles.push({cacheKey, invalidationKey, cacheBuffer}) - - nativeCompileCache.setCacheStore(fakeCacheStore) - nativeCompileCache.setV8Version("a-v8-version") - nativeCompileCache.install() - - it "writes and reads from the cache storage when requiring files", -> - fn1 = require('./fixtures/native-cache/file-1') - fn2 = require('./fixtures/native-cache/file-2') - - expect(cachedFiles.length).toBe(2) - - expect(cachedFiles[0].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-1')) - expect(cachedFiles[0].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[0].cacheBuffer.length).toBeGreaterThan(0) - expect(fn1()).toBe(1) - - expect(cachedFiles[1].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-2')) - expect(cachedFiles[1].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[1].cacheBuffer.length).toBeGreaterThan(0) - expect(fn2()).toBe(2) - - delete Module._cache[require.resolve('./fixtures/native-cache/file-1')] - fn1 = require('./fixtures/native-cache/file-1') - expect(cachedFiles.length).toBe(2) - expect(fn1()).toBe(1) - - describe "when v8 version changes", -> - it "updates the cache of previously required files", -> - nativeCompileCache.setV8Version("version-1") - fn4 = require('./fixtures/native-cache/file-4') - - expect(cachedFiles.length).toBe(1) - expect(cachedFiles[0].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-4')) - expect(cachedFiles[0].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[0].cacheBuffer.length).toBeGreaterThan(0) - expect(fn4()).toBe("file-4") - - nativeCompileCache.setV8Version("version-2") - delete Module._cache[require.resolve('./fixtures/native-cache/file-4')] - fn4 = require('./fixtures/native-cache/file-4') - - expect(cachedFiles.length).toBe(2) - expect(cachedFiles[1].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-4')) - expect(cachedFiles[1].invalidationKey).not.toBe(cachedFiles[0].invalidationKey) - expect(cachedFiles[1].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[1].cacheBuffer.length).toBeGreaterThan(0) - - describe "when a previously required and cached file changes", -> - beforeEach -> - fs.writeFileSync path.resolve(__dirname + '/fixtures/native-cache/file-5'), """ - module.exports = function () { return "file-5" } - """ - - afterEach -> - fs.unlinkSync path.resolve(__dirname + '/fixtures/native-cache/file-5') - - it "removes it from the store and re-inserts it with the new cache", -> - fn5 = require('./fixtures/native-cache/file-5') - - expect(cachedFiles.length).toBe(1) - expect(cachedFiles[0].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-5')) - expect(cachedFiles[0].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[0].cacheBuffer.length).toBeGreaterThan(0) - expect(fn5()).toBe("file-5") - - delete Module._cache[require.resolve('./fixtures/native-cache/file-5')] - fs.appendFileSync(require.resolve('./fixtures/native-cache/file-5'), "\n\n") - fn5 = require('./fixtures/native-cache/file-5') - - expect(cachedFiles.length).toBe(2) - expect(cachedFiles[1].cacheKey).toBe(require.resolve('./fixtures/native-cache/file-5')) - expect(cachedFiles[1].invalidationKey).not.toBe(cachedFiles[0].invalidationKey) - expect(cachedFiles[1].cacheBuffer).toBeInstanceOf(Uint8Array) - expect(cachedFiles[1].cacheBuffer.length).toBeGreaterThan(0) - - it "deletes previously cached code when the cache is an invalid file", -> - fakeCacheStore.has.andReturn(true) - fakeCacheStore.get.andCallFake -> new Buffer("an invalid cache") - - fn3 = require('./fixtures/native-cache/file-3') - - expect(fakeCacheStore.delete).toHaveBeenCalledWith(require.resolve('./fixtures/native-cache/file-3')) - expect(fn3()).toBe(3) diff --git a/src/file-system-blob-store.js b/src/file-system-blob-store.js deleted file mode 100644 index 7bbbdcb14..000000000 --- a/src/file-system-blob-store.js +++ /dev/null @@ -1,133 +0,0 @@ -'use strict' - -const fs = require('fs-plus') -const path = require('path') - -module.exports = -class FileSystemBlobStore { - static load (directory) { - let instance = new FileSystemBlobStore(directory) - instance.load() - return instance - } - - constructor (directory) { - this.blobFilename = path.join(directory, 'BLOB') - this.blobMapFilename = path.join(directory, 'MAP') - this.invalidationKeysFilename = path.join(directory, 'INVKEYS') - this.lockFilename = path.join(directory, 'LOCK') - this.reset() - } - - reset () { - this.inMemoryBlobs = new Map() - this.invalidationKeys = {} - this.storedBlob = new Buffer(0) - this.storedBlobMap = {} - } - - load () { - if (!fs.existsSync(this.blobMapFilename)) { - return - } - if (!fs.existsSync(this.blobFilename)) { - return - } - if (!fs.existsSync(this.invalidationKeysFilename)) { - return - } - - try { - this.storedBlob = fs.readFileSync(this.blobFilename) - this.storedBlobMap = JSON.parse(fs.readFileSync(this.blobMapFilename)) - this.invalidationKeys = JSON.parse(fs.readFileSync(this.invalidationKeysFilename)) - } catch (e) { - this.reset() - } - } - - save () { - let dump = this.getDump() - let blobToStore = Buffer.concat(dump[0]) - let mapToStore = JSON.stringify(dump[1]) - let invalidationKeysToStore = JSON.stringify(this.invalidationKeys) - - let acquiredLock = false - try { - fs.writeFileSync(this.lockFilename, 'LOCK', {flag: 'wx'}) - acquiredLock = true - - fs.writeFileSync(this.blobFilename, blobToStore) - fs.writeFileSync(this.blobMapFilename, mapToStore) - fs.writeFileSync(this.invalidationKeysFilename, invalidationKeysToStore) - } catch (error) { - // Swallow the exception silently only if we fail to acquire the lock. - if (error.code !== 'EEXIST') { - throw error - } - } finally { - if (acquiredLock) { - fs.unlinkSync(this.lockFilename) - } - } - } - - has (key, invalidationKey) { - let containsKey = this.inMemoryBlobs.has(key) || this.storedBlobMap.hasOwnProperty(key) - let isValid = this.invalidationKeys[key] === invalidationKey - return containsKey && isValid - } - - get (key, invalidationKey) { - if (this.has(key, invalidationKey)) { - return this.getFromMemory(key) || this.getFromStorage(key) - } - } - - set (key, invalidationKey, buffer) { - this.invalidationKeys[key] = invalidationKey - return this.inMemoryBlobs.set(key, buffer) - } - - delete (key) { - this.inMemoryBlobs.delete(key) - delete this.storedBlobMap[key] - } - - getFromMemory (key) { - return this.inMemoryBlobs.get(key) - } - - getFromStorage (key) { - if (!this.storedBlobMap[key]) { - return - } - - return this.storedBlob.slice.apply(this.storedBlob, this.storedBlobMap[key]) - } - - getDump () { - let buffers = [] - let blobMap = {} - let currentBufferStart = 0 - - function dump (key, getBufferByKey) { - let buffer = getBufferByKey(key) - buffers.push(buffer) - blobMap[key] = [currentBufferStart, currentBufferStart + buffer.length] - currentBufferStart += buffer.length - } - - for (let key of this.inMemoryBlobs.keys()) { - dump(key, this.getFromMemory.bind(this)) - } - - for (let key of Object.keys(this.storedBlobMap)) { - if (!blobMap[key]) { - dump(key, this.getFromStorage.bind(this)) - } - } - - return [buffers, blobMap] - } -} diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 13562fae2..b855936e0 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -3,7 +3,6 @@ ApplicationDelegate = require './application-delegate' Clipboard = require './clipboard' TextEditor = require './text-editor' TextEditorComponent = require './text-editor-component' -FileSystemBlobStore = require './file-system-blob-store' CompileCache = require './compile-cache' ModuleCache = require './module-cache' @@ -55,7 +54,7 @@ require('whitespace') require('wrap-guide') # Like sands through the hourglass, so are the days of our lives. -module.exports = ({blobStore}) -> +module.exports = -> {updateProcessEnv} = require('./update-process-env') path = require 'path' require './window' @@ -76,7 +75,7 @@ module.exports = ({blobStore}) -> TextEditor.setClipboard(clipboard) window.atom = new AtomEnvironment({ - window, document, clipboard, blobStore, + window, document, clipboard, applicationDelegate: new ApplicationDelegate, configDirPath: process.env.ATOM_HOME, enablePersistence: true, diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 794db3174..3649fea94 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -5,7 +5,7 @@ cloneObject = (object) -> clone[key] = value for key, value of object clone -module.exports = ({blobStore}) -> +module.exports = -> startCrashReporter = require('./crash-reporter-start') {remote} = require 'electron' @@ -77,7 +77,6 @@ module.exports = ({blobStore}) -> buildAtomEnvironment = (params) -> params = cloneObject(params) params.clipboard = clipboard unless params.hasOwnProperty("clipboard") - params.blobStore = blobStore unless params.hasOwnProperty("blobStore") params.onlyLoadBaseStyleSheets = true unless params.hasOwnProperty("onlyLoadBaseStyleSheets") new AtomEnvironment(params) diff --git a/src/native-compile-cache.js b/src/native-compile-cache.js deleted file mode 100644 index e4e7fc146..000000000 --- a/src/native-compile-cache.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict' - -const Module = require('module') -const path = require('path') -const cachedVm = require('cached-run-in-this-context') -const crypto = require('crypto') - -function computeHash (contents) { - return crypto.createHash('sha1').update(contents, 'utf8').digest('hex') -} - -class NativeCompileCache { - constructor () { - this.cacheStore = null - this.previousModuleCompile = null - } - - setCacheStore (store) { - this.cacheStore = store - } - - setV8Version (v8Version) { - this.v8Version = v8Version.toString() - } - - install () { - this.savePreviousModuleCompile() - this.overrideModuleCompile() - } - - uninstall () { - this.restorePreviousModuleCompile() - } - - savePreviousModuleCompile () { - this.previousModuleCompile = Module.prototype._compile - } - - overrideModuleCompile () { - let self = this - let resolvedArgv = null - // Here we override Node's module.js - // (https://github.com/atom/node/blob/atom/lib/module.js#L378), changing - // only the bits that affect compilation in order to use the cached one. - Module.prototype._compile = function (content, filename) { - let moduleSelf = this - // remove shebang - content = content.replace(/^#!.*/, '') - function require (path) { - return moduleSelf.require(path) - } - require.resolve = function (request) { - return Module._resolveFilename(request, moduleSelf) - } - require.main = process.mainModule - - // Enable support to add extra extension types - require.extensions = Module._extensions - require.cache = Module._cache - - let dirname = path.dirname(filename) - - // create wrapper function - let wrapper = Module.wrap(content) - - let cacheKey = filename - let invalidationKey = computeHash(wrapper + self.v8Version) - let compiledWrapper = null - if (self.cacheStore.has(cacheKey, invalidationKey)) { - let buffer = self.cacheStore.get(cacheKey, invalidationKey) - let compilationResult = cachedVm.runInThisContextCached(wrapper, filename, buffer) - compiledWrapper = compilationResult.result - if (compilationResult.wasRejected) { - self.cacheStore.delete(cacheKey) - } - } else { - let compilationResult - try { - compilationResult = cachedVm.runInThisContext(wrapper, filename) - } catch (err) { - console.error(`Error running script ${filename}`) - throw err - } - if (compilationResult.cacheBuffer) { - self.cacheStore.set(cacheKey, invalidationKey, compilationResult.cacheBuffer) - } - compiledWrapper = compilationResult.result - } - if (global.v8debug) { - if (!resolvedArgv) { - // we enter the repl if we're not given a filename argument. - if (process.argv[1]) { - resolvedArgv = Module._resolveFilename(process.argv[1], null) - } else { - resolvedArgv = 'repl' - } - } - - // Set breakpoint on module start - if (filename === resolvedArgv) { - // Installing this dummy debug event listener tells V8 to start - // the debugger. Without it, the setBreakPoint() fails with an - // 'illegal access' error. - global.v8debug.Debug.setListener(function () {}) - global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0) - } - } - let args = [moduleSelf.exports, require, moduleSelf, filename, dirname, process, global] - return compiledWrapper.apply(moduleSelf.exports, args) - } - } - - restorePreviousModuleCompile () { - Module.prototype._compile = this.previousModuleCompile - } -} - -module.exports = new NativeCompileCache() diff --git a/static/index.js b/static/index.js index c79055200..0da1730f8 100644 --- a/static/index.js +++ b/static/index.js @@ -5,8 +5,6 @@ const Module = require('module') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname - let blobStore = null - let devMode = false let useSnapshot = false window.onload = function () { @@ -21,7 +19,7 @@ process.resourcesPath = path.normalize(process.resourcesPath) setupAtomHome() - devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep) + const devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep) useSnapshot = !devMode && typeof snapshotResult !== 'undefined' if (devMode) { @@ -91,7 +89,7 @@ const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) const initialize = useSnapshot ? snapshotResult.customRequire(initScriptPath) : require(initScriptPath) - return initialize({blobStore: blobStore}).then(function () { + return initialize().then(function () { electron.ipcRenderer.send('window-command', 'window:loaded') }) }