Mike Grabowski e8b508144f Merge rnpm cli into react-native
Summary:
This is an initial step of rewriting the CLI interface to use `rnpm` one (commander, plugins etc.).

It's scope is to move all existing commands to use rnpm CLI interface, so that we get plugins, flags and our existing ecosystem working out of the box.

<s>This is still WIP and some of the commands are left commented out.</s>

For the `config` of `rnpm` (functions get info about project and dependency), <s>I am thinking we can merge them with</s> we decided to merge it with [`default.config.js`](e57683e420/local-cli/default.config.js (L33)), so they are available on the `new Config()` [instance](e57683e420/local-cli/cliEntry.js (L59)) (which means we don't have to change anything and current plugins, like runIOS and runAndroid can just start using it [w/o depending on any extra argument](https://github.com/grabbou/react-native/blob/e57683e420210749a5a6b802b4e
Closes https://github.com/facebook/react-native/pull/7899

Differential Revision: D3613193

Pulled By: bestander

fbshipit-source-id: 09a072f3b21e5239dfcd8da88a205bd28dc5d037
2016-07-30 09:13:46 -07:00

145 lines
4.2 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 buildSourceMapWithMetaData = require('./build-unbundle-sourcemap-with-metadata');
const fs = require('fs');
const Promise = require('promise');
const writeSourceMap = require('./write-sourcemap');
const {joinModules} = require('./util');
const MAGIC_UNBUNDLE_FILE_HEADER = require('./magic-number');
const SIZEOF_UINT32 = 4;
/**
* Saves all JS modules of an app as a single file, separated with null bytes.
* The file begins with an offset table that contains module ids and their
* lengths/offsets.
* The module id for the startup code (prelude, polyfills etc.) is the
* empty string.
*/
function saveAsIndexedFile(bundle, options, log) {
const {
bundleOutput,
bundleEncoding: encoding,
sourcemapOutput
} = options;
log('start');
const {startupModules, lazyModules} = bundle.getUnbundle();
log('finish');
const startupCode = joinModules(startupModules);
log('Writing unbundle output to:', bundleOutput);
const writeUnbundle = writeBuffers(
fs.createWriteStream(bundleOutput),
buildTableAndContents(startupCode, lazyModules, encoding)
).then(() => log('Done writing unbundle output'));
const sourceMap =
buildSourceMapWithMetaData({startupModules, lazyModules});
return Promise.all([
writeUnbundle,
writeSourceMap(sourcemapOutput, JSON.stringify(sourceMap), log),
]);
}
/* global Buffer: true */
const fileHeader = Buffer(4);
fileHeader.writeUInt32LE(MAGIC_UNBUNDLE_FILE_HEADER);
const nullByteBuffer = Buffer(1).fill(0);
function writeBuffers(stream, buffers) {
buffers.forEach(buffer => stream.write(buffer));
return new Promise((resolve, reject) => {
stream.on('error', reject);
stream.on('finish', () => resolve());
stream.end();
});
}
function nullTerminatedBuffer(contents, encoding) {
return Buffer.concat([Buffer(contents, encoding), nullByteBuffer]);
}
function moduleToBuffer(id, code, encoding) {
return {
id,
buffer: nullTerminatedBuffer(code, encoding),
};
}
function entryOffset(n) {
// 2: num_entries + startup_code_len
// n * 2: each entry consists of two uint32s
return (2 + n * 2) * SIZEOF_UINT32;
}
function buildModuleTable(startupCode, buffers) {
// table format:
// - num_entries: uint_32 number of entries
// - startup_code_len: uint_32 length of the startup section
// - entries: entry...
//
// entry:
// - module_offset: uint_32 offset into the modules blob
// - module_length: uint_32 length of the module code in bytes
const maxId = buffers.reduce((max, {id}) => Math.max(max, id), 0);
const numEntries = maxId + 1;
const table = new Buffer(entryOffset(numEntries)).fill(0);
// num_entries
table.writeUInt32LE(numEntries, 0);
// startup_code_len
table.writeUInt32LE(startupCode.length, SIZEOF_UINT32);
// entries
let codeOffset = startupCode.length;
buffers.forEach(({id, buffer}) => {
const offset = entryOffset(id);
// module_offset
table.writeUInt32LE(codeOffset, offset);
// module_length
table.writeUInt32LE(buffer.length, offset + SIZEOF_UINT32);
codeOffset += buffer.length;
});
return table;
}
function buildModuleBuffers(modules, encoding) {
return modules.map(
module => moduleToBuffer(module.id, module.code, encoding));
}
function buildTableAndContents(startupCode, modules, encoding) {
// file contents layout:
// - magic number char[4] 0xE5 0xD1 0x0B 0xFB (0xFB0BD1E5 uint32 LE)
// - offset table table see `buildModuleTables`
// - code blob char[] null-terminated code strings, starting with
// the startup code
const startupCodeBuffer = nullTerminatedBuffer(startupCode, encoding);
const moduleBuffers = buildModuleBuffers(modules, encoding);
const table = buildModuleTable(startupCodeBuffer, moduleBuffers);
return [
fileHeader,
table,
startupCodeBuffer
].concat(moduleBuffers.map(({buffer}) => buffer));
}
module.exports = saveAsIndexedFile;