Skip to content

Commit

Permalink
feat: rewrite fs.lua in JavaScript(node)
Browse files Browse the repository at this point in the history
  • Loading branch information
XuJiandong committed Dec 27, 2024
1 parent 0619065 commit 87aed28
Show file tree
Hide file tree
Showing 7 changed files with 546 additions and 4 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ jobs:
chmod +x llvm.sh
sudo ./llvm.sh 18
rm llvm.sh
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Build
run: make all
- name: Install tools
Expand All @@ -25,7 +29,6 @@ jobs:
run: make test
- name: Benchmark
run: make benchmark

macos:
runs-on: macos-latest

Expand Down
6 changes: 3 additions & 3 deletions tests/ckb_js_tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ module: spawn_caller
cargo run --bin module | ${CKB_DEBUGGER} --tx-file=- -s lock

build/bytecode/fs_modules.fs: test_data/fs_module/main.js test_data/fs_module/fib_module.js
cd test_data/fs_module && lua ../../../../tools/fs.lua pack ../../../../$@ main.js fib_module.js
cd test_data/fs_module && node ../../../../tools/fs-packer/dist/index.js pack ../../../../$@ main.js fib_module.js

fs_bytecode:
$(CKB_DEBUGGER) --read-file test_data/fs_module/main.js --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > ../../build/bytecode/main.bc
$(CKB_DEBUGGER) --read-file test_data/fs_module/fib_module.js --bin $(BIN_PATH) -- -c | awk -f $(ROOT_DIR)/../../tools/compile.awk | xxd -r -p > ../../build/bytecode/fib_module.bc
cd ../../build/bytecode && lua ../../tools/fs.lua pack ../../build/bytecode/fs_modules_bc.fs main.bc fib_module.bc
cd ../../build/bytecode && node ../../tools/fs-packer/dist/index.js pack ../../build/bytecode/fs_modules_bc.fs main.bc fib_module.bc
$(CKB_DEBUGGER) --max-cycles $(MAX_CYCLES) --read-file ../../build/bytecode/fs_modules_bc.fs --bin $(BIN_PATH) -- -f -r 2>&1 | fgrep 'Run result: 0'

file_system: build/bytecode/fs_modules.fs
Expand All @@ -39,7 +39,7 @@ syscall:
cargo run --bin syscall | $(CKB_DEBUGGER) --tx-file=- -s lock

fs_mount:
cd test_data/fs_module_mount && lua ../../../../tools/fs.lua pack ../../../../build/bytecode/fib_module.fs fib_module.js
cd test_data/fs_module_mount && node ../../../../tools/fs-packer/dist/index.js pack ../../../../build/bytecode/fib_module.fs fib_module.js
cargo run --bin module_mount | ${CKB_DEBUGGER} --tx-file=- -s lock

