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

/**
* 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;