From 1d16d687bb09589ec2ae54ec73af1740fd4003eb Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 11 Nov 2016 14:33:38 +0100 Subject: [PATCH 01/50] Start on generating a startup snapshot script via electron-link --- script/build | 2 ++ script/lib/generate-startup-snapshot.js | 48 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 script/lib/generate-startup-snapshot.js diff --git a/script/build b/script/build index 680666b05..3a5a545d4 100755 --- a/script/build +++ b/script/build @@ -35,6 +35,7 @@ const dumpSymbols = require('./lib/dump-symbols') const generateAPIDocs = require('./lib/generate-api-docs') const generateMetadata = require('./lib/generate-metadata') const generateModuleCache = require('./lib/generate-module-cache') +const generateStartupSnapshot = require('./lib/generate-startup-snapshot') const installApplication = require('./lib/install-application') const packageApplication = require('./lib/package-application') const prebuildLessCache = require('./lib/prebuild-less-cache') @@ -57,6 +58,7 @@ transpilePegJsPaths() generateModuleCache() prebuildLessCache() generateMetadata() +generateStartupSnapshot() generateAPIDocs() downloadChromedriver() dumpSymbols() diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js new file mode 100644 index 000000000..63335c90a --- /dev/null +++ b/script/lib/generate-startup-snapshot.js @@ -0,0 +1,48 @@ +const fs = require('fs') +const path = require('path') +const electronLink = require('electron-link') +const CONFIG = require('../config') + +module.exports = function () { + const snapshotScriptPath = path.join(CONFIG.buildOutputPath, 'startup.js') + console.log(`Generating snapshot script at "${snapshotScriptPath}"`) + const coreModules = new Set([ + 'path', 'electron', 'module', 'fs', 'child_process', 'crypto', 'url', + 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', + 'http', 'https' + ]) + const snapshotScriptContent = electronLink({ + baseDirPath: CONFIG.intermediateAppPath, + mainPath: path.join(CONFIG.intermediateAppPath, 'src', 'initialize-application-window.js'), + shouldExcludeModule: (modulePath) => { + const relativePath = path.relative(CONFIG.intermediateAppPath, modulePath) + return ( + modulePath.endsWith('.node') || modulePath === 'buffer-offset-index' || + coreModules.has(modulePath) || + (relativePath.startsWith('src' + path.sep) && relativePath.endsWith('-element.js')) || + relativePath == path.join('exports', 'atom.js') || + relativePath == path.join('src', 'config-schema.js') || + relativePath == path.join('src', 'electron-shims.js') || + relativePath == path.join('src', 'module-cache.js') || + relativePath == path.join('src', 'safe-clipboard.js') || + relativePath == path.join('node_modules', 'atom-keymap', 'lib', 'command-event.js') || + relativePath == path.join('node_modules', 'babel-core', 'index.js') || + relativePath == path.join('node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('node_modules', 'git-utils', 'lib', 'git.js') || + relativePath == path.join('node_modules', 'less', 'lib', 'less', 'fs.js') || + relativePath == path.join('node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || + relativePath == path.join('node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || + relativePath == path.join('node_modules', 'mime', 'mime.js') || + relativePath == path.join('node_modules', 'oniguruma', 'lib', 'oniguruma.js') || + relativePath == path.join('node_modules', 'pathwatcher', 'lib', 'main.js') || + relativePath == path.join('node_modules', 'request', 'request.js') || + relativePath == path.join('node_modules', 'resolve', 'index.js') || + relativePath == path.join('node_modules', 'resolve', 'lib', 'core.js') || + relativePath == path.join('node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') + ) + } + }) + fs.writeFileSync(snapshotScriptPath, snapshotScriptContent) +} From 3514adfe4ed8dbce812aae3832ee9f453817cd22 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 11 Nov 2016 14:34:00 +0100 Subject: [PATCH 02/50] Import Point and Range from text-buffer --- src/text-editor-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-editor-registry.js b/src/text-editor-registry.js index b29a3887c..2c66ae90e 100644 --- a/src/text-editor-registry.js +++ b/src/text-editor-registry.js @@ -1,7 +1,7 @@ /** @babel */ import {Emitter, Disposable, CompositeDisposable} from 'event-kit' -import {Point, Range} from 'atom' +import {Point, Range} from 'text-buffer' import TextEditor from './text-editor' import ScopeDescriptor from './scope-descriptor' From 6ccdc421cbb6b167f6cc50cf23a5f5a3645a812a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 11 Nov 2016 15:37:44 +0100 Subject: [PATCH 03/50] Use a different entry script to generate the startup snapshot --- script/lib/generate-startup-snapshot.js | 2 +- src/initialize-snapshot.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/initialize-snapshot.js diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 63335c90a..86d1585c1 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -13,7 +13,7 @@ module.exports = function () { ]) const snapshotScriptContent = electronLink({ baseDirPath: CONFIG.intermediateAppPath, - mainPath: path.join(CONFIG.intermediateAppPath, 'src', 'initialize-application-window.js'), + mainPath: path.join(CONFIG.intermediateAppPath, 'src', 'initialize-snapshot.js'), shouldExcludeModule: (modulePath) => { const relativePath = path.relative(CONFIG.intermediateAppPath, modulePath) return ( diff --git a/src/initialize-snapshot.js b/src/initialize-snapshot.js new file mode 100644 index 000000000..47bd5afa0 --- /dev/null +++ b/src/initialize-snapshot.js @@ -0,0 +1,5 @@ +require('./update-process-env') +require('./window') +require('./atom-environment') +require('./application-delegate') +require('./clipboard') From 77b8089e3abefc245f0ce83fc8da21c8341d9035 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 11 Nov 2016 16:39:58 +0100 Subject: [PATCH 04/50] Use the snapshot result to require core modules --- script/build | 2 +- script/lib/generate-startup-snapshot.js | 54 ++++++------ src/atom-environment.coffee | 8 +- src/initialize-application-window.coffee | 16 ++-- src/main-process/main.js | 4 + src/task.coffee | 4 +- static/index.js | 102 ++++++----------------- 7 files changed, 70 insertions(+), 120 deletions(-) diff --git a/script/build b/script/build index 3a5a545d4..b4bfee6f9 100755 --- a/script/build +++ b/script/build @@ -50,6 +50,7 @@ process.on('unhandledRejection', function (e) { }) cleanOutputDirectory() +downloadChromedriver() copyAssets() transpileBabelPaths() transpileCoffeeScriptPaths() @@ -60,7 +61,6 @@ prebuildLessCache() generateMetadata() generateStartupSnapshot() generateAPIDocs() -downloadChromedriver() dumpSymbols() .then(packageApplication) .then(packagedAppPath => { diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 86d1585c1..f8a0b5e4d 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -11,36 +11,40 @@ module.exports = function () { 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', 'http', 'https' ]) + const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') const snapshotScriptContent = electronLink({ - baseDirPath: CONFIG.intermediateAppPath, - mainPath: path.join(CONFIG.intermediateAppPath, 'src', 'initialize-snapshot.js'), + baseDirPath, + mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'), shouldExcludeModule: (modulePath) => { - const relativePath = path.relative(CONFIG.intermediateAppPath, modulePath) + const relativePath = path.relative(baseDirPath, modulePath) return ( modulePath.endsWith('.node') || modulePath === 'buffer-offset-index' || coreModules.has(modulePath) || - (relativePath.startsWith('src' + path.sep) && relativePath.endsWith('-element.js')) || - relativePath == path.join('exports', 'atom.js') || - relativePath == path.join('src', 'config-schema.js') || - relativePath == path.join('src', 'electron-shims.js') || - relativePath == path.join('src', 'module-cache.js') || - relativePath == path.join('src', 'safe-clipboard.js') || - relativePath == path.join('node_modules', 'atom-keymap', 'lib', 'command-event.js') || - relativePath == path.join('node_modules', 'babel-core', 'index.js') || - relativePath == path.join('node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || - relativePath == path.join('node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || - relativePath == path.join('node_modules', 'fs-plus', 'lib', 'fs-plus.js') || - relativePath == path.join('node_modules', 'git-utils', 'lib', 'git.js') || - relativePath == path.join('node_modules', 'less', 'lib', 'less', 'fs.js') || - relativePath == path.join('node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || - relativePath == path.join('node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || - relativePath == path.join('node_modules', 'mime', 'mime.js') || - relativePath == path.join('node_modules', 'oniguruma', 'lib', 'oniguruma.js') || - relativePath == path.join('node_modules', 'pathwatcher', 'lib', 'main.js') || - relativePath == path.join('node_modules', 'request', 'request.js') || - relativePath == path.join('node_modules', 'resolve', 'index.js') || - relativePath == path.join('node_modules', 'resolve', 'lib', 'core.js') || - relativePath == path.join('node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') + (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) || + relativePath == path.join('..', 'exports', 'atom.js') || + relativePath == path.join('..', 'src', 'config-schema.js') || + relativePath == path.join('..', 'src', 'electron-shims.js') || + relativePath == path.join('..', 'src', 'module-cache.js') || + relativePath == path.join('..', 'src', 'safe-clipboard.js') || + relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || + relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'helpers.js') || + relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || + relativePath == path.join('..', 'node_modules', 'clear-cut', 'index.js') || + relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('..', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || + relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'index.js') || + relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || + relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || + relativePath == path.join('..', 'node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || + relativePath == path.join('..', 'node_modules', 'mime', 'mime.js') || + relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') || + relativePath == path.join('..', 'node_modules', 'pathwatcher', 'lib', 'main.js') || + relativePath == path.join('..', 'node_modules', 'request', 'request.js') || + relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || + relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || + relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') ) } }) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 32cfa331d..09c85afca 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -132,7 +132,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params + {@applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @unloaded = false @loadTime = null @@ -738,7 +738,6 @@ class AtomEnvironment extends Model @storeWindowBackground() @packages.deactivatePackages() - @saveBlobStoreSync() @unloaded = true openInitialEmptyEditorIfNecessary: -> @@ -867,11 +866,6 @@ class AtomEnvironment extends Model showSaveDialogSync: (options={}) -> @applicationDelegate.showSaveDialog(options) - saveBlobStoreSync: -> - return unless @enablePersistence - - @blobStore.save() - saveState: (options) -> new Promise (resolve, reject) => if @enablePersistence and @project diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 7d3a23db7..38133e414 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -1,5 +1,10 @@ +AtomEnvironment = require './atom-environment' +ApplicationDelegate = require './application-delegate' +Clipboard = require './clipboard' +TextEditor = require './text-editor' + # 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' @@ -16,23 +21,18 @@ module.exports = ({blobStore}) -> # Make React faster process.env.NODE_ENV ?= 'production' unless devMode - AtomEnvironment = require './atom-environment' - ApplicationDelegate = require './application-delegate' - Clipboard = require './clipboard' - TextEditor = require './text-editor' - clipboard = new Clipboard TextEditor.setClipboard(clipboard) window.atom = new AtomEnvironment({ - window, document, clipboard, blobStore, + window, document, clipboard, applicationDelegate: new ApplicationDelegate, configDirPath: process.env.ATOM_HOME, enablePersistence: true, env: process.env }) - atom.startEditorWindow().then -> + window.atom.startEditorWindow().then -> # Workaround for focus getting cleared upon window creation windowFocused = -> window.removeEventListener('focus', windowFocused) diff --git a/src/main-process/main.js b/src/main-process/main.js index 7ccd1a6c3..e77d1930f 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -1,3 +1,7 @@ +if (typeof snapshotResult !== 'undefined') { + snapshotResult.setGlobals(global, process, {}, require) +} + const startTime = Date.now() const electron = require('electron') diff --git a/src/task.coffee b/src/task.coffee index fc8c5bd6b..8555b6554 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -70,7 +70,9 @@ class Task compileCachePath = require('./compile-cache').getCacheDirectory() taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');" bootstrap = """ - #{compileCacheRequire}.setCacheDirectory('#{compileCachePath}'); + snapshotResult.setGlobals(global, process, global, require) + CompileCache = snapshotResult.customRequire('../src/compile-cache.js') + CompileCache.setCacheDirectory('#{compileCachePath}'); #{taskBootstrapRequire} """ bootstrap = bootstrap.replace(/\\/g, "\\\\") diff --git a/static/index.js b/static/index.js index b76477e03..0f900d213 100644 --- a/static/index.js +++ b/static/index.js @@ -1,92 +1,41 @@ (function () { - var path = require('path') - var FileSystemBlobStore = require('../src/file-system-blob-store') - var NativeCompileCache = require('../src/native-compile-cache') - - var loadSettings = null - var loadSettingsError = null - var blobStore = null - - window.onload = function () { - try { - var startTime = Date.now() + let loadSettings + const Module = require('module') + const Path = require('path') + const vm = require('vm') + if (typeof snapshotResult !== 'undefined') { + window.onload = function () { + process.resourcesPath = Path.normalize(process.resourcesPath) process.on('unhandledRejection', function (error, promise) { console.error('Unhandled promise rejection %o with error: %o', promise, error) }) - blobStore = FileSystemBlobStore.load( - path.join(process.env.ATOM_HOME, 'blob-store/') - ) - NativeCompileCache.setCacheStore(blobStore) - NativeCompileCache.setV8Version(process.versions.v8) - NativeCompileCache.install() + parseLoadSettings() + setupAtomHome() + require('../src/crash-reporter-start')({_version: loadSettings.appVersion}) - // Normalize to make sure drive letter case is consistent on Windows - process.resourcesPath = path.normalize(process.resourcesPath) - - if (loadSettingsError) { - throw loadSettingsError + const entryPointDirPath = __dirname + Module.prototype.require = function (path) { + const absoluteFilePath = Module._resolveFilename(path, this, false) + const relativeFilePath = Path.relative(entryPointDirPath, absoluteFilePath) + const cachedModule = snapshotResult.customRequire.cache[relativeFilePath] + return cachedModule ? cachedModule : Module._load(path, this, false) } - var devMode = loadSettings.devMode || !loadSettings.resourcePath.startsWith(process.resourcesPath + path.sep) + snapshotResult.setGlobals(global, process, window, require) - if (devMode) { - setupDeprecatedPackages() - } + const CSON = snapshotResult.customRequire("../node_modules/season/lib/cson.js") + CSON.setCacheDir(Path.join(process.env.ATOM_HOME, 'compile-cache', 'cson')) - if (loadSettings.profileStartup) { - profileStartup(loadSettings, Date.now() - startTime) - } else { - setupWindow(loadSettings) - setLoadTime(Date.now() - startTime) - } - } catch (error) { - handleSetupError(error) + const CompileCache = snapshotResult.customRequire('../src/compile-cache.js') + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) + + const initialize = snapshotResult.customRequire('../src/initialize-application-window.js') + initialize() } } - function setLoadTime (loadTime) { - if (global.atom) { - global.atom.loadTime = loadTime - } - } - - function handleSetupError (error) { - var currentWindow = require('electron').remote.getCurrentWindow() - currentWindow.setSize(800, 600) - currentWindow.center() - currentWindow.show() - currentWindow.openDevTools() - console.error(error.stack || error) - } - - function setupWindow (loadSettings) { - var CompileCache = require('../src/compile-cache') - CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - - var ModuleCache = require('../src/module-cache') - ModuleCache.register(loadSettings) - ModuleCache.add(loadSettings.resourcePath) - - // By explicitly passing the app version here, we could save the call - // of "require('remote').require('app').getVersion()". - var startCrashReporter = require('../src/crash-reporter-start') - startCrashReporter({_version: loadSettings.appVersion}) - - setupVmCompatibility() - setupCsonCache(CompileCache.getCacheDirectory()) - - var initialize = require(loadSettings.windowInitializationScript) - return initialize({blobStore: blobStore}).then(function () { - require('electron').ipcRenderer.send('window-command', 'window:loaded') - }) - } - - function setupCsonCache (cacheDir) { - require('season').setCacheDir(path.join(cacheDir, 'cson')) - } - function setupVmCompatibility () { var vm = require('vm') if (!vm.Script.createContext) { @@ -149,7 +98,4 @@ process.env.ATOM_HOME = loadSettings.atomHome } } - - parseLoadSettings() - setupAtomHome() })() From 72b017b01a6d83a8148dabc64a036560a088bf13 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 15 Nov 2016 18:03:00 +0100 Subject: [PATCH 05/50] WIP: Start on requiring packages --- script/lib/generate-startup-snapshot.js | 13 +++- src/initialize-application-window.coffee | 78 ++++++++++++++++++++++++ src/lines-component.coffee | 40 ++++++------ static/index.js | 2 +- 4 files changed, 110 insertions(+), 23 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index f8a0b5e4d..d7da7d8de 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -9,7 +9,7 @@ module.exports = function () { const coreModules = new Set([ 'path', 'electron', 'module', 'fs', 'child_process', 'crypto', 'url', 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', - 'http', 'https' + 'http', 'https', 'shell', 'querystring', 'zlib', 'stream', 'WNdb', 'lapack' ]) const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') const snapshotScriptContent = electronLink({ @@ -33,7 +33,10 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || + relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') || + relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || @@ -44,7 +47,13 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'request', 'request.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || - relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || + relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || + relativePath == path.join('..', 'node_modules', 'styleguide', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') || + relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') || + relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || + relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') ) } }) diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 38133e414..3254e5ca5 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -2,6 +2,84 @@ AtomEnvironment = require './atom-environment' ApplicationDelegate = require './application-delegate' Clipboard = require './clipboard' TextEditor = require './text-editor' +TextEditorComponent = require './text-editor-component' +require('about') +require('archive-view') +require('autocomplete-atom-api') +require('autocomplete-css') +require('autocomplete-html') +require('autocomplete-plus') +require('autocomplete-snippets') +require('autoflow') +require('autosave') +require('background-tips') +require('bookmarks') +require('bracket-matcher') +require('command-palette') +require('deprecation-cop') +require('dev-live-reload') +require('encoding-selector') +require('exception-reporting') +require('find-and-replace') +require('fuzzy-finder') +require('git-diff') +require('go-to-line') +require('grammar-selector') +require('image-view') +require('incompatible-packages') +require('keybinding-resolver') +require('line-ending-selector') +require('link') +require('markdown-preview') +require('metrics') +require('notifications') +require('open-on-github') +require('package-generator') +require('settings-view') +require('snippets') +require('spell-check') +# require('status-bar') +require('styleguide') +require('symbols-view') +require('tabs') +require('timecop') +require('tree-view') +# require('update-package-dependencies') +require('welcome') +require('whitespace') +# require('wrap-guide') +# require('language-c') +# require('language-clojure') +# require('language-coffee-script') +# require('language-csharp') +# require('language-css') +# require('language-gfm') +# require('language-git') +# require('language-go') +# require('language-html') +# require('language-hyperlink') +# require('language-java') +# require('language-javascript') +# require('language-json') +# require('language-less') +# require('language-make') +# require('language-mustache') +# require('language-objective-c') +# require('language-perl') +# require('language-php') +# require('language-property-list') +# require('language-python') +# require('language-ruby') +# require('language-ruby-on-rails') +# require('language-sass') +# require('language-shellscript') +# require('language-source') +# require('language-sql') +# require('language-text') +# require('language-todo') +# require('language-toml') +# require('language-xml') +# require('language-yaml') # Like sands through the hourglass, so are the days of our lives. module.exports = -> diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 6c9271179..02d396021 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -2,24 +2,24 @@ CursorsComponent = require './cursors-component' LinesTileComponent = require './lines-tile-component' TiledComponent = require './tiled-component' -DummyLineNode = document.createElement('div') -DummyLineNode.className = 'line' -DummyLineNode.style.position = 'absolute' -DummyLineNode.style.visibility = 'hidden' -DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.appendChild(document.createElement('span')) -DummyLineNode.children[0].textContent = 'x' -DummyLineNode.children[1].textContent = '我' -DummyLineNode.children[2].textContent = 'ハ' -DummyLineNode.children[3].textContent = '세' - module.exports = class LinesComponent extends TiledComponent placeholderTextDiv: null constructor: ({@views, @presenter, @domElementPool, @assert}) -> + @DummyLineNode = document.createElement('div') + @DummyLineNode.className = 'line' + @DummyLineNode.style.position = 'absolute' + @DummyLineNode.style.visibility = 'hidden' + @DummyLineNode.appendChild(document.createElement('span')) + @DummyLineNode.appendChild(document.createElement('span')) + @DummyLineNode.appendChild(document.createElement('span')) + @DummyLineNode.appendChild(document.createElement('span')) + @DummyLineNode.children[0].textContent = 'x' + @DummyLineNode.children[1].textContent = '我' + @DummyLineNode.children[2].textContent = 'ハ' + @DummyLineNode.children[3].textContent = '세' + @domNode = document.createElement('div') @domNode.classList.add('lines') @tilesNode = document.createElement("div") @@ -78,15 +78,15 @@ class LinesComponent extends TiledComponent getTilesNode: -> @tilesNode measureLineHeightAndDefaultCharWidth: -> - @domNode.appendChild(DummyLineNode) + @domNode.appendChild(@DummyLineNode) - lineHeightInPixels = DummyLineNode.getBoundingClientRect().height - defaultCharWidth = DummyLineNode.children[0].getBoundingClientRect().width - doubleWidthCharWidth = DummyLineNode.children[1].getBoundingClientRect().width - halfWidthCharWidth = DummyLineNode.children[2].getBoundingClientRect().width - koreanCharWidth = DummyLineNode.children[3].getBoundingClientRect().width + lineHeightInPixels = @DummyLineNode.getBoundingClientRect().height + defaultCharWidth = @DummyLineNode.children[0].getBoundingClientRect().width + doubleWidthCharWidth = @DummyLineNode.children[1].getBoundingClientRect().width + halfWidthCharWidth = @DummyLineNode.children[2].getBoundingClientRect().width + koreanCharWidth = @DummyLineNode.children[3].getBoundingClientRect().width - @domNode.removeChild(DummyLineNode) + @domNode.removeChild(@DummyLineNode) @presenter.setLineHeight(lineHeightInPixels) @presenter.setBaseCharacterWidth(defaultCharWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) diff --git a/static/index.js b/static/index.js index 0f900d213..889b7f98b 100644 --- a/static/index.js +++ b/static/index.js @@ -23,7 +23,7 @@ return cachedModule ? cachedModule : Module._load(path, this, false) } - snapshotResult.setGlobals(global, process, window, require) + snapshotResult.setGlobals(global, process, window, document, require) const CSON = snapshotResult.customRequire("../node_modules/season/lib/cson.js") CSON.setCacheDir(Path.join(process.env.ATOM_HOME, 'compile-cache', 'cson')) From e624f24b6d8e314938216503aac35120e6f6a411 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 23 Feb 2017 17:04:43 +0100 Subject: [PATCH 06/50] WIP --- script/build | 99 ++++++++++++------------ script/lib/generate-startup-snapshot.js | 13 +++- script/lib/transpile-babel-paths.js | 1 + src/coffee-script.js | 3 +- src/initialize-application-window.coffee | 38 +-------- static/babelrc.json | 1 - 6 files changed, 66 insertions(+), 89 deletions(-) diff --git a/script/build b/script/build index cfcbc4a93..9afc5b378 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -require('./bootstrap') +// require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') @@ -51,58 +51,57 @@ process.on('unhandledRejection', function (e) { checkChromedriverVersion() cleanOutputDirectory() -downloadChromedriver() copyAssets() transpileBabelPaths() transpileCoffeeScriptPaths() transpileCsonPaths() transpilePegJsPaths() -generateModuleCache() -prebuildLessCache() -generateMetadata() +// generateModuleCache() +// prebuildLessCache() +// generateMetadata() generateStartupSnapshot() -generateAPIDocs() -dumpSymbols() - .then(packageApplication) - .then(packagedAppPath => { - if (process.platform === 'darwin') { - if (argv.codeSign) { - codeSignOnMac(packagedAppPath) - } else { - console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) - } - } else if (process.platform === 'win32') { - if (argv.createWindowsInstaller) { - return createWindowsInstaller(packagedAppPath, argv.codeSign).then(() => packagedAppPath) - } - else { - console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer. Code-signing was skipped too.'.gray) - } - } else if (process.platform === 'linux') { - if (argv.createDebianPackage) { - createDebianPackage(packagedAppPath) - } else { - console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) - } - - if (argv.createRpmPackage) { - createRpmPackage(packagedAppPath) - } else { - console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) - } - } - - return Promise.resolve(packagedAppPath) - }).then(packagedAppPath => { - if (argv.compressArtifacts) { - compressArtifacts(packagedAppPath) - } else { - console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) - } - - if (argv.install) { - installApplication(packagedAppPath) - } else { - console.log('Skipping installation. Specify the --install option to install Atom'.gray) - } - }) +// generateAPIDocs() +// dumpSymbols() +// .then(packageApplication) +// .then(packagedAppPath => { +// if (process.platform === 'darwin') { +// if (argv.codeSign) { +// codeSignOnMac(packagedAppPath) +// } else { +// console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) +// } +// } else if (process.platform === 'win32') { +// if (argv.createWindowsInstaller) { +// return createWindowsInstaller(packagedAppPath, argv.codeSign).then(() => packagedAppPath) +// } +// else { +// console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer. Code-signing was skipped too.'.gray) +// } +// } else if (process.platform === 'linux') { +// if (argv.createDebianPackage) { +// createDebianPackage(packagedAppPath) +// } else { +// console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) +// } +// +// if (argv.createRpmPackage) { +// createRpmPackage(packagedAppPath) +// } else { +// console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) +// } +// } +// +// return Promise.resolve(packagedAppPath) +// }).then(packagedAppPath => { +// if (argv.compressArtifacts) { +// compressArtifacts(packagedAppPath) +// } else { +// console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) +// } +// +// if (argv.install) { +// installApplication(packagedAppPath) +// } else { +// console.log('Skipping installation. Specify the --install option to install Atom'.gray) +// } +// }) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index d7da7d8de..0824b7e12 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -9,7 +9,7 @@ module.exports = function () { const coreModules = new Set([ 'path', 'electron', 'module', 'fs', 'child_process', 'crypto', 'url', 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', - 'http', 'https', 'shell', 'querystring', 'zlib', 'stream', 'WNdb', 'lapack' + 'http', 'https', 'shell', 'querystring', 'zlib', 'stream', 'WNdb', 'lapack', 'remote' ]) const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') const snapshotScriptContent = electronLink({ @@ -26,14 +26,21 @@ module.exports = function () { relativePath == path.join('..', 'src', 'electron-shims.js') || relativePath == path.join('..', 'src', 'module-cache.js') || relativePath == path.join('..', 'src', 'safe-clipboard.js') || + relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || + relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'temp', 'lib', 'temp.js') || + relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'helpers.js') || relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || relativePath == path.join('..', 'node_modules', 'clear-cut', 'index.js') || relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('..', 'node_modules', 'find-and-replace', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || + relativePath == path.join('..', 'node_modules', 'exception-reporting', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'symbols-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') || relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || @@ -41,6 +48,9 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || relativePath == path.join('..', 'node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || + relativePath == path.join('..', 'node_modules', 'metrics', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'notifications', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') || relativePath == path.join('..', 'node_modules', 'mime', 'mime.js') || relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') || relativePath == path.join('..', 'node_modules', 'pathwatcher', 'lib', 'main.js') || @@ -51,6 +61,7 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || relativePath == path.join('..', 'node_modules', 'styleguide', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') || + relativePath == path.join('..', 'node_modules', 'tree-view', 'node_modules', 'pathwatcher', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') diff --git a/script/lib/transpile-babel-paths.js b/script/lib/transpile-babel-paths.js index 3c440a4bd..0a6a15f93 100644 --- a/script/lib/transpile-babel-paths.js +++ b/script/lib/transpile-babel-paths.js @@ -28,6 +28,7 @@ function getPathsToTranspile () { paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'benchmarks', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'exports', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'src', '**', '*.js'))) + paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, '**', 'atom-select-list', 'src', 'select-list-view.js'))) for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) { paths = paths.concat(glob.sync( path.join(CONFIG.intermediateAppPath, 'node_modules', packageName, '**', '*.js'), diff --git a/src/coffee-script.js b/src/coffee-script.js index 0437e787f..45f55e219 100644 --- a/src/coffee-script.js +++ b/src/coffee-script.js @@ -35,8 +35,7 @@ exports.compile = function (sourceCode, filePath) { var output = CoffeeScript.compile(sourceCode, { filename: filePath, - sourceFiles: [filePath], - inlineMap: true + sourceFiles: [filePath] }) // Strip sourceURL from output so there wouldn't be duplicate entries diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 9eda1ef3b..00aad7714 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -3,6 +3,7 @@ ApplicationDelegate = require './application-delegate' Clipboard = require './clipboard' TextEditor = require './text-editor' TextEditorComponent = require './text-editor-component' + require('about') require('archive-view') require('autocomplete-atom-api') @@ -38,48 +39,15 @@ require('package-generator') require('settings-view') require('snippets') require('spell-check') -# require('status-bar') +require('status-bar') require('styleguide') require('symbols-view') require('tabs') require('timecop') require('tree-view') -# require('update-package-dependencies') +require('update-package-dependencies') require('welcome') require('whitespace') -# require('wrap-guide') -# require('language-c') -# require('language-clojure') -# require('language-coffee-script') -# require('language-csharp') -# require('language-css') -# require('language-gfm') -# require('language-git') -# require('language-go') -# require('language-html') -# require('language-hyperlink') -# require('language-java') -# require('language-javascript') -# require('language-json') -# require('language-less') -# require('language-make') -# require('language-mustache') -# require('language-objective-c') -# require('language-perl') -# require('language-php') -# require('language-property-list') -# require('language-python') -# require('language-ruby') -# require('language-ruby-on-rails') -# require('language-sass') -# require('language-shellscript') -# require('language-source') -# require('language-sql') -# require('language-text') -# require('language-todo') -# require('language-toml') -# require('language-xml') -# require('language-yaml') # Like sands through the hourglass, so are the days of our lives. module.exports = -> diff --git a/static/babelrc.json b/static/babelrc.json index 11474dd8d..5d887251a 100644 --- a/static/babelrc.json +++ b/static/babelrc.json @@ -1,5 +1,4 @@ { - "sourceMap": "inline", "plugins": [ ["add-module-exports", {}], ["transform-async-to-generator", {}], From c2f02e16fe38217caa103c32e1d68e375d6d4d53 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 08:13:26 +0100 Subject: [PATCH 07/50] Verify that snapshot can be executed via `mksnapshot` --- script/lib/generate-startup-snapshot.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 0824b7e12..286643fa7 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -2,20 +2,26 @@ const fs = require('fs') const path = require('path') const electronLink = require('electron-link') const CONFIG = require('../config') +const vm = require('vm') module.exports = function () { const snapshotScriptPath = path.join(CONFIG.buildOutputPath, 'startup.js') - console.log(`Generating snapshot script at "${snapshotScriptPath}"`) const coreModules = new Set([ 'path', 'electron', 'module', 'fs', 'child_process', 'crypto', 'url', 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', 'http', 'https', 'shell', 'querystring', 'zlib', 'stream', 'WNdb', 'lapack', 'remote' ]) const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') + let processedFiles = 0 const snapshotScriptContent = electronLink({ baseDirPath, mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'), shouldExcludeModule: (modulePath) => { + if (processedFiles > 0) { + process.stdout.write('\r') + } + process.stdout.write(`Generating snapshot script at "${snapshotScriptPath}" (${++processedFiles})`) + const relativePath = path.relative(baseDirPath, modulePath) return ( modulePath.endsWith('.node') || modulePath === 'buffer-offset-index' || @@ -69,4 +75,8 @@ module.exports = function () { } }) fs.writeFileSync(snapshotScriptPath, snapshotScriptContent) + process.stdout.write('\n') + + console.log('Verifying if snapshot can be executed via `mksnapshot`') + vm.runInNewContext(snapshotScriptContent, undefined, {filename: snapshotScriptPath, displayErrors: true}) } From 5dbae1c3179b20327576133c25469e4b3932f822 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 10:39:05 +0100 Subject: [PATCH 08/50] Copy the generated snapshot into the app bundle --- script/lib/generate-startup-snapshot.js | 34 ++++++++++++++++++++----- src/initialize-snapshot.js | 5 ---- src/main-process/main.js | 2 +- src/task.coffee | 2 +- 4 files changed, 30 insertions(+), 13 deletions(-) delete mode 100644 src/initialize-snapshot.js diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 286643fa7..1d5954a31 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -1,16 +1,13 @@ +const childProcess = require('child_process') const fs = require('fs') const path = require('path') const electronLink = require('electron-link') const CONFIG = require('../config') const vm = require('vm') -module.exports = function () { +module.exports = function (packagedAppPath) { const snapshotScriptPath = path.join(CONFIG.buildOutputPath, 'startup.js') - const coreModules = new Set([ - 'path', 'electron', 'module', 'fs', 'child_process', 'crypto', 'url', - 'atom', 'vm', 'events', 'os', 'assert', 'buffer', 'tty', 'net', 'constants', - 'http', 'https', 'shell', 'querystring', 'zlib', 'stream', 'WNdb', 'lapack', 'remote' - ]) + const coreModules = new Set(['electron', 'atom', 'shell', 'WNdb', 'lapack', 'remote']) const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') let processedFiles = 0 const snapshotScriptContent = electronLink({ @@ -45,11 +42,14 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'find-and-replace', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || + relativePath == path.join('..', 'node_modules', 'debug', 'node.js') || relativePath == path.join('..', 'node_modules', 'exception-reporting', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'symbols-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') || relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || + relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'internal.js') || + relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || @@ -64,8 +64,15 @@ module.exports = function () { relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'htmlparser2', 'lib', 'index.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'request', 'request.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'cookie.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'memstore.js') || relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || + relativePath == path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') || relativePath == path.join('..', 'node_modules', 'styleguide', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || + relativePath == path.join('..', 'node_modules', 'status-bar', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'tree-view', 'node_modules', 'pathwatcher', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') || @@ -79,4 +86,19 @@ module.exports = function () { console.log('Verifying if snapshot can be executed via `mksnapshot`') vm.runInNewContext(snapshotScriptContent, undefined, {filename: snapshotScriptPath, displayErrors: true}) + + const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin') + console.log(`Generating startup blob at "${generatedStartupBlobPath}"`) + childProcess.execFileSync( + path.join(CONFIG.repositoryRootPath, 'electron', 'mksnapshot', `mksnapshot`), + [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath] + ) + + const startupBlobDestinationPath = path.join( + packagedAppPath, + 'Contents', 'Frameworks', 'Electron Framework.framework', 'Resources', 'snapshot_blob.bin' + ) + console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`) + fs.unlinkSync(startupBlobDestinationPath) + fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath) } diff --git a/src/initialize-snapshot.js b/src/initialize-snapshot.js deleted file mode 100644 index 47bd5afa0..000000000 --- a/src/initialize-snapshot.js +++ /dev/null @@ -1,5 +0,0 @@ -require('./update-process-env') -require('./window') -require('./atom-environment') -require('./application-delegate') -require('./clipboard') diff --git a/src/main-process/main.js b/src/main-process/main.js index e77d1930f..0614f19d2 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -1,5 +1,5 @@ if (typeof snapshotResult !== 'undefined') { - snapshotResult.setGlobals(global, process, {}, require) + snapshotResult.setGlobals(global, process, global, {}, require) } const startTime = Date.now() diff --git a/src/task.coffee b/src/task.coffee index 8555b6554..f3e56a507 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -70,7 +70,7 @@ class Task compileCachePath = require('./compile-cache').getCacheDirectory() taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');" bootstrap = """ - snapshotResult.setGlobals(global, process, global, require) + snapshotResult.setGlobals(global, process, global, {}, require) CompileCache = snapshotResult.customRequire('../src/compile-cache.js') CompileCache.setCacheDirectory('#{compileCachePath}'); #{taskBootstrapRequire} From f87a53bce9dbf34f46b696e974894d2cbb746790 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 11:01:59 +0100 Subject: [PATCH 09/50] Run all steps in script/build --- script/build | 101 ++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/script/build b/script/build index 9afc5b378..376067000 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -// require('./bootstrap') +require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') @@ -56,52 +56,53 @@ transpileBabelPaths() transpileCoffeeScriptPaths() transpileCsonPaths() transpilePegJsPaths() -// generateModuleCache() -// prebuildLessCache() -// generateMetadata() -generateStartupSnapshot() -// generateAPIDocs() -// dumpSymbols() -// .then(packageApplication) -// .then(packagedAppPath => { -// if (process.platform === 'darwin') { -// if (argv.codeSign) { -// codeSignOnMac(packagedAppPath) -// } else { -// console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) -// } -// } else if (process.platform === 'win32') { -// if (argv.createWindowsInstaller) { -// return createWindowsInstaller(packagedAppPath, argv.codeSign).then(() => packagedAppPath) -// } -// else { -// console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer. Code-signing was skipped too.'.gray) -// } -// } else if (process.platform === 'linux') { -// if (argv.createDebianPackage) { -// createDebianPackage(packagedAppPath) -// } else { -// console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) -// } -// -// if (argv.createRpmPackage) { -// createRpmPackage(packagedAppPath) -// } else { -// console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) -// } -// } -// -// return Promise.resolve(packagedAppPath) -// }).then(packagedAppPath => { -// if (argv.compressArtifacts) { -// compressArtifacts(packagedAppPath) -// } else { -// console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) -// } -// -// if (argv.install) { -// installApplication(packagedAppPath) -// } else { -// console.log('Skipping installation. Specify the --install option to install Atom'.gray) -// } -// }) +generateModuleCache() +prebuildLessCache() +generateMetadata() +generateAPIDocs() +dumpSymbols() + .then(packageApplication) + .then(packagedAppPath => { + generateStartupSnapshot(packagedAppPath) + + if (process.platform === 'darwin') { + if (argv.codeSign) { + codeSignOnMac(packagedAppPath) + } else { + console.log('Skipping code-signing. Specify the --code-sign option to perform code-signing'.gray) + } + } else if (process.platform === 'win32') { + if (argv.createWindowsInstaller) { + return createWindowsInstaller(packagedAppPath, argv.codeSign).then(() => packagedAppPath) + } + else { + console.log('Skipping creating installer. Specify the --create-windows-installer option to create a Squirrel-based Windows installer. Code-signing was skipped too.'.gray) + } + } else if (process.platform === 'linux') { + if (argv.createDebianPackage) { + createDebianPackage(packagedAppPath) + } else { + console.log('Skipping creating debian package. Specify the --create-debian-package option to create it.'.gray) + } + + if (argv.createRpmPackage) { + createRpmPackage(packagedAppPath) + } else { + console.log('Skipping creating rpm package. Specify the --create-rpm-package option to create it.'.gray) + } + } + + return Promise.resolve(packagedAppPath) + }).then(packagedAppPath => { + if (argv.compressArtifacts) { + compressArtifacts(packagedAppPath) + } else { + console.log('Skipping artifacts compression. Specify the --compress-artifacts option to compress Atom binaries (and symbols on macOS)'.gray) + } + + if (argv.install) { + installApplication(packagedAppPath) + } else { + console.log('Skipping installation. Specify the --install option to install Atom'.gray) + } + }) From 367d595ab8b1b3b26b48c0322ccb0af729b86029 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 11:49:17 +0100 Subject: [PATCH 10/50] Update static/index to match what we do on master --- script/lib/generate-metadata.js | 4 +- static/index.js | 79 ++++++--------------------------- 2 files changed, 15 insertions(+), 68 deletions(-) diff --git a/script/lib/generate-metadata.js b/script/lib/generate-metadata.js index 89ef04f69..8267b1cee 100644 --- a/script/lib/generate-metadata.js +++ b/script/lib/generate-metadata.js @@ -27,8 +27,8 @@ function buildBundledPackagesMetadata () { const packagePath = path.join(CONFIG.intermediateAppPath, 'node_modules', packageName) const packageMetadataPath = path.join(packagePath, 'package.json') const packageMetadata = JSON.parse(fs.readFileSync(packageMetadataPath, 'utf8')) - normalizePackageData(packageMetadata, () => { - throw new Error(`Invalid package metadata. ${metadata.name}: ${msg}`) + normalizePackageData(packageMetadata, (msg) => { + console.warn(`Invalid package metadata. ${packageMetadata.name}: ${msg}`) }, true) if (packageMetadata.repository && packageMetadata.repository.url && packageMetadata.repository.type === 'git') { packageMetadata.repository.url = packageMetadata.repository.url.replace(/^git\+/, '') diff --git a/static/index.js b/static/index.js index 889b7f98b..e1d06558f 100644 --- a/static/index.js +++ b/static/index.js @@ -3,6 +3,7 @@ const Module = require('module') const Path = require('path') const vm = require('vm') + const {remote, ipcRenderer} = require('electron') if (typeof snapshotResult !== 'undefined') { window.onload = function () { @@ -11,8 +12,17 @@ console.error('Unhandled promise rejection %o with error: %o', promise, error) }) - parseLoadSettings() - setupAtomHome() + loadSettings = remote.getCurrentWindow().loadSettings + + if (!process.env.ATOM_HOME) { + // Ensure ATOM_HOME is always set before anything else is required + // This is because of a difference in Linux not inherited between browser and render processes + // https://github.com/atom/atom/issues/5412 + if (loadSettings && loadSettings.atomHome) { + process.env.ATOM_HOME = loadSettings.atomHome + } + } + require('../src/crash-reporter-start')({_version: loadSettings.appVersion}) const entryPointDirPath = __dirname @@ -32,70 +42,7 @@ CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) const initialize = snapshotResult.customRequire('../src/initialize-application-window.js') - initialize() - } - } - - function setupVmCompatibility () { - var vm = require('vm') - if (!vm.Script.createContext) { - vm.Script.createContext = vm.createContext - } - } - - function setupDeprecatedPackages () { - var metadata = require('../package.json') - if (!metadata._deprecatedPackages) { - try { - metadata._deprecatedPackages = require('../script/deprecated-packages.json') - } catch (requireError) { - console.error('Failed to setup deprecated packages list', requireError.stack) - } - } - } - - function profileStartup (loadSettings, initialTime) { - function profile () { - console.profile('startup') - var startTime = Date.now() - setupWindow(loadSettings).then(function () { - setLoadTime(Date.now() - startTime + initialTime) - console.profileEnd('startup') - console.log('Switch to the Profiles tab to view the created startup profile') - }) - } - - var currentWindow = require('electron').remote.getCurrentWindow() - if (currentWindow.devToolsWebContents) { - profile() - } else { - currentWindow.openDevTools() - currentWindow.once('devtools-opened', function () { - setTimeout(profile, 1000) - }) - } - } - - function parseLoadSettings () { - var rawLoadSettings = decodeURIComponent(window.location.hash.substr(1)) - try { - loadSettings = JSON.parse(rawLoadSettings) - } catch (error) { - console.error('Failed to parse load settings: ' + rawLoadSettings) - loadSettingsError = error - } - } - - var setupAtomHome = function () { - if (process.env.ATOM_HOME) { - return - } - - // Ensure ATOM_HOME is always set before anything else is required - // This is because of a difference in Linux not inherited between browser and render processes - // https://github.com/atom/atom/issues/5412 - if (loadSettings && loadSettings.atomHome) { - process.env.ATOM_HOME = loadSettings.atomHome + initialize().then(() => { ipcRenderer.send('window-command', 'window:loaded') }) } } })() From 91a38b633ef713d61cca093502799613b4c9488c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 13:22:24 +0100 Subject: [PATCH 11/50] Require wrap-guide during snapshot --- src/initialize-application-window.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 00aad7714..24039ac4e 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -48,6 +48,7 @@ require('tree-view') require('update-package-dependencies') require('welcome') require('whitespace') +require('wrap-guide') # Like sands through the hourglass, so are the days of our lives. module.exports = -> From ea879340c02f1afae7f5e19288fa3607aaed7b34 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 24 Feb 2017 16:36:16 +0100 Subject: [PATCH 12/50] WIP --- script/build | 2 +- script/lib/package-application.js | 1 - src/package.coffee | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/script/build b/script/build index 376067000..376550f3f 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -require('./bootstrap') +//require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') diff --git a/script/lib/package-application.js b/script/lib/package-application.js index 1e63b8dc0..8c4127b4f 100644 --- a/script/lib/package-application.js +++ b/script/lib/package-application.js @@ -19,7 +19,6 @@ module.exports = function () { 'app-copyright': `Copyright © 2014-${(new Date()).getFullYear()} GitHub, Inc. All rights reserved.`, 'app-version': CONFIG.appMetadata.version, 'arch': process.platform === 'darwin' ? 'x64' : process.arch, // OS X is 64-bit only - 'asar': {unpack: buildAsarUnpackGlobExpression()}, 'build-version': CONFIG.appMetadata.version, 'download': {cache: CONFIG.electronDownloadPath}, 'dir': CONFIG.intermediateAppPath, diff --git a/src/package.coffee b/src/package.coffee index 63efbf02c..e34c70981 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -7,7 +7,6 @@ fs = require 'fs-plus' {Emitter, CompositeDisposable} = require 'event-kit' CompileCache = require './compile-cache' -ModuleCache = require './module-cache' ScopedProperties = require './scoped-properties' BufferedProcess = require './buffered-process' @@ -42,7 +41,7 @@ class Package @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @name = @metadata?.name ? path.basename(@path) - ModuleCache.add(@path, @metadata) + # ModuleCache.add(@path, @metadata) @reset() ### From 54eb65631a5f4086dc9dee0f4ae293ef0023a98d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 27 Feb 2017 09:38:00 +0100 Subject: [PATCH 13/50] :arrow_up: electron-link --- script/build | 3 +- script/lib/generate-startup-snapshot.js | 45 +++++++++++++------------ script/package.json | 1 + 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/script/build b/script/build index 376550f3f..7ceb239b9 100755 --- a/script/build +++ b/script/build @@ -62,9 +62,8 @@ generateMetadata() generateAPIDocs() dumpSymbols() .then(packageApplication) + .then(packagedAppPath => generateStartupSnapshot(packagedAppPath).then(() => packagedAppPath)) .then(packagedAppPath => { - generateStartupSnapshot(packagedAppPath) - if (process.platform === 'darwin') { if (argv.codeSign) { codeSignOnMac(packagedAppPath) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 1d5954a31..2a05ab027 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -10,9 +10,11 @@ module.exports = function (packagedAppPath) { const coreModules = new Set(['electron', 'atom', 'shell', 'WNdb', 'lapack', 'remote']) const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static') let processedFiles = 0 - const snapshotScriptContent = electronLink({ + + return electronLink({ baseDirPath, mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'), + cachePath: path.join(CONFIG.atomHomeDirPath, 'snapshot-cache'), shouldExcludeModule: (modulePath) => { if (processedFiles > 0) { process.stdout.write('\r') @@ -80,25 +82,26 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') ) } + }).then((snapshotScriptContent) => { + fs.writeFileSync(snapshotScriptPath, snapshotScriptContent) + process.stdout.write('\n') + + console.log('Verifying if snapshot can be executed via `mksnapshot`') + vm.runInNewContext(snapshotScriptContent, undefined, {filename: snapshotScriptPath, displayErrors: true}) + + const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin') + console.log(`Generating startup blob at "${generatedStartupBlobPath}"`) + childProcess.execFileSync( + path.join(CONFIG.repositoryRootPath, 'electron', 'mksnapshot', `mksnapshot`), + [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath] + ) + + const startupBlobDestinationPath = path.join( + packagedAppPath, + 'Contents', 'Frameworks', 'Electron Framework.framework', 'Resources', 'snapshot_blob.bin' + ) + console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`) + fs.unlinkSync(startupBlobDestinationPath) + fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath) }) - fs.writeFileSync(snapshotScriptPath, snapshotScriptContent) - process.stdout.write('\n') - - console.log('Verifying if snapshot can be executed via `mksnapshot`') - vm.runInNewContext(snapshotScriptContent, undefined, {filename: snapshotScriptPath, displayErrors: true}) - - const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin') - console.log(`Generating startup blob at "${generatedStartupBlobPath}"`) - childProcess.execFileSync( - path.join(CONFIG.repositoryRootPath, 'electron', 'mksnapshot', `mksnapshot`), - [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath] - ) - - const startupBlobDestinationPath = path.join( - packagedAppPath, - 'Contents', 'Frameworks', 'Electron Framework.framework', 'Resources', 'snapshot_blob.bin' - ) - console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`) - fs.unlinkSync(startupBlobDestinationPath) - fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath) } diff --git a/script/package.json b/script/package.json index 87c43f261..ed21ea906 100644 --- a/script/package.json +++ b/script/package.json @@ -8,6 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", + "electron-link": "0.0.7", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", "fs-extra": "0.30.0", From 681f0f9fe1ca40425342102f01b0f1f406013858 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 27 Feb 2017 14:47:20 +0100 Subject: [PATCH 14/50] Make Atom work also without a snapshot --- src/package.coffee | 3 +- static/index.js | 143 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 116 insertions(+), 30 deletions(-) diff --git a/src/package.coffee b/src/package.coffee index e34c70981..386cc0018 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -41,7 +41,8 @@ class Package @metadata ?= @packageManager.loadPackageMetadata(@path) @bundledPackage = @packageManager.isBundledPackagePath(@path) @name = @metadata?.name ? path.basename(@path) - # ModuleCache.add(@path, @metadata) + unless @bundledPackage + ModuleCache.add(@path, @metadata) @reset() ### diff --git a/static/index.js b/static/index.js index e1d06558f..9fbfbcea7 100644 --- a/static/index.js +++ b/static/index.js @@ -1,48 +1,133 @@ (function () { - let loadSettings - const Module = require('module') - const Path = require('path') - const vm = require('vm') - const {remote, ipcRenderer} = require('electron') + const path = require('path') + const getWindowLoadSettings = require('../src/get-window-load-settings') + const entryPointDirPath = __dirname + let blobStore = null + let devMode = false + let useSnapshot = false + let requireFunction = null + + window.onload = function () { + try { + var startTime = Date.now() - if (typeof snapshotResult !== 'undefined') { - window.onload = function () { - process.resourcesPath = Path.normalize(process.resourcesPath) process.on('unhandledRejection', function (error, promise) { console.error('Unhandled promise rejection %o with error: %o', promise, error) }) - loadSettings = remote.getCurrentWindow().loadSettings + // Normalize to make sure drive letter case is consistent on Windows + process.resourcesPath = path.normalize(process.resourcesPath) - if (!process.env.ATOM_HOME) { - // Ensure ATOM_HOME is always set before anything else is required - // This is because of a difference in Linux not inherited between browser and render processes - // https://github.com/atom/atom/issues/5412 - if (loadSettings && loadSettings.atomHome) { - process.env.ATOM_HOME = loadSettings.atomHome + setupAtomHome() + devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep) + useSnapshot = !devMode && typeof snapshotResult !== 'undefined' + requireFunction = useSnapshot ? snapshotResult.customRequire : require + + if (devMode) { + var metadata = require('../package.json') + if (!metadata._deprecatedPackages) { + try { + metadata._deprecatedPackages = require('../script/deprecated-packages.json') + } catch (requireError) { + console.error('Failed to setup deprecated packages list', requireError.stack) + } } + } else if (useSnapshot) { + Module.prototype.require = function (modulePath) { + const absoluteFilePath = Module._resolveFilename(modulePath, this, false) + const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) + return snapshotResult.customRequire(relativeFilePath) + } + + snapshotResult.setGlobals(global, process, window, document, Module._load) } - require('../src/crash-reporter-start')({_version: loadSettings.appVersion}) + const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') + blobStore = FileSystemBlobStore.load( + path.join(process.env.ATOM_HOME, 'blob-store/') + ) - const entryPointDirPath = __dirname - Module.prototype.require = function (path) { - const absoluteFilePath = Module._resolveFilename(path, this, false) - const relativeFilePath = Path.relative(entryPointDirPath, absoluteFilePath) - const cachedModule = snapshotResult.customRequire.cache[relativeFilePath] - return cachedModule ? cachedModule : Module._load(path, this, false) + const NativeCompileCache = requireFunction('../src/native-compile-cache.js') + NativeCompileCache.setCacheStore(blobStore) + NativeCompileCache.setV8Version(process.versions.v8) + NativeCompileCache.install() + + if (getWindowLoadSettings().profileStartup) { + profileStartup(Date.now() - startTime) + } else { + setupWindow() + setLoadTime(Date.now() - startTime) } + } catch (error) { + handleSetupError(error) + } + } - snapshotResult.setGlobals(global, process, window, document, require) + function setLoadTime (loadTime) { + if (global.atom) { + global.atom.loadTime = loadTime + } + } - const CSON = snapshotResult.customRequire("../node_modules/season/lib/cson.js") - CSON.setCacheDir(Path.join(process.env.ATOM_HOME, 'compile-cache', 'cson')) + function handleSetupError (error) { + const currentWindow = require('electron').remote.getCurrentWindow() + currentWindow.setSize(800, 600) + currentWindow.center() + currentWindow.show() + currentWindow.openDevTools() + console.error(error.stack || error) + } - const CompileCache = snapshotResult.customRequire('../src/compile-cache.js') - CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) + function setupWindow () { + const CompileCache = requireFunction('../src/compile-cache.js') + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - const initialize = snapshotResult.customRequire('../src/initialize-application-window.js') - initialize().then(() => { ipcRenderer.send('window-command', 'window:loaded') }) + const ModuleCache = requireFunction('../src/module-cache.js') + ModuleCache.register(getWindowLoadSettings()) + + const startCrashReporter = requireFunction('../src/crash-reporter-start.js') + startCrashReporter({_version: getWindowLoadSettings().appVersion}) + + const CSON = requireFunction(useSnapshot ? '../node_modules/season/lib/cson.js' : 'season') + CSON.setCacheDir(path.join(CompileCache.getCacheDirectory(), 'cson')) + + const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) + const initialize = requireFunction(initScriptPath) + return initialize({blobStore: blobStore}).then(function () { + require('electron').ipcRenderer.send('window-command', 'window:loaded') + }) + } + + function profileStartup (initialTime) { + function profile () { + console.profile('startup') + var startTime = Date.now() + setupWindow().then(function () { + setLoadTime(Date.now() - startTime + initialTime) + console.profileEnd('startup') + console.log('Switch to the Profiles tab to view the created startup profile') + }) + } + + const webContents = require('electron').remote.getCurrentWindow().webContents + if (webContents.devToolsWebContents) { + profile() + } else { + webContents.once('devtools-opened', () => { setTimeout(profile, 1000) }) + webContents.openDevTools() + } + } + + function setupAtomHome () { + if (process.env.ATOM_HOME) { + return + } + + // Ensure ATOM_HOME is always set before anything else is required + // This is because of a difference in Linux not inherited between browser and render processes + // https://github.com/atom/atom/issues/5412 + if (getWindowLoadSettings() && getWindowLoadSettings().atomHome) { + process.env.ATOM_HOME = getWindowLoadSettings().atomHome } } })() From aec88679047a408ea1c51a47bb7ab7c0236573fd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 27 Feb 2017 14:48:45 +0100 Subject: [PATCH 15/50] Require electron once --- static/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/static/index.js b/static/index.js index 9fbfbcea7..5c65cbd46 100644 --- a/static/index.js +++ b/static/index.js @@ -1,4 +1,5 @@ (function () { + const electron = require('electron') const path = require('path') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname @@ -70,7 +71,7 @@ } function handleSetupError (error) { - const currentWindow = require('electron').remote.getCurrentWindow() + const currentWindow = electron.remote.getCurrentWindow() currentWindow.setSize(800, 600) currentWindow.center() currentWindow.show() @@ -94,7 +95,7 @@ const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) const initialize = requireFunction(initScriptPath) return initialize({blobStore: blobStore}).then(function () { - require('electron').ipcRenderer.send('window-command', 'window:loaded') + electron.ipcRenderer.send('window-command', 'window:loaded') }) } @@ -109,7 +110,7 @@ }) } - const webContents = require('electron').remote.getCurrentWindow().webContents + const webContents = electron.remote.getCurrentWindow().webContents if (webContents.devToolsWebContents) { profile() } else { From 7b8849b8355f05d97d4b038287c29865d5a0decd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 27 Feb 2017 14:51:33 +0100 Subject: [PATCH 16/50] :art: --- static/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/index.js b/static/index.js index 5c65cbd46..8809bf436 100644 --- a/static/index.js +++ b/static/index.js @@ -10,7 +10,7 @@ window.onload = function () { try { - var startTime = Date.now() + const startTime = Date.now() process.on('unhandledRejection', function (error, promise) { console.error('Unhandled promise rejection %o with error: %o', promise, error) @@ -25,7 +25,7 @@ requireFunction = useSnapshot ? snapshotResult.customRequire : require if (devMode) { - var metadata = require('../package.json') + const metadata = require('../package.json') if (!metadata._deprecatedPackages) { try { metadata._deprecatedPackages = require('../script/deprecated-packages.json') @@ -102,7 +102,7 @@ function profileStartup (initialTime) { function profile () { console.profile('startup') - var startTime = Date.now() + const startTime = Date.now() setupWindow().then(function () { setLoadTime(Date.now() - startTime + initialTime) console.profileEnd('startup') From e453b04105abdea29fefb3a85bc11636471b027f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 27 Feb 2017 16:37:48 +0100 Subject: [PATCH 17/50] Put back code that was commented out --- script/build | 2 +- script/lib/transpile-babel-paths.js | 1 - src/atom-environment.coffee | 8 +++++++- src/coffee-script.js | 3 ++- src/initialize-application-window.coffee | 4 ++-- src/package.coffee | 1 + static/index.js | 11 ++++++----- 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/script/build b/script/build index 7ceb239b9..2b45e425d 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -//require('./bootstrap') +require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') diff --git a/script/lib/transpile-babel-paths.js b/script/lib/transpile-babel-paths.js index 0a6a15f93..3c440a4bd 100644 --- a/script/lib/transpile-babel-paths.js +++ b/script/lib/transpile-babel-paths.js @@ -28,7 +28,6 @@ function getPathsToTranspile () { paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'benchmarks', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'exports', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'src', '**', '*.js'))) - paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, '**', 'atom-select-list', 'src', 'select-list-view.js'))) for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) { paths = paths.concat(glob.sync( path.join(CONFIG.intermediateAppPath, 'node_modules', packageName, '**', '*.js'), diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index dae45f7a2..3133b5af8 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -131,7 +131,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params + {@blobStore, @applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @unloaded = false @loadTime = null @@ -733,6 +733,7 @@ class AtomEnvironment extends Model @storeWindowBackground() @packages.deactivatePackages() + @saveBlobStoreSync() @unloaded = true openInitialEmptyEditorIfNecessary: -> @@ -866,6 +867,11 @@ class AtomEnvironment extends Model showSaveDialogSync: (options={}) -> @applicationDelegate.showSaveDialog(options) + saveBlobStoreSync: -> + return unless @enablePersistence + + @blobStore.save() + saveState: (options) -> new Promise (resolve, reject) => if @enablePersistence and @project diff --git a/src/coffee-script.js b/src/coffee-script.js index 45f55e219..0437e787f 100644 --- a/src/coffee-script.js +++ b/src/coffee-script.js @@ -35,7 +35,8 @@ exports.compile = function (sourceCode, filePath) { var output = CoffeeScript.compile(sourceCode, { filename: filePath, - sourceFiles: [filePath] + sourceFiles: [filePath], + inlineMap: true }) // Strip sourceURL from output so there wouldn't be duplicate entries diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 24039ac4e..a3a57e886 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -51,7 +51,7 @@ require('whitespace') require('wrap-guide') # Like sands through the hourglass, so are the days of our lives. -module.exports = -> +module.exports = ({blobStore}) -> {updateProcessEnv} = require('./update-process-env') path = require 'path' require './window' @@ -72,7 +72,7 @@ module.exports = -> TextEditor.setClipboard(clipboard) window.atom = new AtomEnvironment({ - window, document, clipboard, + window, document, clipboard, blobStore, applicationDelegate: new ApplicationDelegate, configDirPath: process.env.ATOM_HOME, enablePersistence: true, diff --git a/src/package.coffee b/src/package.coffee index 386cc0018..dea9c0e58 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -7,6 +7,7 @@ fs = require 'fs-plus' {Emitter, CompositeDisposable} = require 'event-kit' CompileCache = require './compile-cache' +ModuleCache = require './module-cache' ScopedProperties = require './scoped-properties' BufferedProcess = require './buffered-process' diff --git a/static/index.js b/static/index.js index 8809bf436..8d5263c00 100644 --- a/static/index.js +++ b/static/index.js @@ -34,13 +34,14 @@ } } } else if (useSnapshot) { - Module.prototype.require = function (modulePath) { - const absoluteFilePath = Module._resolveFilename(modulePath, this, false) - const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) - return snapshotResult.customRequire(relativeFilePath) + Module.prototype.require = function (path) { + const absoluteFilePath = Module._resolveFilename(path, this, false) + const relativeFilePath = Path.relative(entryPointDirPath, absoluteFilePath) + const cachedModule = snapshotResult.customRequire.cache[relativeFilePath] + return cachedModule ? cachedModule : Module._load(path, this, false) } - snapshotResult.setGlobals(global, process, window, document, Module._load) + snapshotResult.setGlobals(global, process, window, document, require) } const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') From 9b8c7973d724fd66064e814a4c2699abb1649a32 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 09:34:55 +0100 Subject: [PATCH 18/50] WIP --- script/build | 2 +- script/lib/generate-startup-snapshot.js | 6 ++--- script/lib/transpile-babel-paths.js | 1 + src/atom-environment.coffee | 8 +----- src/initialize-application-window.coffee | 3 +++ src/module-cache.coffee | 32 ++---------------------- src/task.coffee | 2 +- static/index.js | 32 +++++++++++++----------- 8 files changed, 29 insertions(+), 57 deletions(-) diff --git a/script/build b/script/build index 2b45e425d..a5368768c 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -require('./bootstrap') +// require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 2a05ab027..f7951daac 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -28,8 +28,8 @@ module.exports = function (packagedAppPath) { (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) || relativePath == path.join('..', 'exports', 'atom.js') || relativePath == path.join('..', 'src', 'config-schema.js') || + relativePath == path.join('..', 'src', 'compile-cache.js') || relativePath == path.join('..', 'src', 'electron-shims.js') || - relativePath == path.join('..', 'src', 'module-cache.js') || relativePath == path.join('..', 'src', 'safe-clipboard.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || @@ -62,13 +62,13 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'mime', 'mime.js') || relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') || relativePath == path.join('..', 'node_modules', 'pathwatcher', 'lib', 'main.js') || - relativePath == path.join('..', 'node_modules', 'request', 'request.js') || + relativePath == path.join('..', 'node_modules', 'request', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'htmlparser2', 'lib', 'index.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'request', 'request.js') || + relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'request', 'index.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'cookie.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'memstore.js') || relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || diff --git a/script/lib/transpile-babel-paths.js b/script/lib/transpile-babel-paths.js index 3c440a4bd..0a6a15f93 100644 --- a/script/lib/transpile-babel-paths.js +++ b/script/lib/transpile-babel-paths.js @@ -28,6 +28,7 @@ function getPathsToTranspile () { paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'benchmarks', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'exports', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'src', '**', '*.js'))) + paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, '**', 'atom-select-list', 'src', 'select-list-view.js'))) for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) { paths = paths.concat(glob.sync( path.join(CONFIG.intermediateAppPath, 'node_modules', packageName, '**', '*.js'), diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 3133b5af8..dae45f7a2 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -131,7 +131,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params + {@applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @unloaded = false @loadTime = null @@ -733,7 +733,6 @@ class AtomEnvironment extends Model @storeWindowBackground() @packages.deactivatePackages() - @saveBlobStoreSync() @unloaded = true openInitialEmptyEditorIfNecessary: -> @@ -867,11 +866,6 @@ class AtomEnvironment extends Model showSaveDialogSync: (options={}) -> @applicationDelegate.showSaveDialog(options) - saveBlobStoreSync: -> - return unless @enablePersistence - - @blobStore.save() - saveState: (options) -> new Promise (resolve, reject) => if @enablePersistence and @project diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index a3a57e886..507818998 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -3,6 +3,9 @@ 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' require('about') require('archive-view') diff --git a/src/module-cache.coffee b/src/module-cache.coffee index 8c6a7c312..5bc162ab1 100644 --- a/src/module-cache.coffee +++ b/src/module-cache.coffee @@ -20,7 +20,7 @@ class Range extends semver.Range @unmatchedVersions.add(version) matches -nativeModules = process.binding('natives') +nativeModules = null cache = builtins: {} @@ -171,6 +171,7 @@ resolveModulePath = (relativePath, parentModule) -> return unless relativePath return unless parentModule?.filename + nativeModules ?= process.binding('natives') return if nativeModules.hasOwnProperty(relativePath) return if relativePath[0] is '.' return if isAbsolute(relativePath) @@ -212,35 +213,6 @@ registerBuiltins = (devMode) -> for builtin in rendererBuiltins cache.builtins[builtin] = path.join(rendererRoot, "#{builtin}.js") -if cache.debug - cache.findPathCount = 0 - cache.findPathTime = 0 - cache.loadCount = 0 - cache.requireTime = 0 - global.moduleCache = cache - - originalLoad = Module::load - Module::load = -> - cache.loadCount++ - originalLoad.apply(this, arguments) - - originalRequire = Module::require - Module::require = -> - startTime = Date.now() - exports = originalRequire.apply(this, arguments) - cache.requireTime += Date.now() - startTime - exports - - originalFindPath = Module._findPath - Module._findPath = (request, paths) -> - cacheKey = JSON.stringify({request, paths}) - cache.findPathCount++ unless Module._pathCache[cacheKey] - - startTime = Date.now() - foundPath = originalFindPath.apply(global, arguments) - cache.findPathTime += Date.now() - startTime - foundPath - exports.create = (modulePath) -> fs = require 'fs-plus' diff --git a/src/task.coffee b/src/task.coffee index f3e56a507..9f115e869 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -71,7 +71,7 @@ class Task taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');" bootstrap = """ snapshotResult.setGlobals(global, process, global, {}, require) - CompileCache = snapshotResult.customRequire('../src/compile-cache.js') + CompileCache = #{compileCacheRequire} CompileCache.setCacheDirectory('#{compileCachePath}'); #{taskBootstrapRequire} """ diff --git a/static/index.js b/static/index.js index 8d5263c00..fa240fcdb 100644 --- a/static/index.js +++ b/static/index.js @@ -1,8 +1,10 @@ (function () { const electron = require('electron') const path = require('path') + const Module = require('module') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname + let CompileCache = null let blobStore = null let devMode = false let useSnapshot = false @@ -34,25 +36,28 @@ } } } else if (useSnapshot) { - Module.prototype.require = function (path) { - const absoluteFilePath = Module._resolveFilename(path, this, false) - const relativeFilePath = Path.relative(entryPointDirPath, absoluteFilePath) + Module.prototype.require = function (module) { + const absoluteFilePath = Module._resolveFilename(module, this, false) + const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) const cachedModule = snapshotResult.customRequire.cache[relativeFilePath] - return cachedModule ? cachedModule : Module._load(path, this, false) + return cachedModule ? cachedModule : Module._load(module, this, false) } snapshotResult.setGlobals(global, process, window, document, require) } - const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') - blobStore = FileSystemBlobStore.load( - path.join(process.env.ATOM_HOME, 'blob-store/') - ) + CompileCache = require('../src/compile-cache') + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - const NativeCompileCache = requireFunction('../src/native-compile-cache.js') - NativeCompileCache.setCacheStore(blobStore) - NativeCompileCache.setV8Version(process.versions.v8) - NativeCompileCache.install() + // const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') + // blobStore = FileSystemBlobStore.load( + // path.join(process.env.ATOM_HOME, 'blob-store/') + // ) + + // const NativeCompileCache = requireFunction('../src/native-compile-cache.js') + // NativeCompileCache.setCacheStore(blobStore) + // NativeCompileCache.setV8Version(process.versions.v8) + // NativeCompileCache.install() if (getWindowLoadSettings().profileStartup) { profileStartup(Date.now() - startTime) @@ -81,9 +86,6 @@ } function setupWindow () { - const CompileCache = requireFunction('../src/compile-cache.js') - CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - const ModuleCache = requireFunction('../src/module-cache.js') ModuleCache.register(getWindowLoadSettings()) From adb0e39166e839a287254e77d8b5eff67ea839e8 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 12:15:00 +0100 Subject: [PATCH 19/50] WIP --- script/lib/generate-startup-snapshot.js | 1 - script/lib/transpile-babel-paths.js | 1 - src/compile-cache.js | 190 ++++++++++++----------- src/initialize-application-window.coffee | 1 + src/main-process/start.js | 1 + src/task.coffee | 1 + static/index.js | 17 +- 7 files changed, 111 insertions(+), 101 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index f7951daac..479fbbbf0 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -28,7 +28,6 @@ module.exports = function (packagedAppPath) { (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) || relativePath == path.join('..', 'exports', 'atom.js') || relativePath == path.join('..', 'src', 'config-schema.js') || - relativePath == path.join('..', 'src', 'compile-cache.js') || relativePath == path.join('..', 'src', 'electron-shims.js') || relativePath == path.join('..', 'src', 'safe-clipboard.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || diff --git a/script/lib/transpile-babel-paths.js b/script/lib/transpile-babel-paths.js index 0a6a15f93..3c440a4bd 100644 --- a/script/lib/transpile-babel-paths.js +++ b/script/lib/transpile-babel-paths.js @@ -28,7 +28,6 @@ function getPathsToTranspile () { paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'benchmarks', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'exports', '**', '*.js'))) paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'src', '**', '*.js'))) - paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, '**', 'atom-select-list', 'src', 'select-list-view.js'))) for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) { paths = paths.concat(glob.sync( path.join(CONFIG.intermediateAppPath, 'node_modules', packageName, '**', '*.js'), diff --git a/src/compile-cache.js b/src/compile-cache.js index 8a4451d90..e15674a2e 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -7,6 +7,7 @@ var path = require('path') var fs = require('fs-plus') +var sourceMapSupport = require('source-map-support') var PackageTranspilationRegistry = require('./package-transpilation-registry') var CSON = null @@ -113,109 +114,112 @@ function writeCachedJavascript (relativeCachePath, code) { var INLINE_SOURCE_MAP_REGEXP = /\/\/[#@]\s*sourceMappingURL=([^'"\n]+)\s*$/mg -require('source-map-support').install({ - handleUncaughtExceptions: false, +exports.install = function (nodeRequire) { + sourceMapSupport.install({ + handleUncaughtExceptions: false, - // Most of this logic is the same as the default implementation in the - // source-map-support module, but we've overridden it to read the javascript - // code from our cache directory. - retrieveSourceMap: function (filePath) { - if (!cacheDirectory || !fs.isFileSync(filePath)) { - return null - } + // Most of this logic is the same as the default implementation in the + // source-map-support module, but we've overridden it to read the javascript + // code from our cache directory. + retrieveSourceMap: function (filePath) { + if (!cacheDirectory || !fs.isFileSync(filePath)) { + return null + } - try { - var sourceCode = fs.readFileSync(filePath, 'utf8') - } catch (error) { - console.warn('Error reading source file', error.stack) - return null - } + try { + var sourceCode = fs.readFileSync(filePath, 'utf8') + } catch (error) { + console.warn('Error reading source file', error.stack) + return null + } - var compiler = COMPILERS[path.extname(filePath)] - if (!compiler) compiler = COMPILERS['.js'] + var compiler = COMPILERS[path.extname(filePath)] + if (!compiler) compiler = COMPILERS['.js'] - try { - var fileData = readCachedJavascript(compiler.getCachePath(sourceCode, filePath)) - } catch (error) { - console.warn('Error reading compiled file', error.stack) - return null - } + try { + var fileData = readCachedJavascript(compiler.getCachePath(sourceCode, filePath)) + } catch (error) { + console.warn('Error reading compiled file', error.stack) + return null + } - if (fileData == null) { - return null - } + if (fileData == null) { + return null + } - var match, lastMatch - INLINE_SOURCE_MAP_REGEXP.lastIndex = 0 - while ((match = INLINE_SOURCE_MAP_REGEXP.exec(fileData))) { - lastMatch = match - } - if (lastMatch == null) { - return null - } + var match, lastMatch + INLINE_SOURCE_MAP_REGEXP.lastIndex = 0 + while ((match = INLINE_SOURCE_MAP_REGEXP.exec(fileData))) { + lastMatch = match + } + if (lastMatch == null) { + return null + } - var sourceMappingURL = lastMatch[1] - var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1) + var sourceMappingURL = lastMatch[1] + var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1) - try { - var sourceMap = JSON.parse(new Buffer(rawData, 'base64')) - } catch (error) { - console.warn('Error parsing source map', error.stack) - return null - } + try { + var sourceMap = JSON.parse(new Buffer(rawData, 'base64')) + } catch (error) { + console.warn('Error parsing source map', error.stack) + return null + } - return { - map: sourceMap, - url: null - } - } -}) - -var prepareStackTraceWithSourceMapping = Error.prepareStackTrace -var prepareStackTrace = prepareStackTraceWithSourceMapping - -function prepareStackTraceWithRawStackAssignment (error, frames) { - if (error.rawStack) { // avoid infinite recursion - return prepareStackTraceWithSourceMapping(error, frames) - } else { - error.rawStack = frames - return prepareStackTrace(error, frames) - } -} - -Error.stackTraceLimit = 30 - -Object.defineProperty(Error, 'prepareStackTrace', { - get: function () { - return prepareStackTraceWithRawStackAssignment - }, - - set: function (newValue) { - prepareStackTrace = newValue - process.nextTick(function () { - prepareStackTrace = prepareStackTraceWithSourceMapping - }) - } -}) - -Error.prototype.getRawStack = function () { // eslint-disable-line no-extend-native - // Access this.stack to ensure prepareStackTrace has been run on this error - // because it assigns this.rawStack as a side-effect - this.stack - return this.rawStack -} - -Object.keys(COMPILERS).forEach(function (extension) { - var compiler = COMPILERS[extension] - - Object.defineProperty(require.extensions, extension, { - enumerable: true, - writable: false, - value: function (module, filePath) { - var code = compileFileAtPath(compiler, filePath, extension) - return module._compile(code, filePath) + return { + map: sourceMap, + url: null + } } }) -}) + + var prepareStackTraceWithSourceMapping = Error.prepareStackTrace + var prepareStackTrace = prepareStackTraceWithSourceMapping + + function prepareStackTraceWithRawStackAssignment (error, frames) { + if (error.rawStack) { // avoid infinite recursion + return prepareStackTraceWithSourceMapping(error, frames) + } else { + error.rawStack = frames + return prepareStackTrace(error, frames) + } + } + + Error.stackTraceLimit = 30 + + Object.defineProperty(Error, 'prepareStackTrace', { + get: function () { + return prepareStackTraceWithRawStackAssignment + }, + + set: function (newValue) { + prepareStackTrace = newValue + process.nextTick(function () { + prepareStackTrace = prepareStackTraceWithSourceMapping + }) + } + }) + + Error.prototype.getRawStack = function () { // eslint-disable-line no-extend-native + // Access this.stack to ensure prepareStackTrace has been run on this error + // because it assigns this.rawStack as a side-effect + this.stack + return this.rawStack + } + + Object.keys(COMPILERS).forEach(function (extension) { + var compiler = COMPILERS[extension] + + Object.defineProperty(nodeRequire.extensions, extension, { + enumerable: true, + writable: false, + value: function (module, filePath) { + var code = compileFileAtPath(compiler, filePath, extension) + return module._compile(code, filePath) + } + }) + }) +} + exports.resetCacheStats() diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 507818998..13562fae2 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -24,6 +24,7 @@ require('deprecation-cop') require('dev-live-reload') require('encoding-selector') require('exception-reporting') +require('dalek') require('find-and-replace') require('fuzzy-finder') require('git-diff') diff --git a/src/main-process/start.js b/src/main-process/start.js index f54d263e0..368370939 100644 --- a/src/main-process/start.js +++ b/src/main-process/start.js @@ -83,4 +83,5 @@ function handleStartupEventWithSquirrel () { function setupCompileCache () { const CompileCache = require('../compile-cache') CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) + CompileCache.install(require) } diff --git a/src/task.coffee b/src/task.coffee index 9f115e869..182d9df88 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -73,6 +73,7 @@ class Task snapshotResult.setGlobals(global, process, global, {}, require) CompileCache = #{compileCacheRequire} CompileCache.setCacheDirectory('#{compileCachePath}'); + CompileCache.install(require) #{taskBootstrapRequire} """ bootstrap = bootstrap.replace(/\\/g, "\\\\") diff --git a/static/index.js b/static/index.js index fa240fcdb..4b7543dff 100644 --- a/static/index.js +++ b/static/index.js @@ -1,10 +1,10 @@ (function () { const electron = require('electron') const path = require('path') + const fs = require('fs-plus') const Module = require('module') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname - let CompileCache = null let blobStore = null let devMode = false let useSnapshot = false @@ -39,16 +39,17 @@ Module.prototype.require = function (module) { const absoluteFilePath = Module._resolveFilename(module, this, false) const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) - const cachedModule = snapshotResult.customRequire.cache[relativeFilePath] - return cachedModule ? cachedModule : Module._load(module, this, false) + let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] + if (!cachedModule) { + cachedModule = Module._load(module, this, false) + snapshotResult.customRequire.cache[relativeFilePath] = cachedModule + } + return cachedModule } snapshotResult.setGlobals(global, process, window, document, require) } - CompileCache = require('../src/compile-cache') - CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) - // const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') // blobStore = FileSystemBlobStore.load( // path.join(process.env.ATOM_HOME, 'blob-store/') @@ -86,6 +87,10 @@ } function setupWindow () { + const CompileCache = requireFunction('../src/compile-cache.js') + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) + CompileCache.install(require) + const ModuleCache = requireFunction('../src/module-cache.js') ModuleCache.register(getWindowLoadSettings()) From 66c7f2f83c23a3a491b3b4885fbc409ea2ee5dea Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 17:12:57 +0100 Subject: [PATCH 20/50] Provide snapshotResult.entryPointDirPath --- static/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/static/index.js b/static/index.js index 4b7543dff..2d660c844 100644 --- a/static/index.js +++ b/static/index.js @@ -48,6 +48,7 @@ } snapshotResult.setGlobals(global, process, window, document, require) + snapshotResult.entryPointDirPath = __dirname } // const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') From deb94f6f4aa414e9dad32c20e8dca38bc1c142cf Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 17:17:02 +0100 Subject: [PATCH 21/50] Fix dev mode --- static/index.js | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/static/index.js b/static/index.js index 2d660c844..c79055200 100644 --- a/static/index.js +++ b/static/index.js @@ -8,7 +8,6 @@ let blobStore = null let devMode = false let useSnapshot = false - let requireFunction = null window.onload = function () { try { @@ -24,7 +23,6 @@ setupAtomHome() devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep) useSnapshot = !devMode && typeof snapshotResult !== 'undefined' - requireFunction = useSnapshot ? snapshotResult.customRequire : require if (devMode) { const metadata = require('../package.json') @@ -51,16 +49,6 @@ snapshotResult.entryPointDirPath = __dirname } - // const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js') - // blobStore = FileSystemBlobStore.load( - // path.join(process.env.ATOM_HOME, 'blob-store/') - // ) - - // const NativeCompileCache = requireFunction('../src/native-compile-cache.js') - // NativeCompileCache.setCacheStore(blobStore) - // NativeCompileCache.setV8Version(process.versions.v8) - // NativeCompileCache.install() - if (getWindowLoadSettings().profileStartup) { profileStartup(Date.now() - startTime) } else { @@ -88,21 +76,21 @@ } function setupWindow () { - const CompileCache = requireFunction('../src/compile-cache.js') + const CompileCache = useSnapshot ? snapshotResult.customRequire('../src/compile-cache.js') : require('../src/compile-cache') CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) CompileCache.install(require) - const ModuleCache = requireFunction('../src/module-cache.js') + const ModuleCache = useSnapshot ? snapshotResult.customRequire('../src/module-cache.js') : require('../src/module-cache') ModuleCache.register(getWindowLoadSettings()) - const startCrashReporter = requireFunction('../src/crash-reporter-start.js') + const startCrashReporter = useSnapshot ? snapshotResult.customRequire('../src/crash-reporter-start.js') : require('../src/crash-reporter-start') startCrashReporter({_version: getWindowLoadSettings().appVersion}) - const CSON = requireFunction(useSnapshot ? '../node_modules/season/lib/cson.js' : 'season') + const CSON = useSnapshot ? snapshotResult.customRequire('../node_modules/season/lib/cson.js') : require('season') CSON.setCacheDir(path.join(CompileCache.getCacheDirectory(), 'cson')) const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) - const initialize = requireFunction(initScriptPath) + const initialize = useSnapshot ? snapshotResult.customRequire(initScriptPath) : require(initScriptPath) return initialize({blobStore: blobStore}).then(function () { electron.ipcRenderer.send('window-command', 'window:loaded') }) From e275570a4eeb160a8841fb63c7235fda835fa7a5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 17:20:49 +0100 Subject: [PATCH 22/50] 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') }) } From dcd9c48f63bce7351fa3218fa755a10fc2e48aba Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 28 Feb 2017 19:01:21 +0100 Subject: [PATCH 23/50] Use CompileCache `supportedExtensions` instead of `require.extensions` --- src/compile-cache.js | 2 +- src/package.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compile-cache.js b/src/compile-cache.js index e15674a2e..9b1966fc8 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -221,5 +221,5 @@ exports.install = function (nodeRequire) { }) } - +exports.supportedExtensions = Object.keys(COMPILERS) exports.resetCacheStats() diff --git a/src/package.coffee b/src/package.coffee index dea9c0e58..ed0f7aa87 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -503,7 +503,7 @@ class Package path.join(@path, @metadata.main) else path.join(@path, 'index') - @mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...]) + @mainModulePath = fs.resolveExtension(mainModulePath, ["", CompileCache.supportedExtensions...]) activationShouldBeDeferred: -> @hasActivationCommands() or @hasActivationHooks() From 9aae33a0f1db1f878e34573435fc158821c0d6f5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 1 Mar 2017 08:58:58 +0100 Subject: [PATCH 24/50] Use a new version of clear-cut that can be snapshotted --- package.json | 2 +- script/lib/generate-startup-snapshot.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index 01eedc2eb..13812c36d 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "cached-run-in-this-context": "0.4.1", "chai": "3.5.0", "chart.js": "^2.3.0", - "clear-cut": "^2.0.1", + "clear-cut": "^2.0.2", "coffee-script": "1.11.1", "color": "^0.7.3", "dedent": "^0.6.0", diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 479fbbbf0..cb8c4c231 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -35,9 +35,7 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'temp', 'lib', 'temp.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || - relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'helpers.js') || relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || - relativePath == path.join('..', 'node_modules', 'clear-cut', 'index.js') || relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'find-and-replace', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || From 70c82b1ffaeea203c8710567d3bb4f4c3ea8fc4a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 1 Mar 2017 17:57:33 +0100 Subject: [PATCH 25/50] Snapshot pathwatcher and fs-plus --- script/lib/generate-startup-snapshot.js | 12 ------------ static/index.js | 1 - 2 files changed, 13 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index cb8c4c231..3e2a56c38 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -30,7 +30,6 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'src', 'config-schema.js') || relativePath == path.join('..', 'src', 'electron-shims.js') || relativePath == path.join('..', 'src', 'safe-clipboard.js') || - relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'temp', 'lib', 'temp.js') || relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'tar', 'tar.js') || @@ -38,12 +37,8 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || - relativePath == path.join('..', 'node_modules', 'find-and-replace', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || - relativePath == path.join('..', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || relativePath == path.join('..', 'node_modules', 'debug', 'node.js') || - relativePath == path.join('..', 'node_modules', 'exception-reporting', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || - relativePath == path.join('..', 'node_modules', 'symbols-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') || relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || @@ -53,17 +48,13 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || relativePath == path.join('..', 'node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || - relativePath == path.join('..', 'node_modules', 'metrics', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || - relativePath == path.join('..', 'node_modules', 'notifications', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') || relativePath == path.join('..', 'node_modules', 'mime', 'mime.js') || relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') || - relativePath == path.join('..', 'node_modules', 'pathwatcher', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'request', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'htmlparser2', 'lib', 'index.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'request', 'index.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'cookie.js') || @@ -71,10 +62,7 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || relativePath == path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') || relativePath == path.join('..', 'node_modules', 'styleguide', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || - relativePath == path.join('..', 'node_modules', 'status-bar', 'node_modules', 'fs-plus', 'lib', 'fs-plus.js') || relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') || - relativePath == path.join('..', 'node_modules', 'tree-view', 'node_modules', 'pathwatcher', 'lib', 'main.js') || - relativePath == path.join('..', 'node_modules', 'text-buffer', 'node_modules', 'pathwatcher', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') ) diff --git a/static/index.js b/static/index.js index 0da1730f8..5e5ddc347 100644 --- a/static/index.js +++ b/static/index.js @@ -1,7 +1,6 @@ (function () { const electron = require('electron') const path = require('path') - const fs = require('fs-plus') const Module = require('module') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname From d73547242b3d5b0b15613e419bd69eeea82578c2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 2 Mar 2017 08:29:45 +0100 Subject: [PATCH 26/50] Run script/bootstrap during script/build --- script/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/build b/script/build index a5368768c..2b45e425d 100755 --- a/script/build +++ b/script/build @@ -4,7 +4,7 @@ // Run bootstrap first to ensure all the dependencies used later in this script // are installed. -// require('./bootstrap') +require('./bootstrap') // Needed so we can require src/module-cache.coffee during generateModuleCache require('coffee-script/register') From 8d46de418f2ad0022374300cab862c08eb563528 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 2 Mar 2017 09:11:54 +0100 Subject: [PATCH 27/50] Re-enable native module cache --- spec/file-system-blob-store-spec.coffee | 109 ++++++++++++++++++ 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/atom-environment.coffee | 7 +- src/file-system-blob-store.js | 138 +++++++++++++++++++++++ src/initialize-application-window.coffee | 5 +- src/initialize-test-window.coffee | 3 +- src/native-compile-cache.js | 116 +++++++++++++++++++ static/index.js | 11 +- 12 files changed, 492 insertions(+), 5 deletions(-) create mode 100644 spec/file-system-blob-store-spec.coffee create mode 100644 spec/fixtures/native-cache/file-1.js create mode 100644 spec/fixtures/native-cache/file-2.js create mode 100644 spec/fixtures/native-cache/file-3.js create mode 100644 spec/fixtures/native-cache/file-4.js create mode 100644 spec/native-compile-cache-spec.coffee create mode 100644 src/file-system-blob-store.js create 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 new file mode 100644 index 000000000..70e4d2b8d --- /dev/null +++ b/spec/file-system-blob-store-spec.coffee @@ -0,0 +1,109 @@ +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 in-memory and previously stored buffers, and deletes unused keys 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")).toBeUndefined() + 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.get("a", "invalidation-key-1") # prevent the key from being deleted on save + 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 new file mode 100644 index 000000000..ce195a18e --- /dev/null +++ b/spec/fixtures/native-cache/file-1.js @@ -0,0 +1 @@ +module.exports = function () { return 1; } diff --git a/spec/fixtures/native-cache/file-2.js b/spec/fixtures/native-cache/file-2.js new file mode 100644 index 000000000..e0cdf1485 --- /dev/null +++ b/spec/fixtures/native-cache/file-2.js @@ -0,0 +1 @@ +module.exports = function () { return 2; } diff --git a/spec/fixtures/native-cache/file-3.js b/spec/fixtures/native-cache/file-3.js new file mode 100644 index 000000000..36ca6e14a --- /dev/null +++ b/spec/fixtures/native-cache/file-3.js @@ -0,0 +1 @@ +module.exports = function () { return 3; } diff --git a/spec/fixtures/native-cache/file-4.js b/spec/fixtures/native-cache/file-4.js new file mode 100644 index 000000000..1b8fd4e15 --- /dev/null +++ b/spec/fixtures/native-cache/file-4.js @@ -0,0 +1 @@ +module.exports = function () { return "file-4" } diff --git a/spec/native-compile-cache-spec.coffee b/spec/native-compile-cache-spec.coffee new file mode 100644 index 000000000..1531deaf9 --- /dev/null +++ b/spec/native-compile-cache-spec.coffee @@ -0,0 +1,104 @@ +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/atom-environment.coffee b/src/atom-environment.coffee index dae45f7a2..2dfa736a2 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -131,7 +131,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params + {@applicationDelegate, @window, @document, @blobStore, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @unloaded = false @loadTime = null @@ -733,8 +733,13 @@ class AtomEnvironment extends Model @storeWindowBackground() @packages.deactivatePackages() + @saveBlobStoreSync() @unloaded = true + saveBlobStoreSync: -> + if @enablePersistence + @blobStore.save() + openInitialEmptyEditorIfNecessary: -> return unless @config.get('core.openEmptyEditorOnStart') if @getLoadSettings().initialPaths?.length is 0 and @workspace.getPaneItems().length is 0 diff --git a/src/file-system-blob-store.js b/src/file-system-blob-store.js new file mode 100644 index 000000000..828e23e94 --- /dev/null +++ b/src/file-system-blob-store.js @@ -0,0 +1,138 @@ +'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 = {} + this.usedKeys = new Set() + } + + 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)) { + this.usedKeys.add(key) + return this.getFromMemory(key) || this.getFromStorage(key) + } + } + + set (key, invalidationKey, buffer) { + this.usedKeys.add(key) + 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()) { + if (this.usedKeys.has(key)) { + dump(key, this.getFromMemory.bind(this)) + } + } + + for (let key of Object.keys(this.storedBlobMap)) { + if (!blobMap[key] && this.usedKeys.has(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 b855936e0..13562fae2 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -3,6 +3,7 @@ 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' @@ -54,7 +55,7 @@ require('whitespace') require('wrap-guide') # Like sands through the hourglass, so are the days of our lives. -module.exports = -> +module.exports = ({blobStore}) -> {updateProcessEnv} = require('./update-process-env') path = require 'path' require './window' @@ -75,7 +76,7 @@ module.exports = -> TextEditor.setClipboard(clipboard) window.atom = new AtomEnvironment({ - window, document, clipboard, + window, document, clipboard, blobStore, 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 3649fea94..794db3174 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 = -> +module.exports = ({blobStore}) -> startCrashReporter = require('./crash-reporter-start') {remote} = require 'electron' @@ -77,6 +77,7 @@ module.exports = -> 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 new file mode 100644 index 000000000..3f3d05991 --- /dev/null +++ b/src/native-compile-cache.js @@ -0,0 +1,116 @@ +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 5e5ddc347..2154f72b1 100644 --- a/static/index.js +++ b/static/index.js @@ -4,6 +4,7 @@ const Module = require('module') const getWindowLoadSettings = require('../src/get-window-load-settings') const entryPointDirPath = __dirname + let blobStore = null let useSnapshot = false window.onload = function () { @@ -46,6 +47,14 @@ snapshotResult.entryPointDirPath = __dirname } + const FileSystemBlobStore = useSnapshot ? snapshotResult.customRequire('../src/file-system-blob-store.js') : require('../src/file-system-blob-store') + blobStore = FileSystemBlobStore.load(path.join(process.env.ATOM_HOME, 'blob-store')) + + const NativeCompileCache = useSnapshot ? snapshotResult.customRequire('../src/native-compile-cache.js') : require('../src/native-compile-cache') + NativeCompileCache.setCacheStore(blobStore) + NativeCompileCache.setV8Version(process.versions.v8) + NativeCompileCache.install() + if (getWindowLoadSettings().profileStartup) { profileStartup(Date.now() - startTime) } else { @@ -88,7 +97,7 @@ const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) const initialize = useSnapshot ? snapshotResult.customRequire(initScriptPath) : require(initScriptPath) - return initialize().then(function () { + return initialize({blobStore: blobStore}).then(function () { electron.ipcRenderer.send('window-command', 'window:loaded') }) } From a9ada3535460567f924886a6b58fb970b6f2315e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 2 Mar 2017 09:29:07 +0100 Subject: [PATCH 28/50] Snapshot NativeCompileCache --- script/lib/generate-startup-snapshot.js | 1 + src/initialize-application-window.coffee | 1 + src/native-compile-cache.js | 18 ------------------ static/index.js | 4 ++++ 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 3e2a56c38..fea976b11 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -35,6 +35,7 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || + relativePath == path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') || relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || diff --git a/src/initialize-application-window.coffee b/src/initialize-application-window.coffee index 13562fae2..f0ea0ed12 100644 --- a/src/initialize-application-window.coffee +++ b/src/initialize-application-window.coffee @@ -4,6 +4,7 @@ Clipboard = require './clipboard' TextEditor = require './text-editor' TextEditorComponent = require './text-editor-component' FileSystemBlobStore = require './file-system-blob-store' +NativeCompileCache = require './native-compile-cache' CompileCache = require './compile-cache' ModuleCache = require './module-cache' diff --git a/src/native-compile-cache.js b/src/native-compile-cache.js index 3f3d05991..6a9f69053 100644 --- a/src/native-compile-cache.js +++ b/src/native-compile-cache.js @@ -84,25 +84,7 @@ class NativeCompileCache { } 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) } diff --git a/static/index.js b/static/index.js index 2154f72b1..f407778dc 100644 --- a/static/index.js +++ b/static/index.js @@ -1,4 +1,8 @@ (function () { + // Eagerly require cached-run-in-this-context to prevent a circular require + // when using `NativeCompileCache` for the first time. + require('cached-run-in-this-context') + const electron = require('electron') const path = require('path') const Module = require('module') From 5a8aa54167548b86c664623e845ae9cff861c11f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 2 Mar 2017 09:48:12 +0100 Subject: [PATCH 29/50] :arrow_up: electron-link --- script/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/package.json b/script/package.json index ed21ea906..56c656866 100644 --- a/script/package.json +++ b/script/package.json @@ -8,7 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", - "electron-link": "0.0.7", + "electron-link": "0.0.8", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", "fs-extra": "0.30.0", From 2f1fd15170c40522f981c5c8d4f7ac9bca5bffe7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 3 Mar 2017 11:21:29 +0100 Subject: [PATCH 30/50] Don't assign snapshotResult.entryPointDirPath ...because we can use `process.resourcesPath` or `atom.getLoadSettings()` in packages that need to resolve the absolute path at runtime. --- static/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/static/index.js b/static/index.js index f407778dc..7021568db 100644 --- a/static/index.js +++ b/static/index.js @@ -48,7 +48,6 @@ } snapshotResult.setGlobals(global, process, window, document, require) - snapshotResult.entryPointDirPath = __dirname } const FileSystemBlobStore = useSnapshot ? snapshotResult.customRequire('../src/file-system-blob-store.js') : require('../src/file-system-blob-store') From ebe725de4d27325c8fe5a7b9c5aedde77a1c5912 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 3 Mar 2017 16:57:15 +0100 Subject: [PATCH 31/50] Assign globals to snapshotResult only if present --- src/task.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/task.coffee b/src/task.coffee index 182d9df88..5c7b08b8a 100644 --- a/src/task.coffee +++ b/src/task.coffee @@ -70,7 +70,10 @@ class Task compileCachePath = require('./compile-cache').getCacheDirectory() taskBootstrapRequire = "require('#{require.resolve('./task-bootstrap')}');" bootstrap = """ - snapshotResult.setGlobals(global, process, global, {}, require) + if (typeof snapshotResult !== 'undefined') { + snapshotResult.setGlobals(global, process, global, {}, require) + } + CompileCache = #{compileCacheRequire} CompileCache.setCacheDirectory('#{compileCachePath}'); CompileCache.install(require) From 7fbe68e12e9332b46ebe552711550637f523b953 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:11:47 +0100 Subject: [PATCH 32/50] Exclude less from snapshot --- script/lib/generate-startup-snapshot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index fea976b11..f82630cf2 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -45,8 +45,9 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'internal.js') || relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'index.js') || - relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'index.js') || + relativePath == path.join('..', 'node_modules', 'less', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || + relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || relativePath == path.join('..', 'node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') || From f2ea38afbab54a52d92295d3cb10d4fc605f0203 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:12:14 +0100 Subject: [PATCH 33/50] Add electron-mksnapshot and use the downloaded bin to generate snapshots --- script/lib/check-chromedriver-version.js | 11 +++++++++++ script/lib/generate-startup-snapshot.js | 2 +- script/package.json | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/script/lib/check-chromedriver-version.js b/script/lib/check-chromedriver-version.js index 90bc220e5..6fd313fc7 100644 --- a/script/lib/check-chromedriver-version.js +++ b/script/lib/check-chromedriver-version.js @@ -7,16 +7,27 @@ const semver = require('semver') module.exports = function () { // Chromedriver should be specified as ~x.y where x and y match Electron major/minor const chromedriverVer = buildMetadata.dependencies['electron-chromedriver'] + const mksnapshotVer = buildMetadata.dependencies['electron-mksnapshot'] // Always use tilde on electron-chromedriver so that it can pick up the best patch vesion if (!chromedriverVer.startsWith('~')) { throw new Error(`electron-chromedriver version in script/package.json should start with a tilde to match latest patch version.`) } + if (!mksnapshotVer.startsWith('~')) { + throw new Error(`electron-mksnapshot version in script/package.json should start with a tilde to match latest patch version.`) + } + const electronVer = CONFIG.appMetadata.electronVersion if (!semver.satisfies(electronVer, chromedriverVer)) { throw new Error(`electron-chromedriver ${chromedriverVer} incompatible with electron ${electronVer}.\n` + 'Did you upgrade electron in package.json and forget to upgrade electron-chromedriver in ' + `script/package.json to '~${semver.major(electronVer)}.${semver.minor(electronVer)}' ?`) } + + if (!semver.satisfies(electronVer, mksnapshotVer)) { + throw new Error(`electron-mksnapshot ${mksnapshotVer} incompatible with electron ${electronVer}.\n` + + 'Did you upgrade electron in package.json and forget to upgrade electron-mksnapshot in ' + + `script/package.json to '~${semver.major(electronVer)}.${semver.minor(electronVer)}' ?`) + } } diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index f82630cf2..457956475 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -79,7 +79,7 @@ module.exports = function (packagedAppPath) { const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin') console.log(`Generating startup blob at "${generatedStartupBlobPath}"`) childProcess.execFileSync( - path.join(CONFIG.repositoryRootPath, 'electron', 'mksnapshot', `mksnapshot`), + path.join(CONFIG.repositoryRootPath, 'script', 'node_modules', 'electron-mksnapshot', 'bin', 'mksnapshot'), [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath] ) diff --git a/script/package.json b/script/package.json index 56c656866..37950b49d 100644 --- a/script/package.json +++ b/script/package.json @@ -9,6 +9,7 @@ "donna": "1.0.13", "electron-chromedriver": "~1.3", "electron-link": "0.0.8", + "electron-mksnapshot": "~1.3", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", "fs-extra": "0.30.0", From 889f480c354e225237155531952ee089dc879254 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:20:52 +0100 Subject: [PATCH 34/50] Delete obsolete asar code --- script/lib/package-application.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/script/lib/package-application.js b/script/lib/package-application.js index 8c4127b4f..5e01e5543 100644 --- a/script/lib/package-application.js +++ b/script/lib/package-application.js @@ -95,20 +95,6 @@ function chmodNodeFiles (packagedAppPath) { childProcess.execSync(`find "${packagedAppPath}" -type f -name *.node -exec chmod a-x {} \\;`) } -function buildAsarUnpackGlobExpression () { - const unpack = [ - '*.node', - 'ctags-config', - 'ctags-darwin', - 'ctags-linux', - 'ctags-win32.exe', - path.join('**', 'node_modules', 'spellchecker', '**'), - path.join('**', 'resources', 'atom.png') - ] - - return `{${unpack.join(',')}}` -} - function getAppName () { if (process.platform === 'darwin') { return CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom' From f05e882911e2e5e6d20e9339fca03148ca36a59e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:21:12 +0100 Subject: [PATCH 35/50] Copy snapshot in the appropriate location on Linux and Windows --- script/lib/generate-startup-snapshot.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 457956475..6a349eeb4 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -83,10 +83,13 @@ module.exports = function (packagedAppPath) { [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath] ) - const startupBlobDestinationPath = path.join( - packagedAppPath, - 'Contents', 'Frameworks', 'Electron Framework.framework', 'Resources', 'snapshot_blob.bin' - ) + let startupBlobDestinationPath + if (process.platform === 'darwin') { + startupBlobDestinationPath = `${packagedAppPath}/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin` + } else { + startupBlobDestinationPath = path.join(packagedAppPath, 'snapshot_blob.bin') + } + console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`) fs.unlinkSync(startupBlobDestinationPath) fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath) From f0e7290b8c73db1d66de36f6bb7795a64ec69d4f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:36:33 +0100 Subject: [PATCH 36/50] Delete unnecessarily excluded modules from snapshot generator --- script/lib/generate-startup-snapshot.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/script/lib/generate-startup-snapshot.js b/script/lib/generate-startup-snapshot.js index 6a349eeb4..0021cf1ab 100644 --- a/script/lib/generate-startup-snapshot.js +++ b/script/lib/generate-startup-snapshot.js @@ -23,16 +23,13 @@ module.exports = function (packagedAppPath) { const relativePath = path.relative(baseDirPath, modulePath) return ( - modulePath.endsWith('.node') || modulePath === 'buffer-offset-index' || + modulePath.endsWith('.node') || coreModules.has(modulePath) || (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) || relativePath == path.join('..', 'exports', 'atom.js') || relativePath == path.join('..', 'src', 'config-schema.js') || relativePath == path.join('..', 'src', 'electron-shims.js') || relativePath == path.join('..', 'src', 'safe-clipboard.js') || - relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') || - relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'temp', 'lib', 'temp.js') || - relativePath == path.join('..', 'node_modules', 'archive-view', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') || relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') || relativePath == path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') || @@ -43,27 +40,19 @@ module.exports = function (packagedAppPath) { relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') || relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') || relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') || - relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'internal.js') || relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') || relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') || relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') || - relativePath == path.join('..', 'node_modules', 'marker-index', 'dist', 'native', 'marker-index.js') || relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') || - relativePath == path.join('..', 'node_modules', 'mime', 'mime.js') || relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') || relativePath == path.join('..', 'node_modules', 'request', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') || relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') || relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'htmlparser2', 'lib', 'index.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'request', 'index.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'cookie.js') || - relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'tough-cookie', 'lib', 'memstore.js') || relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') || relativePath == path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') || - relativePath == path.join('..', 'node_modules', 'styleguide', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') || relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') || relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') || relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') From a403d817ba39e85372ec5af4ebd783c3911dece4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 14:48:53 +0100 Subject: [PATCH 37/50] Put back source map generation for babel files --- static/babelrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/static/babelrc.json b/static/babelrc.json index 5d887251a..11474dd8d 100644 --- a/static/babelrc.json +++ b/static/babelrc.json @@ -1,4 +1,5 @@ { + "sourceMap": "inline", "plugins": [ ["add-module-exports", {}], ["transform-async-to-generator", {}], From 76ae6b29b3c32207fa60cd8c217b0f74f5e25c3d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 6 Mar 2017 19:58:03 +0100 Subject: [PATCH 38/50] :arrow_up: electron-link to handle cyclic requires correctly --- script/package.json | 2 +- static/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/package.json b/script/package.json index 37950b49d..c8106cc4d 100644 --- a/script/package.json +++ b/script/package.json @@ -8,7 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", - "electron-link": "0.0.8", + "electron-link": "0.0.10", "electron-mksnapshot": "~1.3", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", diff --git a/static/index.js b/static/index.js index 7021568db..70ef65d91 100644 --- a/static/index.js +++ b/static/index.js @@ -41,10 +41,10 @@ const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] if (!cachedModule) { - cachedModule = Module._load(module, this, false) + cachedModule = {exports: Module._load(module, this, false)} snapshotResult.customRequire.cache[relativeFilePath] = cachedModule } - return cachedModule + return cachedModule.exports } snapshotResult.setGlobals(global, process, window, document, require) From e0d65bbcae2461c1fd1c8df6f7eb110e666fade9 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 09:04:49 +0100 Subject: [PATCH 39/50] :arrow_up: apm --- apm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apm/package.json b/apm/package.json index e57d07aee..5e3dcb1e0 100644 --- a/apm/package.json +++ b/apm/package.json @@ -6,6 +6,6 @@ "url": "https://github.com/atom/atom.git" }, "dependencies": { - "atom-package-manager": "1.16.1" + "atom-package-manager": "1.17.0" } } From 6aacd3d76e314d6ebc0780644843bbddd5cbc851 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 09:25:20 +0100 Subject: [PATCH 40/50] Copy atom.png from the appropriate location on Linux --- script/lib/create-debian-package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/create-debian-package.js b/script/lib/create-debian-package.js index 03196816d..fd3e07b92 100644 --- a/script/lib/create-debian-package.js +++ b/script/lib/create-debian-package.js @@ -92,7 +92,7 @@ module.exports = function (packagedAppPath) { console.log(`Copying icon into "${debianPackageIconsDirPath}"`) fs.copySync( - path.join(packagedAppPath, 'resources', 'app.asar.unpacked', 'resources', 'atom.png'), + path.join(packagedAppPath, 'resources', 'app', 'resources', 'atom.png'), path.join(debianPackageIconsDirPath, `${atomExecutableName}.png`) ) From 6ac01d278137b2d50127decb5889e9bb466d6d00 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 09:39:14 +0100 Subject: [PATCH 41/50] Cache snapshot cache on CIs --- .travis.yml | 1 + appveyor.yml | 1 + circle.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 06416e8e0..6c3f25c49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ cache: - apm/node_modules - script/node_modules - ~/.atom/compile-cache + - ~/.atom/snapshot-cache notifications: email: diff --git a/appveyor.yml b/appveyor.yml index 3d8c0b274..e94e75441 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -52,3 +52,4 @@ cache: - '%APPVEYOR_BUILD_FOLDER%\electron' - '%USERPROFILE%\.atom\.apm' - '%USERPROFILE%\.atom\compile-cache' + - '%USERPROFILE%\.atom\snapshot-cache' diff --git a/circle.yml b/circle.yml index c264754d4..5890c45e9 100644 --- a/circle.yml +++ b/circle.yml @@ -29,6 +29,7 @@ dependencies: - script/node_modules - node_modules - ~/.atom/compile-cache + - ~/.atom/snapshot-cache test: override: From 3d40f55747fd905a61393d2630377e7eead4fd69 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 10:00:09 +0100 Subject: [PATCH 42/50] Fix lint errors --- src/main-process/main.js | 2 +- src/native-compile-cache.js | 1 - static/index.js | 20 ++++++++++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main-process/main.js b/src/main-process/main.js index 0614f19d2..d63de0677 100644 --- a/src/main-process/main.js +++ b/src/main-process/main.js @@ -1,5 +1,5 @@ if (typeof snapshotResult !== 'undefined') { - snapshotResult.setGlobals(global, process, global, {}, require) + snapshotResult.setGlobals(global, process, global, {}, require) // eslint-disable-line no-undef } const startTime = Date.now() diff --git a/src/native-compile-cache.js b/src/native-compile-cache.js index 6a9f69053..b1867ff55 100644 --- a/src/native-compile-cache.js +++ b/src/native-compile-cache.js @@ -36,7 +36,6 @@ class NativeCompileCache { 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. diff --git a/static/index.js b/static/index.js index 70ef65d91..f7d2d4c2f 100644 --- a/static/index.js +++ b/static/index.js @@ -39,21 +39,21 @@ Module.prototype.require = function (module) { const absoluteFilePath = Module._resolveFilename(module, this, false) const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) - let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] + let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] // eslint-disable-line no-undef if (!cachedModule) { cachedModule = {exports: Module._load(module, this, false)} - snapshotResult.customRequire.cache[relativeFilePath] = cachedModule + snapshotResult.customRequire.cache[relativeFilePath] = cachedModule // eslint-disable-line no-undef } return cachedModule.exports } - snapshotResult.setGlobals(global, process, window, document, require) + snapshotResult.setGlobals(global, process, window, document, require) // eslint-disable-line no-undef } - const FileSystemBlobStore = useSnapshot ? snapshotResult.customRequire('../src/file-system-blob-store.js') : require('../src/file-system-blob-store') + const FileSystemBlobStore = useSnapshot ? snapshotResult.customRequire('../src/file-system-blob-store.js') : require('../src/file-system-blob-store') // eslint-disable-line no-undef blobStore = FileSystemBlobStore.load(path.join(process.env.ATOM_HOME, 'blob-store')) - const NativeCompileCache = useSnapshot ? snapshotResult.customRequire('../src/native-compile-cache.js') : require('../src/native-compile-cache') + const NativeCompileCache = useSnapshot ? snapshotResult.customRequire('../src/native-compile-cache.js') : require('../src/native-compile-cache') // eslint-disable-line no-undef NativeCompileCache.setCacheStore(blobStore) NativeCompileCache.setV8Version(process.versions.v8) NativeCompileCache.install() @@ -85,21 +85,21 @@ } function setupWindow () { - const CompileCache = useSnapshot ? snapshotResult.customRequire('../src/compile-cache.js') : require('../src/compile-cache') + const CompileCache = useSnapshot ? snapshotResult.customRequire('../src/compile-cache.js') : require('../src/compile-cache') // eslint-disable-line no-undef CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) CompileCache.install(require) - const ModuleCache = useSnapshot ? snapshotResult.customRequire('../src/module-cache.js') : require('../src/module-cache') + const ModuleCache = useSnapshot ? snapshotResult.customRequire('../src/module-cache.js') : require('../src/module-cache') // eslint-disable-line no-undef ModuleCache.register(getWindowLoadSettings()) - const startCrashReporter = useSnapshot ? snapshotResult.customRequire('../src/crash-reporter-start.js') : require('../src/crash-reporter-start') + const startCrashReporter = useSnapshot ? snapshotResult.customRequire('../src/crash-reporter-start.js') : require('../src/crash-reporter-start') // eslint-disable-line no-undef startCrashReporter({_version: getWindowLoadSettings().appVersion}) - const CSON = useSnapshot ? snapshotResult.customRequire('../node_modules/season/lib/cson.js') : require('season') + const CSON = useSnapshot ? snapshotResult.customRequire('../node_modules/season/lib/cson.js') : require('season') // eslint-disable-line no-undef CSON.setCacheDir(path.join(CompileCache.getCacheDirectory(), 'cson')) const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript) - const initialize = useSnapshot ? snapshotResult.customRequire(initScriptPath) : require(initScriptPath) + const initialize = useSnapshot ? snapshotResult.customRequire(initScriptPath) : require(initScriptPath) // eslint-disable-line no-undef return initialize({blobStore: blobStore}).then(function () { electron.ipcRenderer.send('window-command', 'window:loaded') }) From 1d774ea20a47f8531effa218cf216e1e9b599e70 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 11:18:21 +0100 Subject: [PATCH 43/50] :arrow_up: electron-link for Windows support --- script/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/package.json b/script/package.json index dd31befc7..4de509dca 100644 --- a/script/package.json +++ b/script/package.json @@ -8,7 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", - "electron-link": "0.0.10", + "electron-link": "0.0.13", "electron-mksnapshot": "~1.3", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", From bfac08ab3f9a826b82ae57a5b34ee817a0f84162 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 12:02:41 +0100 Subject: [PATCH 44/50] :arrow_up: electron-link to handle backslashes on Windows correctly --- script/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/package.json b/script/package.json index 4de509dca..b87e794ea 100644 --- a/script/package.json +++ b/script/package.json @@ -8,7 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", - "electron-link": "0.0.13", + "electron-link": "0.0.17", "electron-mksnapshot": "~1.3", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", From b228d2de4f5644a10647afd49a336b4510d6ec06 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 10 Mar 2017 15:04:13 +0100 Subject: [PATCH 45/50] :arrow_up: electron-link --- script/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/package.json b/script/package.json index b87e794ea..9441213ac 100644 --- a/script/package.json +++ b/script/package.json @@ -8,7 +8,7 @@ "csslint": "1.0.2", "donna": "1.0.13", "electron-chromedriver": "~1.3", - "electron-link": "0.0.17", + "electron-link": "0.0.18", "electron-mksnapshot": "~1.3", "electron-packager": "7.3.0", "electron-winstaller": "2.5.1", From 0d29004723c478ee2acaa8475dedf8f833819d02 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 13 Mar 2017 19:11:53 +0100 Subject: [PATCH 46/50] Speed up FileSystemBlobStore.load by not storing invalidation keys This was unneeded because we can simply compute the cache key by concatenating the v8 version and the file's contents. --- spec/file-system-blob-store-spec.coffee | 84 ++++++++++++------------- spec/native-compile-cache-spec.coffee | 25 +++----- src/file-system-blob-store.js | 21 ++----- src/native-compile-cache.js | 9 ++- 4 files changed, 58 insertions(+), 81 deletions(-) diff --git a/spec/file-system-blob-store-spec.coffee b/spec/file-system-blob-store-spec.coffee index 70e4d2b8d..ff1c81eb6 100644 --- a/spec/file-system-blob-store-spec.coffee +++ b/spec/file-system-blob-store-spec.coffee @@ -14,79 +14,75 @@ describe "FileSystemBlobStore", -> 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() + expect(blobStore.get("foo")).toBeUndefined() + expect(blobStore.get("bar")).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")) + blobStore.set("foo", new Buffer("foo")) + blobStore.set("bar", 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")).toEqual(new Buffer("foo")) + expect(blobStore.get("bar")).toEqual(new Buffer("bar")) - expect(blobStore.get("foo", "unexisting-key")).toBeUndefined() - expect(blobStore.get("bar", "unexisting-key")).toBeUndefined() + expect(blobStore.get("baz")).toBeUndefined() + expect(blobStore.get("qux")).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.set("foo", new Buffer("foo")) + blobStore.set("bar", 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() + expect(blobStore.get("foo")).toEqual(new Buffer("foo")) + expect(blobStore.get("bar")).toEqual(new Buffer("bar")) + expect(blobStore.get("baz")).toBeUndefined() + expect(blobStore.get("qux")).toBeUndefined() - blobStore.set("foo", "new-key", new Buffer("changed")) + blobStore.set("foo", new Buffer("changed")) - expect(blobStore.get("foo", "new-key")).toEqual(new Buffer("changed")) - expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined() + expect(blobStore.get("foo")).toEqual(new Buffer("changed")) it "persists in-memory and previously stored buffers, and deletes unused keys when saved", -> - blobStore.set("foo", "invalidation-key-1", new Buffer("foo")) - blobStore.set("bar", "invalidation-key-2", new Buffer("bar")) + blobStore.set("foo", new Buffer("foo")) + blobStore.set("bar", 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.set("bar", new Buffer("changed")) + blobStore.set("qux", new Buffer("qux")) blobStore.save() blobStore = FileSystemBlobStore.load(storageDirectory) - expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined() - 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() + expect(blobStore.get("foo")).toBeUndefined() + expect(blobStore.get("bar")).toEqual(new Buffer("changed")) + expect(blobStore.get("qux")).toEqual(new Buffer("qux")) 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.set("a", new Buffer("a")) + blobStore.set("b", new Buffer("b")) blobStore.save() blobStore = FileSystemBlobStore.load(storageDirectory) - blobStore.get("a", "invalidation-key-1") # prevent the key from being deleted on save - blobStore.set("b", "invalidation-key-3", new Buffer("b")) - blobStore.set("c", "invalidation-key-4", new Buffer("c")) + blobStore.get("a") # prevent the key from being deleted on save + blobStore.set("b", new Buffer("b")) + blobStore.set("c", 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() + expect(blobStore.get("a")).toEqual(new Buffer("a")) + expect(blobStore.get("b")).toBeUndefined() + expect(blobStore.get("b")).toBeUndefined() + expect(blobStore.get("c")).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.set("a", new Buffer("a")) + blobStore.set("b", new Buffer("b")) blobStore.save() # Simulate corruption @@ -96,14 +92,14 @@ describe "FileSystemBlobStore", -> blobStore = FileSystemBlobStore.load(storageDirectory) - expect(blobStore.get("a", "invalidation-key-1")).toBeUndefined() - expect(blobStore.get("b", "invalidation-key-2")).toBeUndefined() + expect(blobStore.get("a")).toBeUndefined() + expect(blobStore.get("b")).toBeUndefined() - blobStore.set("a", "invalidation-key-1", new Buffer("x")) - blobStore.set("b", "invalidation-key-2", new Buffer("y")) + blobStore.set("a", new Buffer("x")) + blobStore.set("b", 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")) + expect(blobStore.get("a")).toEqual(new Buffer("x")) + expect(blobStore.get("b")).toEqual(new Buffer("y")) diff --git a/spec/native-compile-cache-spec.coffee b/spec/native-compile-cache-spec.coffee index 1531deaf9..a43cbe815 100644 --- a/spec/native-compile-cache-spec.coffee +++ b/spec/native-compile-cache-spec.coffee @@ -9,16 +9,18 @@ describe "NativeCompileCache", -> 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) -> + + fakeCacheStore.has.andCallFake (cacheKey) -> + fakeCacheStore.get(cacheKey)? + + fakeCacheStore.get.andCallFake (cacheKey) -> 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}) + + fakeCacheStore.set.andCallFake (cacheKey, cacheBuffer) -> + cachedFiles.push({cacheKey, cacheBuffer}) nativeCompileCache.setCacheStore(fakeCacheStore) nativeCompileCache.setV8Version("a-v8-version") @@ -29,13 +31,10 @@ describe "NativeCompileCache", -> 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) @@ -51,7 +50,6 @@ describe "NativeCompileCache", -> 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") @@ -61,8 +59,6 @@ describe "NativeCompileCache", -> 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) @@ -79,7 +75,6 @@ describe "NativeCompileCache", -> 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") @@ -89,8 +84,6 @@ describe "NativeCompileCache", -> 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) @@ -100,5 +93,5 @@ describe "NativeCompileCache", -> fn3 = require('./fixtures/native-cache/file-3') - expect(fakeCacheStore.delete).toHaveBeenCalledWith(require.resolve('./fixtures/native-cache/file-3')) + expect(fakeCacheStore.delete).toHaveBeenCalled() expect(fn3()).toBe(3) diff --git a/src/file-system-blob-store.js b/src/file-system-blob-store.js index 828e23e94..67a959735 100644 --- a/src/file-system-blob-store.js +++ b/src/file-system-blob-store.js @@ -14,14 +14,12 @@ class FileSystemBlobStore { 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 = {} this.usedKeys = new Set() @@ -34,14 +32,10 @@ class FileSystemBlobStore { 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() } @@ -51,7 +45,6 @@ class FileSystemBlobStore { 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 { @@ -60,7 +53,6 @@ class FileSystemBlobStore { 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') { @@ -73,22 +65,19 @@ class FileSystemBlobStore { } } - has (key, invalidationKey) { - let containsKey = this.inMemoryBlobs.has(key) || this.storedBlobMap.hasOwnProperty(key) - let isValid = this.invalidationKeys[key] === invalidationKey - return containsKey && isValid + has (key) { + return this.inMemoryBlobs.has(key) || this.storedBlobMap.hasOwnProperty(key) } - get (key, invalidationKey) { - if (this.has(key, invalidationKey)) { + get (key) { + if (this.has(key)) { this.usedKeys.add(key) return this.getFromMemory(key) || this.getFromStorage(key) } } - set (key, invalidationKey, buffer) { + set (key, buffer) { this.usedKeys.add(key) - this.invalidationKeys[key] = invalidationKey return this.inMemoryBlobs.set(key, buffer) } diff --git a/src/native-compile-cache.js b/src/native-compile-cache.js index b1867ff55..09a62b186 100644 --- a/src/native-compile-cache.js +++ b/src/native-compile-cache.js @@ -60,11 +60,10 @@ class NativeCompileCache { // create wrapper function let wrapper = Module.wrap(content) - let cacheKey = filename - let invalidationKey = computeHash(wrapper + self.v8Version) + let cacheKey = computeHash(wrapper + self.v8Version) let compiledWrapper = null - if (self.cacheStore.has(cacheKey, invalidationKey)) { - let buffer = self.cacheStore.get(cacheKey, invalidationKey) + if (self.cacheStore.has(cacheKey)) { + let buffer = self.cacheStore.get(cacheKey) let compilationResult = cachedVm.runInThisContextCached(wrapper, filename, buffer) compiledWrapper = compilationResult.result if (compilationResult.wasRejected) { @@ -79,7 +78,7 @@ class NativeCompileCache { throw err } if (compilationResult.cacheBuffer) { - self.cacheStore.set(cacheKey, invalidationKey, compilationResult.cacheBuffer) + self.cacheStore.set(cacheKey, compilationResult.cacheBuffer) } compiledWrapper = compilationResult.result } From 09b9e57cb4ab4f2fb58ad17f52f3149bbed7cb28 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 14 Mar 2017 11:57:26 -0700 Subject: [PATCH 47/50] :arrow_up: Upgrade to Electron 1.3.14 with snapshot patch --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f972b4890..71ce9bb07 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "https://github.com/atom/atom/issues" }, "license": "MIT", - "electronVersion": "1.3.13", + "electronVersion": "1.3.14", "dependencies": { "async": "0.2.6", "atom-keymap": "8.0.2", From 7caeb3d8529f6e0e29bebf1c29297d660825eb9a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 15 Mar 2017 09:49:05 +0100 Subject: [PATCH 48/50] Clear compile-cache on AppVeyor --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index e94e75441..7c243fec9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,5 +51,4 @@ cache: - '%APPVEYOR_BUILD_FOLDER%\node_modules' - '%APPVEYOR_BUILD_FOLDER%\electron' - '%USERPROFILE%\.atom\.apm' - - '%USERPROFILE%\.atom\compile-cache' - '%USERPROFILE%\.atom\snapshot-cache' From d95a5f1d3c94463b3e9b0d491f52572672daf828 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 15 Mar 2017 10:38:13 +0100 Subject: [PATCH 49/50] Revert "Clear compile-cache on AppVeyor" This reverts commit 7caeb3d8529f6e0e29bebf1c29297d660825eb9a. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 7c243fec9..e94e75441 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -51,4 +51,5 @@ cache: - '%APPVEYOR_BUILD_FOLDER%\node_modules' - '%APPVEYOR_BUILD_FOLDER%\electron' - '%USERPROFILE%\.atom\.apm' + - '%USERPROFILE%\.atom\compile-cache' - '%USERPROFILE%\.atom\snapshot-cache' From b2983f63bab0b74988a2a6bc58157a8c9d616d8f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 15 Mar 2017 13:26:29 +0100 Subject: [PATCH 50/50] Replace backward with forward slashes when requiring files on Windows --- static/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/static/index.js b/static/index.js index f7d2d4c2f..6297eb5ef 100644 --- a/static/index.js +++ b/static/index.js @@ -38,7 +38,10 @@ } else if (useSnapshot) { Module.prototype.require = function (module) { const absoluteFilePath = Module._resolveFilename(module, this, false) - const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) + let relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath) + if (process.platform === 'win32') { + relativeFilePath = relativeFilePath.replace(/\\/g, '/') + } let cachedModule = snapshotResult.customRequire.cache[relativeFilePath] // eslint-disable-line no-undef if (!cachedModule) { cachedModule = {exports: Module._load(module, this, false)}