mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-08 17:22:05 +08:00
Reviewed By: davidaurelio Differential Revision: D2819820 fb-gh-sync-id: 066fd1191c459cf3434899de6326e25f798c4b07
171 lines
4.4 KiB
JavaScript
171 lines
4.4 KiB
JavaScript
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* 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
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
'use strict';
|
|
|
|
const Bundle = require('../Bundler/Bundle');
|
|
const PrepackBundle = require('../Bundler/PrepackBundle');
|
|
const Promise = require('promise');
|
|
const bser = require('bser');
|
|
const debug = require('debug')('ReactNativePackager:SocketClient');
|
|
const fs = require('fs');
|
|
const net = require('net');
|
|
const path = require('path');
|
|
const tmpdir = require('os').tmpdir();
|
|
|
|
const LOG_PATH = path.join(tmpdir, 'react-packager.log');
|
|
|
|
class SocketClient {
|
|
static create(sockPath) {
|
|
return new SocketClient(sockPath).onReady();
|
|
}
|
|
|
|
constructor(sockPath) {
|
|
debug('connecting to', sockPath);
|
|
|
|
this._sock = net.connect(sockPath);
|
|
this._ready = new Promise((resolve, reject) => {
|
|
this._sock.on('connect', () => {
|
|
this._sock.removeAllListeners('error');
|
|
process.on('uncaughtException', (error) => {
|
|
console.error('uncaught error', error.stack);
|
|
setImmediate(() => process.exit(1));
|
|
});
|
|
resolve(this);
|
|
});
|
|
this._sock.on('error', (e) => {
|
|
e.message = `Error connecting to server on ${sockPath} ` +
|
|
`with error: ${e.message}`;
|
|
e.message += getServerLogs();
|
|
|
|
reject(e);
|
|
});
|
|
});
|
|
|
|
this._resolvers = Object.create(null);
|
|
const bunser = new bser.BunserBuf();
|
|
this._sock.on('data', (buf) => bunser.append(buf));
|
|
bunser.on('value', (message) => this._handleMessage(message));
|
|
|
|
this._sock.on('close', () => {
|
|
if (!this._closing) {
|
|
const terminate = (result) => {
|
|
const sockPathExists = fs.existsSync(sockPath);
|
|
throw new Error(
|
|
'Server closed unexpectedly.\n' +
|
|
'Server ping connection attempt result: ' + result + '\n' +
|
|
'Socket path: `' + sockPath + '` ' +
|
|
(sockPathExists ? ' exists.' : 'doesn\'t exist') + '\n' +
|
|
getServerLogs()
|
|
);
|
|
};
|
|
|
|
// before throwing ping the server to see if it's still alive
|
|
const socket = net.connect(sockPath);
|
|
socket.on('connect', () => {
|
|
socket.end();
|
|
terminate('OK');
|
|
});
|
|
socket.on('error', error => terminate(error));
|
|
}
|
|
});
|
|
}
|
|
|
|
onReady() {
|
|
return this._ready;
|
|
}
|
|
|
|
getDependencies(main) {
|
|
return this._send({
|
|
type: 'getDependencies',
|
|
data: main,
|
|
});
|
|
}
|
|
|
|
getOrderedDependencyPaths(main) {
|
|
return this._send({
|
|
type: 'getOrderedDependencyPaths',
|
|
data: main,
|
|
});
|
|
}
|
|
|
|
buildBundle(options) {
|
|
return this._send({
|
|
type: 'buildBundle',
|
|
data: options,
|
|
}).then(json => Bundle.fromJSON(json));
|
|
}
|
|
|
|
buildPrepackBundle(options) {
|
|
return this._send({
|
|
type: 'buildPrepackBundle',
|
|
data: options,
|
|
}).then(json => PrepackBundle.fromJSON(json));
|
|
}
|
|
|
|
_send(message) {
|
|
message.id = uid();
|
|
this._sock.write(bser.dumpToBuffer(message));
|
|
return new Promise((resolve, reject) => {
|
|
this._resolvers[message.id] = {resolve, reject};
|
|
});
|
|
}
|
|
|
|
_handleMessage(message) {
|
|
if (!(message && message.id && message.type)) {
|
|
throw new Error(
|
|
'Malformed message from server ' + JSON.stringify(message)
|
|
);
|
|
}
|
|
|
|
debug('got message with type', message.type);
|
|
|
|
const resolver = this._resolvers[message.id];
|
|
if (!resolver) {
|
|
throw new Error(
|
|
'Unrecognized message id (' + message.id + ') ' +
|
|
'message already resolved or never existed.'
|
|
);
|
|
}
|
|
|
|
delete this._resolvers[message.id];
|
|
|
|
if (message.type === 'error') {
|
|
const errorLog =
|
|
message.data && message.data.indexOf('TimeoutError') === -1
|
|
? 'See logs ' + LOG_PATH
|
|
: getServerLogs();
|
|
|
|
resolver.reject(new Error(message.data + '\n' + errorLog));
|
|
} else {
|
|
resolver.resolve(message.data);
|
|
}
|
|
}
|
|
|
|
close() {
|
|
debug('closing connection');
|
|
this._closing = true;
|
|
this._sock.end();
|
|
}
|
|
}
|
|
|
|
module.exports = SocketClient;
|
|
|
|
function uid(len) {
|
|
len = len || 7;
|
|
return Math.random().toString(35).substr(2, len);
|
|
}
|
|
|
|
function getServerLogs() {
|
|
if (fs.existsSync(LOG_PATH)) {
|
|
return '\nServer logs:\n' + fs.readFileSync(LOG_PATH, 'utf8');
|
|
}
|
|
|
|
return '';
|
|
}
|