This reverts commit8d1ff873d8. Revert "Binding fix" This reverts commitc606ec5139. Revert "Add support for HL libraries" This reverts commit6b49f4d240. Revert "Minor fixes" This reverts commitdcacb9f04a. Revert "Compile fixes" This reverts commit3b9e572f8b. Revert "Sync with Haxe std library (remove some overrides)" This reverts commitc05061c970. Revert "Initial support for HL target in tools (for testing)" This reverts commit1dadbb725c.
352 lines
9.9 KiB
Haxe
352 lines
9.9 KiB
Haxe
/*
|
|
* Copyright (C)2005-2012 Haxe Foundation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
package haxe;
|
|
|
|
/**
|
|
Elements return by `CallStack` methods.
|
|
**/
|
|
enum StackItem {
|
|
CFunction;
|
|
Module( m : String );
|
|
FilePos( s : Null<StackItem>, file : String, line : Int );
|
|
Method( classname : String, method : String );
|
|
LocalFunction( ?v : Int );
|
|
}
|
|
|
|
/**
|
|
Get informations about the call stack.
|
|
**/
|
|
class CallStack {
|
|
#if js
|
|
static var lastException:js.Error;
|
|
|
|
static function getStack(e:js.Error):Array<StackItem> {
|
|
if (e == null) return [];
|
|
// https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
|
|
var oldValue = (untyped Error).prepareStackTrace;
|
|
(untyped Error).prepareStackTrace = function (error, callsites :Array<Dynamic>) {
|
|
var stack = [];
|
|
for (site in callsites) {
|
|
if (wrapCallSite != null) site = wrapCallSite(site);
|
|
var method = null;
|
|
var fullName :String = site.getFunctionName();
|
|
if (fullName != null) {
|
|
var idx = fullName.lastIndexOf(".");
|
|
if (idx >= 0) {
|
|
var className = fullName.substr(0, idx);
|
|
var methodName = fullName.substr(idx+1);
|
|
method = Method(className, methodName);
|
|
}
|
|
}
|
|
stack.push(FilePos(method, site.getFileName(), site.getLineNumber()));
|
|
}
|
|
return stack;
|
|
}
|
|
var a = makeStack(e.stack);
|
|
(untyped Error).prepareStackTrace = oldValue;
|
|
return a;
|
|
}
|
|
|
|
// support for source-map-support module
|
|
@:noCompletion
|
|
public static var wrapCallSite:Dynamic->Dynamic;
|
|
#end
|
|
|
|
/**
|
|
Return the call stack elements, or an empty array if not available.
|
|
**/
|
|
public static function callStack() : Array<StackItem> {
|
|
#if neko
|
|
var a = makeStack(untyped __dollar__callstack());
|
|
a.shift(); // remove Stack.callStack()
|
|
return a;
|
|
#elseif flash
|
|
var a = makeStack( new flash.errors.Error().getStackTrace() );
|
|
a.shift(); // remove Stack.callStack()
|
|
return a;
|
|
#elseif php
|
|
return makeStack("%s");
|
|
#elseif cpp
|
|
var s:Array<String> = untyped __global__.__hxcpp_get_call_stack(true);
|
|
return makeStack(s);
|
|
#elseif js
|
|
try {
|
|
throw new js.Error();
|
|
} catch( e : Dynamic ) {
|
|
var a = getStack(e);
|
|
a.shift(); // remove Stack.callStack()
|
|
return a;
|
|
}
|
|
|
|
#elseif java
|
|
var stack = [];
|
|
for ( el in java.lang.Thread.currentThread().getStackTrace() ) {
|
|
var className = el.getClassName();
|
|
var methodName = el.getMethodName();
|
|
var fileName = el.getFileName();
|
|
var lineNumber = el.getLineNumber();
|
|
var method = Method( className, methodName );
|
|
if ( fileName != null || lineNumber >= 0 ) {
|
|
stack.push( FilePos( method, fileName, lineNumber ) );
|
|
}
|
|
else {
|
|
stack.push( method );
|
|
}
|
|
}
|
|
stack.shift();
|
|
stack.shift();
|
|
stack.pop();
|
|
return stack;
|
|
#elseif cs
|
|
return makeStack(new cs.system.diagnostics.StackTrace(1, true));
|
|
#elseif python
|
|
var stack = [];
|
|
var infos = python.lib.Traceback.extract_stack();
|
|
infos.pop();
|
|
infos.reverse();
|
|
for (elem in infos)
|
|
stack.push(FilePos(null, elem._1, elem._2));
|
|
return stack;
|
|
#else
|
|
return []; // Unsupported
|
|
#end
|
|
}
|
|
|
|
/**
|
|
Return the exception stack : this is the stack elements between
|
|
the place the last exception was thrown and the place it was
|
|
caught, or an empty array if not available.
|
|
**/
|
|
#if cpp @:noStack #end /* Do not mess up the exception stack */
|
|
public static function exceptionStack() : Array<StackItem> {
|
|
#if neko
|
|
return makeStack(untyped __dollar__excstack());
|
|
#elseif as3
|
|
return new Array();
|
|
#elseif flash
|
|
var err : flash.errors.Error = untyped flash.Boot.lastError;
|
|
if( err == null ) return new Array();
|
|
var a = makeStack( err.getStackTrace() );
|
|
var c = callStack();
|
|
var i = c.length - 1;
|
|
while( i > 0 ) {
|
|
if( Std.string(a[a.length-1]) == Std.string(c[i]) )
|
|
a.pop();
|
|
else
|
|
break;
|
|
i--;
|
|
}
|
|
return a;
|
|
#elseif php
|
|
return makeStack("%e");
|
|
#elseif cpp
|
|
var s:Array<String> = untyped __global__.__hxcpp_get_exception_stack();
|
|
return makeStack(s);
|
|
#elseif java
|
|
var stack = [];
|
|
for ( el in java.internal.Exceptions.currentException().getStackTrace() ) {
|
|
var className = el.getClassName();
|
|
var methodName = el.getMethodName();
|
|
var fileName = el.getFileName();
|
|
var lineNumber = el.getLineNumber();
|
|
var method = Method( className, methodName );
|
|
if ( fileName != null || lineNumber >= 0 ) {
|
|
stack.push( FilePos( method, fileName, lineNumber ) );
|
|
}
|
|
else {
|
|
stack.push( method );
|
|
}
|
|
}
|
|
// stack.shift();
|
|
stack.shift();
|
|
stack.pop();
|
|
return stack;
|
|
#elseif cs
|
|
return makeStack(new cs.system.diagnostics.StackTrace(cs.internal.Exceptions.exception, true));
|
|
#elseif python
|
|
var stack = [];
|
|
var exc = python.lib.Sys.exc_info();
|
|
if (exc._3 != null)
|
|
{
|
|
var infos = python.lib.Traceback.extract_tb(exc._3);
|
|
infos.reverse();
|
|
for (elem in infos)
|
|
stack.push(FilePos(null, elem._1, elem._2));
|
|
}
|
|
return stack;
|
|
#elseif js
|
|
return untyped __define_feature__("haxe.CallStack.exceptionStack", getStack(lastException));
|
|
#else
|
|
return []; // Unsupported
|
|
#end
|
|
}
|
|
|
|
/**
|
|
Returns a representation of the stack as a printable string.
|
|
**/
|
|
public static function toString( stack : Array<StackItem> ) {
|
|
var b = new StringBuf();
|
|
#if cpp
|
|
stack = stack.copy ();
|
|
stack.reverse();
|
|
#end
|
|
for( s in stack ) {
|
|
b.add("\nCalled from ");
|
|
itemToString(b,s);
|
|
}
|
|
return b.toString();
|
|
}
|
|
|
|
private static function itemToString( b : StringBuf, s ) {
|
|
switch( s ) {
|
|
case CFunction:
|
|
b.add("a C function");
|
|
case Module(m):
|
|
b.add("module ");
|
|
b.add(m);
|
|
case FilePos(s,file,line):
|
|
if( s != null ) {
|
|
itemToString(b,s);
|
|
b.add(" (");
|
|
}
|
|
b.add(file);
|
|
b.add(" line ");
|
|
b.add(line);
|
|
if( s != null ) b.add(")");
|
|
case Method(cname,meth):
|
|
b.add(cname);
|
|
b.add(".");
|
|
b.add(meth);
|
|
case LocalFunction(n):
|
|
b.add("local function #");
|
|
b.add(n);
|
|
}
|
|
}
|
|
|
|
#if cpp @:noStack #end /* Do not mess up the exception stack */
|
|
private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #end) {
|
|
#if neko
|
|
var a = new Array();
|
|
var l = untyped __dollar__asize(s);
|
|
var i = 0;
|
|
while( i < l ) {
|
|
var x = s[i++];
|
|
if( x == null )
|
|
a.unshift(CFunction);
|
|
else if( untyped __dollar__typeof(x) == __dollar__tstring )
|
|
a.unshift(Module(new String(x)));
|
|
else
|
|
a.unshift(FilePos(null,new String(untyped x[0]),untyped x[1]));
|
|
}
|
|
return a;
|
|
#elseif flash
|
|
var a = new Array();
|
|
var r = ~/at ([^\/]+?)\$?(\/[^\(]+)?\(\)(\[(.*?):([0-9]+)\])?/;
|
|
var rlambda = ~/^MethodInfo-([0-9]+)$/g;
|
|
while( r.match(s) ) {
|
|
var cl = r.matched(1).split("::").join(".");
|
|
var meth = r.matched(2);
|
|
var item;
|
|
if( meth == null ) {
|
|
if( rlambda.match(cl) )
|
|
item = LocalFunction(Std.parseInt(rlambda.matched(1)));
|
|
else
|
|
item = Method(cl,"new");
|
|
} else
|
|
item = Method(cl,meth.substr(1));
|
|
if( r.matched(3) != null )
|
|
item = FilePos( item, r.matched(4), Std.parseInt(r.matched(5)) );
|
|
a.push(item);
|
|
s = r.matchedRight();
|
|
}
|
|
return a;
|
|
#elseif php
|
|
if (!untyped __call__("isset", __var__("GLOBALS", s)))
|
|
return [];
|
|
var a : Array<String> = untyped __var__("GLOBALS", s);
|
|
var m = [];
|
|
for( i in 0...a.length - ((s == "%s") ? 2 : 0)) {
|
|
var d = a[i].split("::");
|
|
m.unshift(Method(d[0],d[1]));
|
|
}
|
|
return m;
|
|
#elseif cpp
|
|
var stack : Array<String> = s;
|
|
var m = new Array<StackItem>();
|
|
for(func in stack) {
|
|
var words = func.split("::");
|
|
if (words.length==0)
|
|
m.push(CFunction)
|
|
else if (words.length==2)
|
|
m.push(Method(words[0],words[1]));
|
|
else if (words.length==4)
|
|
m.push(FilePos( Method(words[0],words[1]),words[2],Std.parseInt(words[3])));
|
|
}
|
|
return m;
|
|
#elseif js
|
|
if (s == null) {
|
|
return [];
|
|
} else if ((untyped __js__("typeof"))(s) == "string") {
|
|
// Return the raw lines in browsers that don't support prepareStackTrace
|
|
var stack : Array<String> = s.split("\n");
|
|
if( stack[0] == "Error" ) stack.shift();
|
|
var m = [];
|
|
var rie10 = ~/^ at ([A-Za-z0-9_. ]+) \(([^)]+):([0-9]+):([0-9]+)\)$/;
|
|
for( line in stack ) {
|
|
if( rie10.match(line) ) {
|
|
var path = rie10.matched(1).split(".");
|
|
var meth = path.pop();
|
|
var file = rie10.matched(2);
|
|
var line = Std.parseInt(rie10.matched(3));
|
|
m.push(FilePos( meth == "Anonymous function" ? LocalFunction() : meth == "Global code" ? null : Method(path.join("."),meth), file, line ));
|
|
} else
|
|
m.push(Module(StringTools.trim(line))); // A little weird, but better than nothing
|
|
}
|
|
return m;
|
|
} else {
|
|
return cast s;
|
|
}
|
|
#elseif cs
|
|
var stack = [];
|
|
for (i in 0...s.FrameCount)
|
|
{
|
|
var frame = s.GetFrame(i);
|
|
var m = frame.GetMethod();
|
|
|
|
var method = StackItem.Method(m.ReflectedType.ToString(), m.Name);
|
|
|
|
var fileName = frame.GetFileName();
|
|
var lineNumber = frame.GetFileLineNumber();
|
|
|
|
if (fileName != null || lineNumber >= 0)
|
|
stack.push(FilePos(method, fileName, lineNumber));
|
|
else
|
|
stack.push(method);
|
|
}
|
|
return stack;
|
|
#else
|
|
return null;
|
|
#end
|
|
}
|
|
|
|
}
|