Greetings all, For those of you who don't know, a new effort to migrate JS to TS has been going on for a few weeks new. Please follow along the discussion here: #8656.
My specific question here is with the emitText() function, which hijacks out:
Module['emitText'] = function(expr) {
if (typeof expr === 'object') {
return expr.emitText();
}
const old = out;
let ret = '';
out = x => { ret += x + '\n' };
Module['_BinaryenExpressionPrint'](expr);
out = old;
return ret;
};
Since this code is appended to the Emscripten preprocessed input, this mysterious out is able to be temporarily reassigned to a function that just updates the ret string.
(for reference:)
void BinaryenExpressionPrint(BinaryenExpressionRef expr) {
std::cout << *(Expression*)expr << '\n';
}
But seeing as the TS effort will not have access to those internals (see #8656), my current rewrite looks like this:
(adding out & err to the EXPORTED_RUNTIME_METHODS)
target_link_libraries(binaryen_js PRIVATE "-sEXPORTED_RUNTIME_METHODS=out,err,HEAP8,HEAPU8,HEAP32,HEAPU32,stackSave,stackRestore,stackAlloc,UTF8ToString,stringToAscii,stringToUTF8OnStack,getExceptionMessage")
target_link_libraries(binaryen_js PRIVATE "-sEXPORTED_FUNCTIONS=_malloc,_free,__i32_load")
(calling it "BinaryenObj" instead of "Module" to avoid confusion)
const BinaryenObj = await Binaryen();
export function emitText(expr: ExpressionRef): string {
let returned = "";
const temp_out = BinaryenObj.out;
BinaryenObj.out = (x: string): void => {
returned += `${ x }\n`;
};
BinaryenObj["_BinaryenExpressionPrint"](expr);
BinaryenObj.out = temp_out;
return returned;
}
The problem is, it doesn't do anything. Calling this function still prints the text to the console, and then returns an empty string. I guess that's because temporarily reassigning BinaryenObj.out doesn't actually hijack the internals used in BinaryenExpressionPrint.
So my hope is we can offer a new function in the C++ library to return the expression stringified, which could then just be pulled into the TS library. We already do this in the Module class:
char* BinaryenModuleAllocateAndWriteText(BinaryenModuleRef module) {
std::ostringstream os;
bool colors = Colors::isEnabled();
Colors::setEnabled(false); // do not use colors for writing
os << *(Module*)module;
Colors::setEnabled(colors); // restore colors state
auto str = os.str();
const size_t len = str.length() + 1;
char* output = (char*)malloc(len);
std::copy_n(str.c_str(), len, output);
return output;
}
function wrapModule(module, self = {}) {
// ...
self['emitText'] = function() {
let textPtr = Module['_BinaryenModuleAllocateAndWriteText'](module);
let text = UTF8ToString(textPtr);
if (textPtr) _free(textPtr);
return text;
};
}
(and my TS rewrite)
class Module {
emitText(): string {
const textPtr = BinaryenObj["_BinaryenModuleAllocateAndWriteText"](this[PTR]);
const text = UTF8ToString(textPtr);
if (textPtr) {
_free(textPtr);
}
return text;
}
}
Following this same pattern, we could have a new "BinaryenExpressionAllocateAndWriteText" function, which just spits out the string of the expression, and then I'd update the global emitText JS/TS function accordingly. Moreover, the original BinaryenExpressionPrint function could be updated to call that instead of duplicating code.
Please let me know if there'd be any problems with this approach. Thank you!
Greetings all, For those of you who don't know, a new effort to migrate JS to TS has been going on for a few weeks new. Please follow along the discussion here: #8656.
My specific question here is with the
emitText()function, which hijacksout:Since this code is appended to the Emscripten preprocessed input, this mysterious
outis able to be temporarily reassigned to a function that just updates theretstring.(for reference:)
But seeing as the TS effort will not have access to those internals (see #8656), my current rewrite looks like this:
(adding
out&errto theEXPORTED_RUNTIME_METHODS)(calling it "
BinaryenObj" instead of "Module" to avoid confusion)The problem is, it doesn't do anything. Calling this function still prints the text to the console, and then returns an empty string. I guess that's because temporarily reassigning
BinaryenObj.outdoesn't actually hijack the internals used inBinaryenExpressionPrint.So my hope is we can offer a new function in the C++ library to return the expression stringified, which could then just be pulled into the TS library. We already do this in the
Moduleclass:(and my TS rewrite)
Following this same pattern, we could have a new "
BinaryenExpressionAllocateAndWriteText" function, which just spits out the string of the expression, and then I'd update the globalemitTextJS/TS function accordingly. Moreover, the originalBinaryenExpressionPrintfunction could be updated to call that instead of duplicating code.Please let me know if there'd be any problems with this approach. Thank you!