在Duktape中,如何将JS源文件内容转换为字节码

时间:2016-04-06 09:09:42

标签: javascript c++ duktape

我想知道下面描述的步骤是如何完成的:

  1. 如何将JS源文件(带有两个函数的test.js,funcA()和funcB())转换为字节码?
  2. 如何将生成的字节码加载到duktape并调用其中一个函数,比如funcA()?
  3. 感谢。

    test.js:

    function funcA() {
        print("funcA()");
    }
    
    function funcB() {
        print("funcB()");
    }
    

    的main.cpp

    int main() {
        duk_context* ctx = duk_create_heap_default();
    
        std::string byteCodeBuff; // buffer where to save the byte code;
    
        { // generate the bytecode from 'sourceFilePath'
    
            const char* sourceCodeFilePath = "test.js"; // contains the JS code
            //  Step 1 How to 'dump' the 'sourceFilePath' to bytecode buffer ???
    
            // get the duktape bytecode
            duk_size_t bufferSize = 0;
            const char* bytecode = (const char*)duk_get_buffer(ctx, -1, &bufferSize);
    
            // save the bytecode to byteCodeBuff 
            byteCodeBuff.assign(bytecode,bufferSize);
    
            duk_pop(ctx);  // bytecode buffer
        }
    
        { // load the bytecode into duktape
    
            const size_t length = byteCodeBuff.size();    // bytecode length
            const char* bytecode = &byteCodeBuff.front(); // pointer to bytecode 
    
            char* dukBuff = (char*)duk_push_fixed_buffer(ctx, length); // push a duk buffer to stack
            memcpy(dukBuff, bytecode, length); // copy the bytecode to the duk buffer
    
            // Step 2 ??? How start using the bytecode
            // ??? How to invoke funcA()
            // ??? How to invoke funcB()
        }
    
        duk_destroy_heap(ctx);
    
        return 0;
    }
    

1 个答案:

答案 0 :(得分:1)

duk_dump_functionduk_load_function是Duktape提供的用于转换为字节码的功能:

首先,只需加载您的文件:

//  Step 1 (a):
char* sourceCode;
int sourceLen;
{ // load from file (excuse lack of error catching...)
    ifstream fscript(sourceCodeFilePath,ios::in | ios::binary);
    fscript.seekg(0,ios::end);
    sourceLen= fscript.tellg();
    buffer = new char[sourceLen];
    fscript.seekg(0);
    fscript.read(sourceCode,sourceLen);
}

然后,在编译javascript时,脚本被编译为'功能' (实际上是一块未执行的全局代码)到堆栈中:

//  Step 1 (b):

// compile source code
duk_compile_lstring(ctx,0,sourceCode,sourceLen); // compiles to an ECMAScript function and puts it on the stack top

// dump the code into a buffer
duk_dump_function(ctx); // replaces the stack top function with its bytecode

从这一点开始,代码的其余部分应该在堆栈顶部拾取缓冲区。

至于恢复它:

//  Step 2 (a):
// replaces the buffer on the stack top with the original function
duk_load_function(ctx);

// since this is a global script, it must be executed before calling the invidual functions
duk_call(ctx,0); // perhaps consider using duk_pcall() instead

此时,ctx堆的全局对象现在包含属性funcAfuncB。 这些可以这样获得和调用:

//  Step 2 (b):
// push the global object on the stack to get its properties
duk_push_global_object(ctx);

// obtain the function with the name "funcA" and push it on the stack
duk_get_prop_string(ctx,-1,"funcA"); // key name / global function name

duk_require_function(ctx,-1); // require this is a function before calling it

// now invoke it!
// duk_push_* arguments here
duk_call(ctx,0); // 0: number of arguments

// duk_get_* (ctx,-1); to obtain return value

// pop function return value
duk_pop(ctx);

// current stack top: global object

// get next function
duk_get_prop_string(ctx,-1,"funcB");

// require it's a function
duk_require_function(ctx,-1);

// invoke it!
duk_call(ctx,0);

// pop return and global object off stack
duk_pop_2(ctx);