Merge pull request #14080 from atom/as-preload-packages

Packages preloading
This commit is contained in:
Antonio Scandurra 2017-04-03 09:59:34 +02:00 committed by GitHub
commit cef72fd66f
12 changed files with 277 additions and 111 deletions

View File

@ -110,7 +110,7 @@
"grammar-selector": "0.49.4",
"image-view": "0.61.2",
"incompatible-packages": "0.27.2",
"keybinding-resolver": "0.37.0",
"keybinding-resolver": "0.38.0",
"line-ending-selector": "0.6.3",
"link": "0.31.3",
"markdown-preview": "0.159.10",

View File

@ -48,10 +48,18 @@ function buildBundledPackagesMetadata () {
}
}
const packageNewMetadata = {metadata: packageMetadata, keymaps: {}, menus: {}}
const packageNewMetadata = {metadata: packageMetadata, keymaps: {}, menus: {}, grammarPaths: [], settings: {}}
packageNewMetadata.rootDirPath = path.relative(CONFIG.intermediateAppPath, packagePath)
if (packageMetadata.main) {
const mainPath = require.resolve(path.resolve(packagePath, packageMetadata.main))
packageNewMetadata.main = path.relative(CONFIG.intermediateAppPath, mainPath)
packageNewMetadata.main = path.relative(path.join(CONFIG.intermediateAppPath, 'static'), mainPath)
// Convert backward slashes to forward slashes in order to allow package
// main modules to be required from the snapshot. This is because we use
// forward slashes to cache the sources in the snapshot, so we need to use
// them here as well.
packageNewMetadata.main = packageNewMetadata.main.replace(/\\/g, '/')
}
const packageKeymapsPath = path.join(packagePath, 'keymaps')
@ -76,6 +84,18 @@ function buildBundledPackagesMetadata () {
}
}
const packageGrammarsPath = path.join(packagePath, 'grammars')
for (let packageGrammarPath of fs.listSync(packageGrammarsPath, ['json', 'cson'])) {
const relativePath = path.relative(CONFIG.intermediateAppPath, packageGrammarPath)
packageNewMetadata.grammarPaths.push(relativePath)
}
const packageSettingsPath = path.join(packagePath, 'settings')
for (let packageSettingPath of fs.listSync(packageSettingsPath, ['json', 'cson'])) {
const relativePath = path.relative(CONFIG.intermediateAppPath, packageSettingPath)
packageNewMetadata.settings[relativePath] = CSON.readFileSync(packageSettingPath)
}
const packageStyleSheetsPath = path.join(packagePath, 'styles')
let styleSheets = null
if (packageMetadata.mainStyleSheet) {

View File

@ -9,7 +9,7 @@
"csslint": "1.0.2",
"donna": "1.0.13",
"electron-chromedriver": "~1.3",
"electron-link": "0.0.20",
"electron-link": "0.0.21",
"electron-mksnapshot": "~1.3",
"electron-packager": "7.3.0",
"electron-winstaller": "2.5.1",

View File

@ -36,7 +36,7 @@ describe "PackageManager", ->
describe "::loadPackages()", ->
beforeEach ->
spyOn(atom.packages, 'loadPackage')
spyOn(atom.packages, 'loadAvailablePackage')
afterEach ->
atom.packages.deactivatePackages()

View File

@ -11,8 +11,7 @@ describe "Package", ->
keymapManager: atom.keymaps, commandRegistry: atom.command,
grammarRegistry: atom.grammars, themeManager: atom.themes,
menuManager: atom.menu, contextMenuManager: atom.contextMenu,
deserializerManager: atom.deserializers, viewRegistry: atom.views,
devMode: false
deserializerManager: atom.deserializers, viewRegistry: atom.views
)
buildPackage = (packagePath) -> build(Package, packagePath)
@ -21,8 +20,12 @@ describe "Package", ->
describe "when the package contains incompatible native modules", ->
beforeEach ->
atom.packages.devMode = false
mockLocalStorage()
afterEach ->
atom.packages.devMode = true
it "does not activate it", ->
packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-incompatible-native-module')
pack = buildPackage(packagePath)
@ -64,8 +67,12 @@ describe "Package", ->
describe "::rebuild()", ->
beforeEach ->
atom.packages.devMode = false
mockLocalStorage()
afterEach ->
atom.packages.devMode = true
it "returns a promise resolving to the results of `apm rebuild`", ->
packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-index')
pack = buildPackage(packagePath)

