You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.1 KiB
80 lines
2.1 KiB
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
*
|
|
* @format
|
|
* @oncall react_native
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
// The magic number is used as a header for bytecode.
|
|
// It represents a Metro tunnel in binary.
|
|
//
|
|
// 11111111
|
|
// 11100111
|
|
// 11000011
|
|
// 11000011
|
|
const MAGIC_NUMBER = 0xffe7c3c3;
|
|
function getFileHeader(moduleCount) {
|
|
const buffer = Buffer.alloc(8);
|
|
buffer.writeUInt32LE(MAGIC_NUMBER, 0);
|
|
buffer.writeUInt32LE(moduleCount, 4);
|
|
return buffer;
|
|
}
|
|
function addModuleHeader(buffer) {
|
|
const { getFileLength } = require("metro-hermes-compiler");
|
|
const fileLength = getFileLength(buffer, 0);
|
|
const header = Buffer.alloc(4);
|
|
header.writeUInt32LE(fileLength, 0);
|
|
return [header, buffer];
|
|
}
|
|
|
|
/**
|
|
* A bytecode bundle has the following format:
|
|
*
|
|
* 4 bytes MAGIC_NUMBER
|
|
* 4 bytes Module count
|
|
* 4 bytes Module length N + N bytes
|
|
* ...
|
|
*
|
|
*/
|
|
function bundleToBytecode(bundle) {
|
|
const buffers = [];
|
|
if (bundle.pre.length) {
|
|
buffers.push(...bundle.pre);
|
|
}
|
|
const modules = [];
|
|
const sortedModules = bundle.modules
|
|
.slice()
|
|
// In a JS bundle, the order of modules needs to be deterministic for source
|
|
// maps to work. This constraint is not necessary for bytecode bundles but
|
|
// is kept for consistency.
|
|
.sort((a, b) => a[0] - b[0]);
|
|
for (const [id, bytecodeBundle] of sortedModules) {
|
|
buffers.push(...bytecodeBundle);
|
|
// Use the size of the last item in `bytecodeBundle` which is always
|
|
// the actual module without headers.
|
|
modules.push([id, bytecodeBundle[bytecodeBundle.length - 1].length]);
|
|
}
|
|
if (bundle.post.length) {
|
|
buffers.push(...bundle.post);
|
|
}
|
|
return {
|
|
bytecode: Buffer.concat([
|
|
getFileHeader(buffers.length),
|
|
...buffers.flatMap(addModuleHeader),
|
|
]),
|
|
metadata: {
|
|
pre: bundle.pre ? bundle.pre.length : 0,
|
|
post: bundle.post.length,
|
|
modules,
|
|
},
|
|
};
|
|
}
|
|
bundleToBytecode.MAGIC_NUMBER = MAGIC_NUMBER;
|
|
module.exports = bundleToBytecode;
|