aboutsummaryrefslogtreecommitdiff
path: root/src/library.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/library.js')
-rw-r--r--src/library.js187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/library.js b/src/library.js
index bdc0a39e..fc731e01 100644
--- a/src/library.js
+++ b/src/library.js
@@ -8835,6 +8835,193 @@ LibraryManager.library = {
}
},
+ // Returns [parentFuncArguments, functionName, paramListName]
+ _emscripten_traverse_stack: function(args) {
+ if (!args || !args.callee || !args.callee.name) {
+ return [null, '', ''];
+ }
+
+ var funstr = args.callee.toString();
+ var funcname = args.callee.name;
+ var str = '(';
+ var first = true;
+ for(i in args) {
+ var a = args[i];
+ if (!first) {
+ str += ", ";
+ }
+ first = false;
+ if (typeof a === 'number' || typeof a === 'string') {
+ str += a;
+ } else {
+ str += '(' + typeof a + ')';
+ }
+ }
+ str += ')';
+ args = args.callee.caller.arguments;
+ if (first)
+ str = '';
+ return [args, funcname, str];
+ },
+
+ emscripten_get_callstack_js__deps: ['_emscripten_traverse_stack'],
+ emscripten_get_callstack_js: function(flags) {
+ var err = new Error();
+ if (!err.stack) {
+ Runtime.warnOnce('emscripten_get_callstack_js is not supported on this browser!');
+ return '';
+ }
+ var callstack = new Error().stack.toString();
+
+ // Find the symbols in the callstack that corresponds to the functions that report callstack information, and remove everyhing up to these from the output.
+ var iThisFunc = callstack.lastIndexOf('_emscripten_log');
+ var iThisFunc2 = callstack.lastIndexOf('_emscripten_get_callstack');
+ var iNextLine = callstack.indexOf('\n', Math.max(iThisFunc, iThisFunc2))+1;
+ callstack = callstack.slice(iNextLine);
+
+ // If user requested to see the original source stack, but no source map information is available, just fall back to showing the JS stack.
+ if (flags & 8/*EM_LOG_C_STACK*/ && typeof emscripten_source_map === 'undefined') {
+ Runtime.warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.');
+ flags ^= 8/*EM_LOG_C_STACK*/;
+ flags |= 16/*EM_LOG_JS_STACK*/;
+ }
+
+ var stack_args = null;
+ if (flags & 128 /*EM_LOG_FUNC_PARAMS*/) {
+ // To get the actual parameters to the functions, traverse the stack via the unfortunately deprecated 'arguments.callee' method, if it works:
+ var stack_args = __emscripten_traverse_stack(arguments);
+ while (stack_args[1].indexOf('_emscripten_') >= 0)
+ stack_args = __emscripten_traverse_stack(stack_args[0]);
+ }
+
+ // Process all lines:
+ lines = callstack.split('\n');
+ callstack = '';
+ var firefoxRe = new RegExp('\\s*(.*?)@(.*):(.*)'); // Extract components of form ' Object._main@http://server.com:4324'
+ var chromeRe = new RegExp('\\s*at (.*?) \\\((.*):(.*):(.*)\\\)'); // Extract components of form ' at Object._main (http://server.com/file.html:4324:12)'
+
+ for(l in lines) {
+ var line = lines[l];
+
+ var jsSymbolName = '';
+ var file = '';
+ var lineno = 0;
+ var column = 0;
+
+ var parts = chromeRe.exec(line);
+ if (parts && parts.length == 5) {
+ jsSymbolName = parts[1];
+ file = parts[2];
+ lineno = parts[3];
+ column = parts[4];
+ } else {
+ parts = firefoxRe.exec(line);
+ if (parts && parts.length == 4) {
+ jsSymbolName = parts[1];
+ file = parts[2];
+ lineno = parts[3];
+ column = 0; // Firefox doesn't carry column information. See https://bugzilla.mozilla.org/show_bug.cgi?id=762556
+ } else {
+ // Was not able to extract this line for demangling/sourcemapping purposes. Output it as-is.
+ callstack += line + '\n';
+ continue;
+ }
+ }
+
+ // Try to demangle the symbol, but fall back to showing the original JS symbol name if not available.
+ var cSymbolName = (flags & 32/*EM_LOG_DEMANGLE*/) ? demangle(jsSymbolName) : jsSymbolName;
+ if (!cSymbolName) {
+ cSymbolName = jsSymbolName;
+ }
+
+ var haveSourceMap = false;
+
+ if (flags & 8/*EM_LOG_C_STACK*/) {
+ var orig = emscripten_source_map.originalPositionFor({line: lineno, column: column});
+ haveSourceMap = (orig && orig.source);
+ if (haveSourceMap) {
+ if (flags & 64/*EM_LOG_NO_PATHS*/) {
+ orig.source = orig.source.substring(orig.source.replace(/\\/g, "/").lastIndexOf('/')+1);
+ }
+ callstack += ' at ' + cSymbolName + ' (' + orig.source + ':' + orig.line + ':' + orig.column + ')\n';
+ }
+ }
+ if ((flags & 16/*EM_LOG_JS_STACK*/) || !haveSourceMap) {
+ if (flags & 64/*EM_LOG_NO_PATHS*/) {
+ file = file.substring(file.replace(/\\/g, "/").lastIndexOf('/')+1);
+ }
+ callstack += (haveSourceMap ? (' = '+jsSymbolName) : (' at '+cSymbolName)) + ' (' + file + ':' + lineno + ':' + column + ')\n';
+ }
+
+ // If we are still keeping track with the callstack by traversing via 'arguments.callee', print the function parameters as well.
+ if (flags & 128 /*EM_LOG_FUNC_PARAMS*/ && stack_args[0]) {
+ if (stack_args[1] == jsSymbolName && stack_args[2].length > 0) {
+ callstack = callstack.replace(/\s+$/, '');
+ callstack += ' with values: ' + stack_args[1] + stack_args[2] + '\n';
+ }
+ stack_args = __emscripten_traverse_stack(stack_args[0]);
+ }
+ }
+ // Trim extra whitespace at the end of the output.
+ callstack = callstack.replace(/\s+$/, '');
+ return callstack;
+ },
+
+ emscripten_get_callstack__deps: ['emscripten_get_callstack_js'],
+ emscripten_get_callstack: function(flags, str, maxbytes) {
+ var callstack = _emscripten_get_callstack_js(flags);
+ // User can query the required amount of bytes to hold the callstack.
+ if (!str || maxbytes <= 0) {
+ return callstack.length+1;
+ }
+ // Truncate output to avoid writing past bounds.
+ if (callstack.length > maxbytes-1) {
+ callstack.slice(0, maxbytes-1);
+ }
+ // Output callstack string as C string to HEAP.
+ writeStringToMemory(callstack, str, false);
+
+ // Return number of bytes written.
+ return callstack.length+1;
+ },
+
+ emscripten_log_js__deps: ['emscripten_get_callstack_js'],
+ emscripten_log_js: function(flags, str) {
+ if (flags & 24/*EM_LOG_C_STACK | EM_LOG_JS_STACK*/) {
+ str = str.replace(/\s+$/, ''); // Ensure the message and the callstack are joined cleanly with exactly one newline.
+ str += (str.length > 0 ? '\n' : '') + _emscripten_get_callstack_js(flags);
+ }
+
+ if (flags & 1 /*EM_LOG_CONSOLE*/) {
+ if (flags & 4 /*EM_LOG_ERROR*/) {
+ console.error(str);
+ } else if (flags & 2 /*EM_LOG_WARN*/) {
+ console.warn(str);
+ } else {
+ console.log(str);
+ }
+ } else if (flags & 6 /*EM_LOG_ERROR|EM_LOG_WARN*/) {
+ Module.printErr(str);
+ } else {
+ Module.print(str);
+ }
+ },
+
+ emscripten_log__deps: ['_formatString', 'emscripten_log_js'],
+ emscripten_log: function(flags, varargs) {
+ // Extract the (optionally-existing) printf format specifier field from varargs.
+ var format = {{{ makeGetValue('varargs', '0', 'i32', undefined, undefined, true) }}};
+ varargs += Math.max(Runtime.getNativeFieldSize('i32'), Runtime.getAlignSize('i32', null, true));
+ var str = '';
+ if (format) {
+ var result = __formatString(format, varargs);
+ for(var i = 0 ; i < result.length; ++i) {
+ str += String.fromCharCode(result[i]);
+ }
+ }
+ _emscripten_log_js(flags, str);
+ },
+
//============================
// emscripten vector ops
//============================