mirror of
https://github.com/status-im/react-native.git
synced 2025-01-28 02:04:55 +00:00
packager: attachHMRServer.js: Flow
Summary: The breakage fixed by changeset [1] could have been identified earlier if we had typing on `attachHMRServer`, so I spent some time on that. This has revealed in turn a few functions across the codebase that were incorrectly typed, and that are now fixed. [1] packager: attachHMRServer.js: fix callsite of Server#getModuleForPath() Reviewed By: davidaurelio Differential Revision: D4706241 fbshipit-source-id: fc4285245921ae45d5781a47d626fc0559dba998
This commit is contained in:
parent
18c239ee22
commit
7098c450d8
@ -5,7 +5,10 @@
|
|||||||
* This source code is licensed under the BSD-style license found in the
|
* This source code is licensed under the BSD-style license found in the
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const querystring = require('querystring');
|
const querystring = require('querystring');
|
||||||
@ -13,15 +16,27 @@ const url = require('url');
|
|||||||
|
|
||||||
const {getInverseDependencies} = require('../../../packager/src//node-haste');
|
const {getInverseDependencies} = require('../../../packager/src//node-haste');
|
||||||
|
|
||||||
|
import type HMRBundle from '../../../packager/src/Bundler/HMRBundle';
|
||||||
|
import type Server from '../../../packager/src/Server';
|
||||||
|
import type ResolutionResponse from '../../../packager/src/node-haste/DependencyGraph/ResolutionResponse';
|
||||||
|
import type Module from '../../../packager/src/node-haste/Module';
|
||||||
|
import type {Server as HTTPServer} from 'http';
|
||||||
|
|
||||||
const blacklist = [
|
const blacklist = [
|
||||||
'Libraries/Utilities/HMRClient.js',
|
'Libraries/Utilities/HMRClient.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
type HMROptions = {
|
||||||
|
httpServer: HTTPServer,
|
||||||
|
path: string,
|
||||||
|
packagerServer: Server,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a WebSocket based connection to the Packager to expose
|
* Attaches a WebSocket based connection to the Packager to expose
|
||||||
* Hot Module Replacement updates to the simulator.
|
* Hot Module Replacement updates to the simulator.
|
||||||
*/
|
*/
|
||||||
function attachHMRServer({httpServer, path, packagerServer}) {
|
function attachHMRServer({httpServer, path, packagerServer}: HMROptions) {
|
||||||
let client = null;
|
let client = null;
|
||||||
|
|
||||||
function disconnect() {
|
function disconnect() {
|
||||||
@ -33,18 +48,25 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
// - The full list of dependencies.
|
// - The full list of dependencies.
|
||||||
// - The shallow dependencies each file on the dependency list has
|
// - The shallow dependencies each file on the dependency list has
|
||||||
// - Inverse shallow dependencies map
|
// - Inverse shallow dependencies map
|
||||||
function getDependencies(platform, bundleEntry) {
|
function getDependencies(platform: string, bundleEntry: string): Promise<{
|
||||||
|
dependenciesCache: Array<string>,
|
||||||
|
dependenciesModulesCache: {[mixed]: Module},
|
||||||
|
shallowDependencies: {[string]: Array<Module>},
|
||||||
|
inverseDependenciesCache: mixed,
|
||||||
|
resolutionResponse: ResolutionResponse,
|
||||||
|
}> {
|
||||||
return packagerServer.getDependencies({
|
return packagerServer.getDependencies({
|
||||||
platform: platform,
|
platform: platform,
|
||||||
dev: true,
|
dev: true,
|
||||||
hot: true,
|
hot: true,
|
||||||
entryFile: bundleEntry,
|
entryFile: bundleEntry,
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
const {getModuleId} = response;
|
/* $FlowFixMe: getModuleId might be null */
|
||||||
|
const {getModuleId}: {getModuleId: () => number} = response;
|
||||||
|
|
||||||
// for each dependency builds the object:
|
// for each dependency builds the object:
|
||||||
// `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}`
|
// `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}`
|
||||||
return Promise.all(Object.values(response.dependencies).map(dep => {
|
return Promise.all(response.dependencies.map((dep: Module) => {
|
||||||
return dep.getName().then(depName => {
|
return dep.getName().then(depName => {
|
||||||
if (dep.isAsset() || dep.isJSON()) {
|
if (dep.isAsset() || dep.isJSON()) {
|
||||||
return Promise.resolve({path: dep.path, deps: []});
|
return Promise.resolve({path: dep.path, deps: []});
|
||||||
@ -54,23 +76,23 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
dev: true,
|
dev: true,
|
||||||
hot: true,
|
hot: true,
|
||||||
entryFile: dep.path
|
entryFile: dep.path
|
||||||
})
|
}).then(deps => {
|
||||||
.then(deps => {
|
return {
|
||||||
return {
|
path: dep.path,
|
||||||
path: dep.path,
|
name: depName,
|
||||||
name: depName,
|
deps,
|
||||||
deps,
|
};
|
||||||
};
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}))
|
}))
|
||||||
.then(deps => {
|
.then((deps: Array<{path: string, name?: string, deps: Array<Module>}>) => {
|
||||||
// list with all the dependencies' filenames the bundle entry has
|
// list with all the dependencies' filenames the bundle entry has
|
||||||
const dependenciesCache = response.dependencies.map(dep => dep.path);
|
const dependenciesCache = response.dependencies.map(dep => dep.path);
|
||||||
|
|
||||||
// map from module name to path
|
// map from module name to path
|
||||||
const moduleToFilenameCache = Object.create(null);
|
const moduleToFilenameCache = Object.create(null);
|
||||||
deps.forEach(dep => {
|
deps.forEach(dep => {
|
||||||
|
/* $FlowFixMe: `name` could be null, but `deps` would be as well. */
|
||||||
moduleToFilenameCache[dep.name] = dep.path;
|
moduleToFilenameCache[dep.name] = dep.path;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -114,6 +136,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
wss.on('connection', ws => {
|
wss.on('connection', ws => {
|
||||||
|
/* $FlowFixMe: url might be null */
|
||||||
const params = querystring.parse(url.parse(ws.upgradeReq.url).query);
|
const params = querystring.parse(url.parse(ws.upgradeReq.url).query);
|
||||||
|
|
||||||
getDependencies(params.platform, params.bundleEntry)
|
getDependencies(params.platform, params.bundleEntry)
|
||||||
@ -195,11 +218,13 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nonNullClient = client;
|
||||||
|
|
||||||
return packagerServer.getModuleForPath(filename).then(moduleToUpdate => {
|
return packagerServer.getModuleForPath(filename).then(moduleToUpdate => {
|
||||||
// build list of modules for which we'll send HMR updates
|
// build list of modules for which we'll send HMR updates
|
||||||
const modulesToUpdate = [moduleToUpdate];
|
const modulesToUpdate = [moduleToUpdate];
|
||||||
Object.keys(depsModulesCache).forEach(module => {
|
Object.keys(depsModulesCache).forEach(module => {
|
||||||
if (!client.dependenciesModulesCache[module]) {
|
if (!nonNullClient.dependenciesModulesCache[module]) {
|
||||||
modulesToUpdate.push(depsModulesCache[module]);
|
modulesToUpdate.push(depsModulesCache[module]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -215,10 +240,10 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
modulesToUpdate.reverse();
|
modulesToUpdate.reverse();
|
||||||
|
|
||||||
// invalidate caches
|
// invalidate caches
|
||||||
client.dependenciesCache = depsCache;
|
nonNullClient.dependenciesCache = depsCache;
|
||||||
client.dependenciesModulesCache = depsModulesCache;
|
nonNullClient.dependenciesModulesCache = depsModulesCache;
|
||||||
client.shallowDependencies = shallowDeps;
|
nonNullClient.shallowDependencies = shallowDeps;
|
||||||
client.inverseDependenciesCache = inverseDepsCache;
|
nonNullClient.inverseDependenciesCache = inverseDepsCache;
|
||||||
|
|
||||||
return resolutionResponse.copy({
|
return resolutionResponse.copy({
|
||||||
dependencies: modulesToUpdate
|
dependencies: modulesToUpdate
|
||||||
@ -252,7 +277,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
resolutionResponse,
|
resolutionResponse,
|
||||||
}, packagerHost, httpServerAddress.port);
|
}, packagerHost, httpServerAddress.port);
|
||||||
})
|
})
|
||||||
.then(bundle => {
|
.then((bundle: HMRBundle) => {
|
||||||
if (!client || !bundle || bundle.isEmpty()) {
|
if (!client || !bundle || bundle.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -299,6 +324,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
|
/* $FlowFixMe: assume `client` non-null */
|
||||||
client.ws.send(JSON.stringify({type: 'update-done'}));
|
client.ws.send(JSON.stringify({type: 'update-done'}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -316,7 +342,7 @@ function attachHMRServer({httpServer, path, packagerServer}) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayEquals(arrayA, arrayB) {
|
function arrayEquals<T>(arrayA: Array<T>, arrayB: Array<T>): boolean {
|
||||||
arrayA = arrayA || [];
|
arrayA = arrayA || [];
|
||||||
arrayB = arrayB || [];
|
arrayB = arrayB || [];
|
||||||
return (
|
return (
|
||||||
|
@ -277,7 +277,7 @@ class Bundler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
hmrBundle(options: {platform: ?string}, host: string, port: number) {
|
hmrBundle(options: {platform: ?string}, host: string, port: number): Promise<HMRBundle> {
|
||||||
return this._bundle({
|
return this._bundle({
|
||||||
...options,
|
...options,
|
||||||
bundle: new HMRBundle({
|
bundle: new HMRBundle({
|
||||||
@ -492,7 +492,7 @@ class Bundler {
|
|||||||
minify?: boolean,
|
minify?: boolean,
|
||||||
hot?: boolean,
|
hot?: boolean,
|
||||||
generateSourceMaps?: boolean,
|
generateSourceMaps?: boolean,
|
||||||
}) {
|
}): Promise<Array<Module>> {
|
||||||
return this.getTransformOptions(
|
return this.getTransformOptions(
|
||||||
entryFile,
|
entryFile,
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ class Resolver {
|
|||||||
getShallowDependencies(
|
getShallowDependencies(
|
||||||
entryFile: string,
|
entryFile: string,
|
||||||
transformOptions: TransformOptions,
|
transformOptions: TransformOptions,
|
||||||
): Array<string> {
|
): Promise<Array<Module>> {
|
||||||
return this._depGraph.getShallowDependencies(entryFile, transformOptions);
|
return this._depGraph.getShallowDependencies(entryFile, transformOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import type {Stats} from 'fs';
|
|||||||
import type {IncomingMessage, ServerResponse} from 'http';
|
import type {IncomingMessage, ServerResponse} from 'http';
|
||||||
import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse';
|
import type ResolutionResponse from '../node-haste/DependencyGraph/ResolutionResponse';
|
||||||
import type Bundle from '../Bundler/Bundle';
|
import type Bundle from '../Bundler/Bundle';
|
||||||
|
import type HMRBundle from '../Bundler/HMRBundle';
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
import type {GetTransformOptions} from '../Bundler';
|
import type {GetTransformOptions} from '../Bundler';
|
||||||
import type GlobalTransformCache from '../lib/GlobalTransformCache';
|
import type GlobalTransformCache from '../lib/GlobalTransformCache';
|
||||||
@ -157,7 +158,7 @@ class Server {
|
|||||||
_assetServer: AssetServer;
|
_assetServer: AssetServer;
|
||||||
_bundler: Bundler;
|
_bundler: Bundler;
|
||||||
_debouncedFileChangeHandler: (filePath: string) => mixed;
|
_debouncedFileChangeHandler: (filePath: string) => mixed;
|
||||||
_hmrFileChangeListener: (type: string, filePath: string) => mixed;
|
_hmrFileChangeListener: ?(type: string, filePath: string) => mixed;
|
||||||
_reporter: Reporter;
|
_reporter: Reporter;
|
||||||
_symbolicateInWorker: Symbolicate;
|
_symbolicateInWorker: Symbolicate;
|
||||||
|
|
||||||
@ -244,9 +245,7 @@ class Server {
|
|||||||
return this._bundler.end();
|
return this._bundler.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
setHMRFileChangeListener(
|
setHMRFileChangeListener(listener: ?(type: string, filePath: string) => mixed) {
|
||||||
listener: (type: string, filePath: string) => mixed,
|
|
||||||
) {
|
|
||||||
this._hmrFileChangeListener = listener;
|
this._hmrFileChangeListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +275,7 @@ class Server {
|
|||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildBundleFromUrl(reqUrl: string): Promise<mixed> {
|
buildBundleFromUrl(reqUrl: string): Promise<Bundle> {
|
||||||
const options = this._getOptionsFromUrl(reqUrl);
|
const options = this._getOptionsFromUrl(reqUrl);
|
||||||
return this.buildBundle(options);
|
return this.buildBundle(options);
|
||||||
}
|
}
|
||||||
@ -285,14 +284,14 @@ class Server {
|
|||||||
options: {platform: ?string},
|
options: {platform: ?string},
|
||||||
host: string,
|
host: string,
|
||||||
port: number,
|
port: number,
|
||||||
): Promise<string> {
|
): Promise<HMRBundle> {
|
||||||
return this._bundler.hmrBundle(options, host, port);
|
return this._bundler.hmrBundle(options, host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
getShallowDependencies(options: {
|
getShallowDependencies(options: {
|
||||||
entryFile: string,
|
entryFile: string,
|
||||||
platform?: string,
|
platform?: string,
|
||||||
}): Promise<mixed> {
|
}): Promise<Array<Module>> {
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
if (!options.platform) {
|
if (!options.platform) {
|
||||||
options.platform = getPlatformExtension(options.entryFile);
|
options.platform = getPlatformExtension(options.entryFile);
|
||||||
@ -335,10 +334,11 @@ class Server {
|
|||||||
// If Hot Loading is enabled avoid rebuilding bundles and sending live
|
// If Hot Loading is enabled avoid rebuilding bundles and sending live
|
||||||
// updates. Instead, send the HMR updates right away and clear the bundles
|
// updates. Instead, send the HMR updates right away and clear the bundles
|
||||||
// cache so that if the user reloads we send them a fresh bundle
|
// cache so that if the user reloads we send them a fresh bundle
|
||||||
if (this._hmrFileChangeListener) {
|
const {_hmrFileChangeListener} = this;
|
||||||
|
if (_hmrFileChangeListener) {
|
||||||
// Clear cached bundles in case user reloads
|
// Clear cached bundles in case user reloads
|
||||||
this._clearBundles();
|
this._clearBundles();
|
||||||
this._hmrFileChangeListener(type, filePath);
|
_hmrFileChangeListener(type, filePath);
|
||||||
return;
|
return;
|
||||||
} else if (type !== 'change' && filePath.indexOf(NODE_MODULES) !== -1) {
|
} else if (type !== 'change' && filePath.indexOf(NODE_MODULES) !== -1) {
|
||||||
// node module resolution can be affected by added or removed files
|
// node module resolution can be affected by added or removed files
|
||||||
|
@ -173,7 +173,10 @@ class DependencyGraph extends EventEmitter {
|
|||||||
* Returns a promise with the direct dependencies the module associated to
|
* Returns a promise with the direct dependencies the module associated to
|
||||||
* the given entryPath has.
|
* the given entryPath has.
|
||||||
*/
|
*/
|
||||||
getShallowDependencies(entryPath: string, transformOptions: TransformOptions) {
|
getShallowDependencies(
|
||||||
|
entryPath: string,
|
||||||
|
transformOptions: TransformOptions,
|
||||||
|
): Promise<Array<Module>> {
|
||||||
return this._moduleCache
|
return this._moduleCache
|
||||||
.getModule(entryPath)
|
.getModule(entryPath)
|
||||||
.getDependencies(transformOptions);
|
.getDependencies(transformOptions);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user