View File

@ -258,6 +258,9 @@ class AtomEnvironment extends Model
@history.initialize(@window.localStorage)
@disposables.add @applicationDelegate.onDidChangeHistoryManager(=> @history.loadState())
preloadPackages: ->
@packages.preloadPackages()
attachSaveStateListeners: ->
saveState = _.debounce((=>
window.requestIdleCallback => @saveState({isUnloading: false}) unless @unloaded

View File

@ -58,12 +58,14 @@ require('wrap-guide')
clipboard = new Clipboard
TextEditor.setClipboard(clipboard)
window.atom = new AtomEnvironment({
global.atom = new AtomEnvironment({
clipboard,
applicationDelegate: new ApplicationDelegate,
enablePersistence: true
})
global.atom.preloadPackages()
# Like sands through the hourglass, so are the days of our lives.
module.exports = ({blobStore}) ->
{updateProcessEnv} = require('./update-process-env')
@ -82,13 +84,13 @@ module.exports = ({blobStore}) ->
# Make React faster
process.env.NODE_ENV ?= 'production' unless devMode
window.atom.initialize({
global.atom.initialize({
window, document, blobStore,
configDirPath: process.env.ATOM_HOME,
env: process.env
})
window.atom.startEditorWindow().then ->
global.atom.startEditorWindow().then ->
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)

View File

@ -17,7 +17,7 @@ KeymapManager::canLoadBundledKeymapsFromMemory = ->
KeymapManager::loadBundledKeymaps = ->
if bundledKeymaps?
for keymapName, keymap of bundledKeymaps
keymapPath = "core/#{keymapName}"
keymapPath = "core:#{keymapName}"
@add(keymapPath, keymap, 0, @devMode ? false)
else
keymapsPath = path.join(@resourcePath, 'keymaps')

View File

@ -94,7 +94,7 @@ class MenuManager
add: (items) ->
items = _.deepClone(items)
@merge(@template, item) for item in items
@update() if @initialized
@update()
new Disposable => @remove(items)
remove: (items) ->
@ -147,6 +147,8 @@ class MenuManager
# Public: Refreshes the currently visible menu.
update: ->
return unless @initialized
clearImmediate(@pendingUpdateOperation) if @pendingUpdateOperation?
@pendingUpdateOperation = setImmediate =>

View File

@ -10,6 +10,7 @@ ServiceHub = require 'service-hub'
Package = require './package'
ThemePackage = require './theme-package'
{isDeprecatedPackage, getDeprecatedPackageMetadata} = require './deprecated-packages'
packageJSON = require('../package.json')
# Extended: Package manager for coordinating the lifecycle of Atom packages.
#
@ -39,9 +40,11 @@ class PackageManager
@packageDirPaths = []
@deferredActivationHooks = []
@triggeredActivationHooks = new Set()
@packagesCache = require('../package.json')?._atomPackages ? {}
@packagesCache = packageJSON._atomPackages ? {}
@packageDependencies = packageJSON.packageDependencies ? {}
@initialPackagesLoaded = false
@initialPackagesActivated = false
@preloadedPackages = {}
@loadedPackages = {}
@activePackages = {}
@activatingPackages = {}
@ -288,32 +291,47 @@ class PackageManager
# Public: Returns an {Array} of {String}s of all the available package paths.
getAvailablePackagePaths: ->
packagePaths = []
for packageDirPath in @packageDirPaths
for packagePath in fs.listSync(packageDirPath)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
packagesPath = path.join(@resourcePath, 'node_modules')
for packageName of @getPackageDependencies()
packagePath = path.join(packagesPath, packageName)
packagePaths.push(packagePath) if fs.isDirectorySync(packagePath)
_.uniq(packagePaths)
@getAvailablePackages().map((a) -> a.path)
# Public: Returns an {Array} of {String}s of all the available package names.
getAvailablePackageNames: ->
_.uniq _.map @getAvailablePackagePaths(), (packagePath) -> path.basename(packagePath)
@getAvailablePackages().map((a) -> a.name)
# Public: Returns an {Array} of {String}s of all the available package metadata.
getAvailablePackageMetadata: ->
packages = []
for packagePath in @getAvailablePackagePaths()
name = path.basename(packagePath)
metadata = @getLoadedPackage(name)?.metadata ? @loadPackageMetadata(packagePath, true)
for pack in @getAvailablePackages()
metadata = @getLoadedPackage(pack.name)?.metadata ? @loadPackageMetadata(pack, true)
packages.push(metadata)
packages
getAvailablePackages: ->
packages = []
packagesByName = new Set()
for packageDirPath in @packageDirPaths
if fs.isDirectorySync(packageDirPath)
for packagePath in fs.readdirSync(packageDirPath)
packagePath = path.join(packageDirPath, packagePath)
packageName = path.basename(packagePath)
if not packageName.startsWith('.') and not packagesByName.has(packageName) and fs.isDirectorySync(packagePath)
packages.push({
name: packageName,
path: packagePath,
isBundled: false
})
packagesByName.add(packageName)
for packageName of @packageDependencies
unless packagesByName.has(packageName)
packages.push({
name: packageName,
path: path.join(@resourcePath, 'node_modules', packageName),
isBundled: true
})
packages.sort((a, b) -> a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
###
Section: Private
###
@ -325,11 +343,6 @@ class PackageManager
@packageStates[name] = state
getPackageDependencies: ->
unless @packageDependencies?
try
@packageDependencies = require('../package.json')?.packageDependencies
@packageDependencies ?= {}
@packageDependencies
hasAtomEngine: (packagePath) ->
@ -358,51 +371,99 @@ class PackageManager
keymapsToEnable = _.difference(oldValue, newValue)
keymapsToDisable = _.difference(newValue, oldValue)
for packageName in keymapsToDisable when not @isPackageDisabled(packageName)
disabledPackageNames = new Set(@config.get('core.disabledPackages'))
for packageName in keymapsToDisable when not disabledPackageNames.has(packageName)
@getLoadedPackage(packageName)?.deactivateKeymaps()
for packageName in keymapsToEnable when not @isPackageDisabled(packageName)
for packageName in keymapsToEnable when not disabledPackageNames.has(packageName)
@getLoadedPackage(packageName)?.activateKeymaps()
null
preloadPackages: ->
for packageName, pack of @packagesCache
metadata = pack.metadata ? {}
unless typeof metadata.name is 'string' and metadata.name.length > 0
metadata.name = packageName
if metadata.repository?.type is 'git' and typeof metadata.repository.url is 'string'
metadata.repository.url = metadata.repository.url.replace(/(^git\+)|(\.git$)/g, '')
options = {
path: pack.rootDirPath, name: packageName, preloadedPackage: true,
bundledPackage: true, metadata, packageManager: this, @config,
@styleManager, @commandRegistry, @keymapManager,
@notificationManager, @grammarRegistry, @themeManager, @menuManager,
@contextMenuManager, @deserializerManager, @viewRegistry
}
if metadata.theme
pack = new ThemePackage(options)
else
pack = new Package(options)
pack.preload()
@preloadedPackages[packageName] = pack
loadPackages: ->
# Ensure atom exports is already in the require cache so the load time
# of the first package isn't skewed by being the first to require atom
require '../exports/atom'
packagePaths = @getAvailablePackagePaths()
packagePaths = packagePaths.filter (packagePath) => not @isPackageDisabled(path.basename(packagePath))
packagePaths = _.uniq packagePaths, (packagePath) -> path.basename(packagePath)
disabledPackageNames = new Set(@config.get('core.disabledPackages'))
@config.transact =>
@loadPackage(packagePath) for packagePath in packagePaths
for pack in @getAvailablePackages()
if disabledPackageNames.has(pack.name)
if preloadedPackage = @preloadedPackages[pack.name]
preloadedPackage.deactivate()
delete preloadedPackage[pack.name]
else
@loadAvailablePackage(pack)
return
@initialPackagesLoaded = true
@emitter.emit 'did-load-initial-packages'
loadPackage: (nameOrPath) ->
return null if path.basename(nameOrPath)[0].match /^\./ # primarily to skip .git folder
return pack if pack = @getLoadedPackage(nameOrPath)
if packagePath = @resolvePackagePath(nameOrPath)
if path.basename(nameOrPath)[0].match(/^\./) # primarily to skip .git folder
null
else if pack = @getLoadedPackage(nameOrPath)
pack
else if packagePath = @resolvePackagePath(nameOrPath)
name = path.basename(nameOrPath)
return pack if pack = @getLoadedPackage(name)
@loadAvailablePackage({name, path: packagePath, isBundled: @isBundledPackage(name)})
else
console.warn "Could not resolve '#{nameOrPath}' to a package path"
null
loadAvailablePackage: (availablePackage) ->
loadedPackage = @getLoadedPackage(availablePackage.name)
if loadedPackage?
loadedPackage
else
preloadedPackage = @preloadedPackages[availablePackage.name]
if preloadedPackage?
if availablePackage.isBundled
preloadedPackage.finishLoading()
@loadedPackages[availablePackage.name] = preloadedPackage
return preloadedPackage
else
preloadedPackage.deactivate()
delete preloadedPackage[availablePackage.name]
try
metadata = @loadPackageMetadata(packagePath) ? {}
metadata = @loadPackageMetadata(availablePackage) ? {}
catch error
@handleMetadataError(error, packagePath)
@handleMetadataError(error, availablePackage.path)
return null
unless @isBundledPackage(metadata.name)
unless availablePackage.isBundled
if @isDeprecatedPackage(metadata.name, metadata.version)
console.warn "Could not load #{metadata.name}@#{metadata.version} because it uses deprecated APIs that have been removed."
return null
options = {
path: packagePath, metadata, packageManager: this, @config, @styleManager,
@commandRegistry, @keymapManager, @devMode, @notificationManager,
@grammarRegistry, @themeManager, @menuManager, @contextMenuManager,
@deserializerManager, @viewRegistry
path: availablePackage.path, name: availablePackage.name, metadata,
bundledPackage: availablePackage.isBundled, packageManager: this,
@config, @styleManager, @commandRegistry, @keymapManager,
@notificationManager, @grammarRegistry, @themeManager, @menuManager,
@contextMenuManager, @deserializerManager, @viewRegistry
}
if metadata.theme
pack = new ThemePackage(options)
@ -411,10 +472,7 @@ class PackageManager
pack.load()
@loadedPackages[pack.name] = pack
@emitter.emit 'did-load-package', pack
return pack
else
console.warn "Could not resolve '#{nameOrPath}' to a package path"
null
pack
unloadPackages: ->
@unloadPackage(name) for name in _.keys(@loadedPackages)
@ -550,10 +608,20 @@ class PackageManager
@resourcePathWithTrailingSlash ?= "#{@resourcePath}#{path.sep}"
packagePath?.startsWith(@resourcePathWithTrailingSlash)
loadPackageMetadata: (packagePath, ignoreErrors=false) ->
packageName = path.basename(packagePath)
if @isBundledPackagePath(packagePath)
loadPackageMetadata: (packagePathOrAvailablePackage, ignoreErrors=false) ->
if typeof packagePathOrAvailablePackage is 'object'
availablePackage = packagePathOrAvailablePackage
packageName = availablePackage.name
packagePath = availablePackage.path
isBundled = availablePackage.isBundled
else
packagePath = packagePathOrAvailablePackage
packageName = path.basename(packagePath)
isBundled = @isBundledPackagePath(packagePath)
if isBundled
metadata = @packagesCache[packageName]?.metadata
unless metadata?
if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
try

View File

@ -33,15 +33,15 @@ class Package
constructor: (params) ->
{
@path, @metadata, @packageManager, @config, @styleManager, @commandRegistry,
@keymapManager, @devMode, @notificationManager, @grammarRegistry, @themeManager,
@path, @metadata, @bundledPackage, @preloadedPackage, @packageManager, @config, @styleManager, @commandRegistry,
@keymapManager, @notificationManager, @grammarRegistry, @themeManager,
@menuManager, @contextMenuManager, @deserializerManager, @viewRegistry
} = params
@emitter = new Emitter
@metadata ?= @packageManager.loadPackageMetadata(@path)
@bundledPackage = @packageManager.isBundledPackagePath(@path)
@name = @metadata?.name ? path.basename(@path)
@bundledPackage ?= @packageManager.isBundledPackagePath(@path)
@name = @metadata?.name ? params.name ? path.basename(@path)
unless @bundledPackage
ModuleCache.add(@path, @metadata)
@reset()
@ -81,6 +81,28 @@ class Package
getStyleSheetPriority: -> 0
preload: ->
@loadKeymaps()
@loadMenus()
@registerDeserializerMethods()
@activateCoreStartupServices()
@registerTranspilerConfig()
@configSchemaRegisteredOnLoad = @registerConfigSchemaFromMetadata()
@requireMainModule()
@settingsPromise = @loadSettings()
@activationDisposables = new CompositeDisposable
@activateKeymaps()
@activateContextMenus()
@activateMenus()
settings.activate() for settings in @settings
@settingsActivated = true
finishLoading: ->
@measure 'loadTime', =>
@path = path.join(@packageManager.resourcePath, @path)
@loadStylesheets()
load: ->
@measure 'loadTime', =>
try
@ -218,39 +240,33 @@ class Package
@stylesheetsActivated = true
activateResources: ->
@activationDisposables = new CompositeDisposable
@activationDisposables ?= new CompositeDisposable
keymapIsDisabled = _.include(@config.get("core.packagesWithKeymapsDisabled") ? [], @name)
if keymapIsDisabled
@deactivateKeymaps()
else
else unless @preloadedPackage
@activateKeymaps()
for [menuPath, map] in @menus when map['context-menu']?
try
itemsBySelector = map['context-menu']
@activationDisposables.add(@contextMenuManager.add(itemsBySelector))
catch error
if error.code is 'EBADSELECTOR'
error.message += " in #{menuPath}"
error.stack += "\n at #{menuPath}:1:1"
throw error
@activationDisposables.add(@menuManager.add(map['menu'])) for [menuPath, map] in @menus when map['menu']?
unless @preloadedPackage
@activateContextMenus()
@activateMenus()
unless @grammarsActivated
grammar.activate() for grammar in @grammars
@grammarsActivated = true
settings.activate() for settings in @settings
@settingsActivated = true
unless @preloadedPackage
settings.activate() for settings in @settings
@settingsActivated = true
activateKeymaps: ->
return if @keymapActivated
@keymapDisposables = new CompositeDisposable()
@keymapDisposables.add(@keymapManager.add(keymapPath, map)) for [keymapPath, map] in @keymaps
validateSelectors = not @preloadedPackage
@keymapDisposables.add(@keymapManager.add(keymapPath, map, 0, validateSelectors)) for [keymapPath, map] in @keymaps
@menuManager.update()
@keymapActivated = true
@ -269,6 +285,22 @@ class Package
return true
false
activateContextMenus: ->
validateSelectors = not @preloadedPackage
for [menuPath, map] in @menus when map['context-menu']?
try
itemsBySelector = map['context-menu']
@activationDisposables.add(@contextMenuManager.add(itemsBySelector, validateSelectors))
catch error
if error.code is 'EBADSELECTOR'
error.message += " in #{menuPath}"
error.stack += "\n at #{menuPath}:1:1"
throw error
activateMenus: ->
for [menuPath, map] in @menus when map['menu']?
@activationDisposables.add(@menuManager.add(map['menu']))
activateServices: ->
for name, {versions} of @metadata.providedServices
servicesByVersion = {}
@ -293,14 +325,14 @@ class Package
loadKeymaps: ->
if @bundledPackage and @packageManager.packagesCache[@name]?
@keymaps = (["#{@packageManager.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps)
@keymaps = (["core:#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps)
else
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath, allowDuplicateKeys: false) ? {}]
return
loadMenus: ->
if @bundledPackage and @packageManager.packagesCache[@name]?
@menus = (["#{@packageManager.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of @packageManager.packagesCache[@name].menus)
@menus = (["core:#{menuPath}", menuObject] for menuPath, menuObject of @packageManager.packagesCache[@name].menus)
else
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath) ? {}]
return
@ -327,7 +359,7 @@ class Package
if @metadata.deserializers?
Object.keys(@metadata.deserializers).forEach (deserializerName) =>
methodName = @metadata.deserializers[deserializerName]
atom.deserializers.add
@deserializerManager.add
name: deserializerName,
deserialize: (state, atomEnvironment) =>
@registerViewProviders()
@ -375,9 +407,15 @@ class Package
loadGrammarsSync: ->
return if @grammarsLoaded
grammarsDirPath = path.join(@path, 'grammars')
grammarPaths = fs.listSync(grammarsDirPath, ['json', 'cson'])
if @preloadedPackage
grammarPaths = @packageManager.packagesCache[@name].grammarPaths
else
grammarPaths = fs.listSync(path.join(@path, 'grammars'), ['json', 'cson'])
for grammarPath in grammarPaths
if @preloadedPackage
grammarPath = path.resolve(@packageManager.resourcePath, grammarPath)
try
grammar = @grammarRegistry.readGrammarSync(grammarPath)
grammar.packageName = @name
@ -394,6 +432,9 @@ class Package
return Promise.resolve() if @grammarsLoaded
loadGrammar = (grammarPath, callback) =>
if @preloadedPackage
grammarPath = path.resolve(@packageManager.resourcePath, grammarPath)
@grammarRegistry.readGrammar grammarPath, (error, grammar) =>
if error?
detail = "#{error.message} in #{grammarPath}"
@ -407,12 +448,16 @@ class Package
callback()
new Promise (resolve) =>
grammarsDirPath = path.join(@path, 'grammars')
fs.exists grammarsDirPath, (grammarsDirExists) ->
return resolve() unless grammarsDirExists
if @preloadedPackage
grammarPaths = @packageManager.packagesCache[@name].grammarPaths
async.each grammarPaths, loadGrammar, -> resolve()
else
grammarsDirPath = path.join(@path, 'grammars')
fs.exists grammarsDirPath, (grammarsDirExists) ->
return resolve() unless grammarsDirExists
fs.list grammarsDirPath, ['json', 'cson'], (error, grammarPaths=[]) ->
async.each grammarPaths, loadGrammar, -> resolve()
fs.list grammarsDirPath, ['json', 'cson'], (error, grammarPaths=[]) ->
async.each grammarPaths, loadGrammar, -> resolve()
loadSettings: ->
@settings = []
@ -429,13 +474,19 @@ class Package
callback()
new Promise (resolve) =>
settingsDirPath = path.join(@path, 'settings')
if @preloadedPackage
for settingsPath, scopedProperties of @packageManager.packagesCache[@name].settings
settings = new ScopedProperties("core:#{settingsPath}", scopedProperties ? {}, @config)
@settings.push(settings)
settings.activate() if @settingsActivated
resolve()
else
settingsDirPath = path.join(@path, 'settings')
fs.exists settingsDirPath, (settingsDirExists) ->
return resolve() unless settingsDirExists
fs.exists settingsDirPath, (settingsDirExists) ->
return resolve() unless settingsDirExists
fs.list settingsDirPath, ['json', 'cson'], (error, settingsPaths=[]) ->
async.each settingsPaths, loadSettingsFile, -> resolve()
fs.list settingsDirPath, ['json', 'cson'], (error, settingsPaths=[]) ->
async.each settingsPaths, loadSettingsFile, -> resolve()
serialize: ->
if @mainActivated
@ -484,23 +535,28 @@ class Package
@activateStylesheets()
requireMainModule: ->
return @mainModule if @mainModuleRequired
unless @isCompatible()
if @bundledPackage and @packageManager.packagesCache[@name]?
if @packageManager.packagesCache[@name].main?
@mainModule = require(@packageManager.packagesCache[@name].main)
else if @mainModuleRequired
@mainModule
else if not @isCompatible()
console.warn """
Failed to require the main module of '#{@name}' because it requires one or more incompatible native modules (#{_.pluck(@incompatibleModules, 'name').join(', ')}).
Run `apm rebuild` in the package directory and restart Atom to resolve.
"""
return
mainModulePath = @getMainModulePath()
if fs.isFileSync(mainModulePath)
@mainModuleRequired = true
else
mainModulePath = @getMainModulePath()
if fs.isFileSync(mainModulePath)
@mainModuleRequired = true
previousViewProviderCount = @viewRegistry.getViewProviderCount()
previousDeserializerCount = @deserializerManager.getDeserializerCount()
@mainModule = require(mainModulePath)
if (@viewRegistry.getViewProviderCount() is previousViewProviderCount and
@deserializerManager.getDeserializerCount() is previousDeserializerCount)
localStorage.setItem(@getCanDeferMainModuleRequireStorageKey(), 'true')
previousViewProviderCount = @viewRegistry.getViewProviderCount()
previousDeserializerCount = @deserializerManager.getDeserializerCount()
@mainModule = require(mainModulePath)
if (@viewRegistry.getViewProviderCount() is previousViewProviderCount and
@deserializerManager.getDeserializerCount() is previousDeserializerCount)
localStorage.setItem(@getCanDeferMainModuleRequireStorageKey(), 'true')
getMainModulePath: ->
return @mainModulePath if @resolvedMainModulePath
@ -508,7 +564,7 @@ class Package
if @bundledPackage and @packageManager.packagesCache[@name]?
if @packageManager.packagesCache[@name].main
@mainModulePath = "#{@packageManager.resourcePath}#{path.sep}#{@packageManager.packagesCache[@name].main}"
@mainModulePath = path.resolve(@packageManager.resourcePath, 'static', @packageManager.packagesCache[@name].main)
else
@mainModulePath = null
else
@ -643,8 +699,8 @@ class Package
isCompatible: ->
return @compatible if @compatible?
if @path.indexOf(path.join(@packageManager.resourcePath, 'node_modules') + path.sep) is 0
# Bundled packages are always considered compatible
if @preloadedPackage
# Preloaded packages are always considered compatible
@compatible = true
else if @getMainModulePath()
@incompatibleModules = @getIncompatibleNativeModules()
@ -704,7 +760,7 @@ class Package
# This information is cached in local storage on a per package/version basis
# to minimize the impact on startup time.
getIncompatibleNativeModules: ->
unless @devMode
unless @packageManager.devMode
try
if arrayAsString = global.localStorage.getItem(@getIncompatibleNativeModulesStorageKey())
return JSON.parse(arrayAsString)

View File

@ -1,3 +1,4 @@
path = require 'path'
Package = require './package'
module.exports =
@ -12,6 +13,13 @@ class ThemePackage extends Package
disable: ->
@config.removeAtKeyPath('core.themes', @name)
preload: ->
@loadTime = 0
@configSchemaRegisteredOnLoad = @registerConfigSchemaFromMetadata()
finishLoading: ->
@path = path.join(@packageManager.resourcePath, @path)
load: ->
@loadTime = 0
@configSchemaRegisteredOnLoad = @registerConfigSchemaFromMetadata()