Skip to content
Go back

deepkit学习-bytecode生成

Updated:

在 compiler.ts 中,类型编码的主要流程如下:

  1. 首先在 ReflectionTransformer 类中的 packOpsAndStack 方法中进行打包:
protected packOpsAndStack(program: CompilerProgram) {
    const packStruct = program.buildPackStruct();
    if (packStruct.ops.length === 0) return;
    // debugPackStruct(this.sourceFile, program.forNode, packStruct);
    const packed = [...packStruct.stack, encodeOps(packStruct.ops)];
    return this.valueToExpression(packed);
}
  1. buildPackStruct 方法在 CompilerProgram 类中:
buildPackStruct() {
    const ops: ReflectionOp[] = [...this.ops];

    if (this.coRoutines.length) {
        for (let i = this.coRoutines.length - 1; i >= 0; i--) {
            ops.unshift(...this.coRoutines[i].ops);
        }
    }

    if (this.mainOffset) {
        ops.unshift(ReflectionOp.jump, this.mainOffset);
    }

    return { ops, stack: this.stack };
}

关键的编码函数是 encodeOps:

export function encodeOps(ops: ReflectionOp[]): string {
    return ops.map(v => String.fromCharCode(v + 33)).join('');
}

编码的基本原理是:

  1. 收集类型信息时会生成一系列操作码(ReflectionOp)和相关的栈数据
  2. 操作码通过 encodeOps 函数编码成字符串:
    • 每个操作码加33后转换为ASCII字符
    • 33是为了避开控制字符,使得编码后的字符都是可打印字符
  3. 最终生成的类型信息是一个数组,包含:
    • 栈数据(类型名称、参数等)
    • 编码后的操作码字符串

例如测试用例:

interface User {
    id: number;
    name: string;
    password: string;
}
type ReadUser = Omit<User, 'password'>;

编码过程大致是:

  1. 解析AST生成操作码序列
  2. 将操作码编码为字符串
  3. 与栈数据一起组成最终的类型信息数组

Suggest Changes

Previous Post
deepkit的复杂类型例子
Next Post
deepkit协程学习