2016-04-06 14 views
2

Bytecode Ich würde gerne wissen, wie der Schritt weiter unten beschrieben werden durchgeführt:In Duktape, wie ein JS-Quelldatei Inhalt konvertieren

  1. Wie eine JS-Quelldatei (test.js mit zwei Funktionen konvertieren, funcA() und funcB()) zu Bytecode?
  2. Wie laden Sie den generierten Bytecode in duktape und rufen eine der Funktionen auf, sagen wir funcA()?

Danke.

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; 
} 

Antwort

1

duk_dump_function und duk_load_function sind die von Duktape bereitgestellten Funktionen zu und von Bytecode zu konvertieren:

Zuerst laden Sie einfach Ihre Datei:

 
// 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); 
} 

Dann, wenn Sie Javascript kompiliert, wird das Skript als eine ‚Funktion‘ (wirklich ein Stück unausgeführt globalen Code) auf den Stapel zusammengestellt:

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

Von diesem Punkt wird der Rest des Codes den Puffer abholen sollte auf dem Stapel oben.

Da es für die Wiederherstellung:

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

An diesem Punkt der ctx Haufen des globalen Objekts enthält nun die Eigenschaften funcA und funcB. Diese können als solche erhalten und aufgerufen werden:

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