simple_udt:
Expand Down
3 changes: 3 additions & 0 deletions tools/fs-packer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
test.pak
test-output
180 changes: 180 additions & 0 deletions tools/fs-packer/dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pack = pack;
exports.unpack = unpack;
var fs = require("fs");
var path = require("path");
function getFileSize(filePath) {
var stats = fs.statSync(filePath);
return stats.size;
}
function appendToStream(data, stream) {
stream.write(data);
}
function appendFileToStream(filePath, stream) {
var content = fs.readFileSync(filePath);
appendToStream(content, stream);
}
function appendStringNullToStream(str, stream) {
var buffer = Buffer.from(str + '\0');
appendToStream(buffer, stream);
}
function appendIntegerToStream(num, stream) {
var buffer = Buffer.alloc(4);
buffer.writeInt32LE(num);
appendToStream(buffer, stream);
}
function pack(files, outputStream) {
var numFiles = Object.keys(files).length;
appendIntegerToStream(numFiles, outputStream);
var offset = 0;
var length = 0;
// Write metadata
for (var _i = 0, _a = Object.entries(files); _i < _a.length; _i++) {
var _b = _a[_i], name_1 = _b[0], filePath = _b[1];
console.log("packing file ".concat(filePath, " to ").concat(name_1));
appendIntegerToStream(offset, outputStream);
length = Buffer.byteLength(name_1) + 1; // include null terminator
appendIntegerToStream(length, outputStream);
offset += length;
appendIntegerToStream(offset, outputStream);
length = getFileSize(filePath);
appendIntegerToStream(length, outputStream);
offset += length;
}
// Write actual file data
for (var _c = 0, _d = Object.entries(files); _c < _d.length; _c++) {
var _e = _d[_c], name_2 = _e[0], filePath = _e[1];
appendStringNullToStream(name_2, outputStream);
appendFileToStream(filePath, outputStream);
}
}
function createDirectory(dir) {
fs.mkdirSync(dir, { recursive: true });
}
function unpack(directory, fileContent) {
var position = 0;
function readInteger() {
var value = fileContent.readInt32LE(position);
position += 4;
return value;
}
function readStringNull(length) {
var value = fileContent.toString('utf8', position, position + length).replace(/\0$/, '');
position += length;
return value;
}
function copyToFile(directory, filename, offset, length) {
var normalizedFilename = filename.replace(/\//g, path.sep);
var filePath = path.join(directory, normalizedFilename);
var dir = path.dirname(filePath);
createDirectory(dir);
console.log("unpacking file ".concat(filename, " to ").concat(filePath));
var content = fileContent.slice(offset, offset + length);
fs.writeFileSync(filePath, content);
}
var numFiles = readInteger();
var metadata = [];
// Read metadata
for (var i = 0; i < numFiles; i++) {
metadata.push({
fileNameOffset: readInteger(),
fileNameLength: readInteger(),
fileContentOffset: readInteger(),
fileContentLength: readInteger()
});
}
var blobStart = position;
for (var _i = 0, metadata_1 = metadata; _i < metadata_1.length; _i++) {
var metadatum = metadata_1[_i];
position = blobStart + metadatum.fileNameOffset;
var filename = readStringNull(metadatum.fileNameLength);
position = blobStart + metadatum.fileContentOffset;
copyToFile(directory, filename, position, metadatum.fileContentLength);
}
}
function isIdealPath(path) {
return !path.startsWith('/') &&
!path.startsWith('..') &&
!/^[a-zA-Z]:/.test(path);
}
function normalizeRelativePath(path) {
return path.replace(/^\.\//, '')
.replace(/\/\.\//g, '/');
}
function mustNormalizePath(path) {
if (!isIdealPath(path)) {
throw new Error("Either not a relative path or a relative path referring to ..: ".concat(path));
}
return normalizeRelativePath(path);
}
// Add CLI functionality
function usage(msg) {
if (msg)
console.log(msg);
console.log("".concat(process.argv[1], " pack output_file [files] | ").concat(process.argv[1], " unpack input_file [directory]"));
}
function doPack() {
if (process.argv.length === 2) {
usage('You must specify the output file.');
process.exit(1);
}
var outfile = process.argv[3];
var stream = fs.createWriteStream(outfile);
var files = {};
var n = 0;
if (process.argv.length !== 3) {
// Read files from command line arguments
for (var i = 4; i < process.argv.length; i++) {
n++;
var file = process.argv[i];
files[mustNormalizePath(file)] = file;
}
}
else {
// Read files from stdin
var input = fs.readFileSync(0, 'utf-8'); // 0 is stdin
for (var _i = 0, _a = input.split('\n').filter(Boolean); _i < _a.length; _i++) {
var file = _a[_i];
n++;
files[mustNormalizePath(file)] = file;
}
}
if (n === 0) {
usage('You must at least specify one file to pack');
process.exit(1);
}
pack(files, stream);
stream.end();
}
function doUnpack() {
if (process.argv.length === 2) {
usage('You must specify the input file when unpacking.');
process.exit(1);
}
var infile = process.argv[3];
if (!fs.existsSync(infile)) {
console.error("Error: File '".concat(infile, "' does not exist"));
process.exit(1);
}
var fileContent = fs.readFileSync(infile);
var directory = process.argv.length !== 3 ? process.argv[4] : '.';
unpack(directory, fileContent);
}
// Main program
function main() {
if (process.argv.length <= 2 || !['pack', 'unpack'].includes(process.argv[2])) {
usage('Please specify whether to pack or unpack');
process.exit(1);
}
if (process.argv[2] === 'pack') {
doPack();
}
else {
doUnpack();
}
}
// Only run if this is the main module
if (require.main === module) {
main();
}
16 changes: 16 additions & 0 deletions tools/fs-packer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "fs-packer",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "tsc src/index.ts --outDir dist",
"pretty": "prettier --write src/**/*.ts",
"test:pack": "node dist/index.js pack test.pak dist/index.js src/index.ts",
"test:unpack": "node dist/index.js unpack test.pak test-output",
"test:compare": "cmp dist/index.js test-output/dist/index.js && cmp src/index.ts test-output/src/index.ts && echo 'passed'"
},
"author": "",
"license": "ISC",
"description": ""
}

Loading

0 comments on commit 87aed28

Please sign in to comment.