Skip to content

Commit db7dc25

Browse files
fix leaking platform-specific code into macro context (fixes #10)
1 parent 6e5cc0c commit db7dc25

File tree

4 files changed

+111
-88
lines changed

4 files changed

+111
-88
lines changed

format/js/haxe/CallStack.hx

Lines changed: 92 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,107 @@
11
package haxe;
22

33
enum StackItem {
4-
CFunction;
5-
Module( m : String );
6-
FilePos( s : Null<StackItem>, file : String, line : Int );
7-
Method( classname : String, method : String );
8-
LocalFunction( ?v : Int );
4+
CFunction;
5+
Module( m : String );
6+
FilePos( s : Null<StackItem>, file : String, line : Int );
7+
Method( classname : String, method : String );
8+
LocalFunction( ?v : Int );
99
}
1010

1111
/**
12-
Get information about the call stack.
12+
Get information about the call stack.
1313
**/
1414
class CallStack {
15-
static var lastException:js.Error;
15+
#if js
16+
static var lastException:js.Error;
1617

17-
static function getStack(e:js.Error):Array<StackItem> {
18-
if (e == null) return [];
19-
// https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
20-
var oldValue = (untyped Error).prepareStackTrace;
21-
(untyped Error).prepareStackTrace = function (error, callsites :Array<Dynamic>) {
22-
var stack = [];
23-
for (site in callsites) {
24-
if (wrapCallSite != null) site = wrapCallSite(site);
25-
var method = null;
26-
var fullName :String = site.getFunctionName();
27-
if (fullName != null) {
28-
var idx = fullName.lastIndexOf(".");
29-
if (idx >= 0) {
30-
var className = fullName.substr(0, idx);
31-
var methodName = fullName.substr(idx+1);
32-
method = Method(className, methodName);
33-
}
34-
}
35-
stack.push(FilePos(method, site.getFileName(), site.getLineNumber()));
36-
}
37-
return stack;
38-
}
39-
var a = makeStack(e.stack);
40-
(untyped Error).prepareStackTrace = oldValue;
41-
return a;
42-
}
18+
static function getStack(e:js.Error):Array<StackItem> {
19+
if (e == null) return [];
20+
// https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
21+
var oldValue = (untyped Error).prepareStackTrace;
22+
(untyped Error).prepareStackTrace = function (error, callsites :Array<Dynamic>) {
23+
var stack = [];
24+
for (site in callsites) {
25+
if (wrapCallSite != null) site = wrapCallSite(site);
26+
var method = null;
27+
var fullName :String = site.getFunctionName();
28+
if (fullName != null) {
29+
var idx = fullName.lastIndexOf(".");
30+
if (idx >= 0) {
31+
var className = fullName.substr(0, idx);
32+
var methodName = fullName.substr(idx+1);
33+
method = Method(className, methodName);
34+
}
35+
}
36+
stack.push(FilePos(method, site.getFileName(), site.getLineNumber()));
37+
}
38+
return stack;
39+
}
40+
var a = makeStack(e.stack);
41+
(untyped Error).prepareStackTrace = oldValue;
42+
return a;
43+
}
4344

44-
// support for source-map-support module
45-
@:noCompletion
46-
public static var wrapCallSite:Dynamic->Dynamic;
45+
// support for source-map-support module
46+
@:noCompletion
47+
public static var wrapCallSite:Dynamic->Dynamic;
4748

48-
/**
49-
Return the call stack elements, or an empty array if not available.
50-
**/
51-
public static function callStack() : Array<StackItem> {
52-
try {
53-
throw new js.Error();
54-
} catch( e : Dynamic ) {
55-
var a = getStack(e);
56-
a.shift(); // remove Stack.callStack()
57-
return a;
58-
}
59-
}
49+
/**
50+
Return the call stack elements, or an empty array if not available.
51+
**/
52+
public static function callStack() : Array<StackItem> {
53+
try {
54+
throw new js.Error();
55+
} catch( e : Dynamic ) {
56+
var a = getStack(e);
57+
a.shift(); // remove Stack.callStack()
58+
return a;
59+
}
60+
}
6061

61-
/**
62-
Return the exception stack : this is the stack elements between
63-
the place the last exception was thrown and the place it was
64-
caught, or an empty array if not available.
65-
**/
66-
public static function exceptionStack() : Array<StackItem> {
67-
return untyped __define_feature__("haxe.CallStack.exceptionStack", getStack(lastException));
68-
}
62+
/**
63+
Return the exception stack : this is the stack elements between
64+
the place the last exception was thrown and the place it was
65+
caught, or an empty array if not available.
66+
**/
67+
public static function exceptionStack() : Array<StackItem> {
68+
return untyped __define_feature__("haxe.CallStack.exceptionStack", getStack(lastException));
69+
}
6970

70-
/**
71-
Returns a representation of the stack as a printable string.
72-
**/
73-
public static function toString( stack : Array<StackItem> ) {
74-
return jstack.Format.toString(stack);
75-
}
76-
77-
private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #elseif hl : hl.NativeArray<hl.Bytes> #end) {
78-
if (s == null) {
79-
return [];
80-
} else if ((untyped __js__("typeof"))(s) == "string") {
81-
// Return the raw lines in browsers that don't support prepareStackTrace
82-
var stack : Array<String> = s.split("\n");
83-
if( stack[0] == "Error" ) stack.shift();
84-
var m = [];
85-
var rie10 = ~/^ at ([A-Za-z0-9_. ]+) \(([^)]+):([0-9]+):([0-9]+)\)$/;
86-
for( line in stack ) {
87-
if( rie10.match(line) ) {
88-
var path = rie10.matched(1).split(".");
89-
var meth = path.pop();
90-
var file = rie10.matched(2);
91-
var line = Std.parseInt(rie10.matched(3));
92-
m.push(FilePos( meth == "Anonymous function" ? LocalFunction() : meth == "Global code" ? null : Method(path.join("."),meth), file, line ));
93-
} else
94-
m.push(Module(StringTools.trim(line))); // A little weird, but better than nothing
95-
}
96-
return m;
97-
} else {
98-
return cast s;
99-
}
100-
}
71+
/**
72+
Returns a representation of the stack as a printable string.
73+
**/
74+
public static function toString( stack : Array<StackItem> ) {
75+
return jstack.Format.toString(stack);
76+
}
10177

78+
private static function makeStack(s #if cs : cs.system.diagnostics.StackTrace #elseif hl : hl.NativeArray<hl.Bytes> #end) {
79+
if (s == null) {
80+
return [];
81+
} else if ((untyped __js__("typeof"))(s) == "string") {
82+
// Return the raw lines in browsers that don't support prepareStackTrace
83+
var stack : Array<String> = s.split("\n");
84+
if( stack[0] == "Error" ) stack.shift();
85+
var m = [];
86+
var rie10 = ~/^ at ([A-Za-z0-9_. ]+) \(([^)]+):([0-9]+):([0-9]+)\)$/;
87+
for( line in stack ) {
88+
if( rie10.match(line) ) {
89+
var path = rie10.matched(1).split(".");
90+
var meth = path.pop();
91+
var file = rie10.matched(2);
92+
var line = Std.parseInt(rie10.matched(3));
93+
m.push(FilePos( meth == "Anonymous function" ? LocalFunction() : meth == "Global code" ? null : Method(path.join("."),meth), file, line ));
94+
} else
95+
m.push(Module(StringTools.trim(line))); // A little weird, but better than nothing
96+
}
97+
return m;
98+
} else {
99+
return cast s;
100+
}
101+
}
102+
#else
103+
static public function callStack():Array<StackItem> throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
104+
static public function exceptionStack():Array<StackItem> throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
105+
static public function toString():String throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
106+
#end
102107
}

format/php7/haxe/CallStack.hx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package haxe;
22

3+
#if (php7 && !macro)
34
import php.*;
45

56
private typedef NativeTrace = NativeIndexedArray<NativeAssocArray<Dynamic>>;
7+
#end
68

79
/**
810
Elements return by `CallStack` methods.
@@ -16,6 +18,7 @@ enum StackItem {
1618
}
1719

1820
class CallStack {
21+
#if (php7 && !macro)
1922
/**
2023
If defined this function will be used to transform call stack entries.
2124
@param String - generated php file name.
@@ -121,5 +124,9 @@ class CallStack {
121124

122125
return result;
123126
}
124-
127+
#else
128+
static public function callStack():Array<StackItem> throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
129+
static public function exceptionStack():Array<StackItem> throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
130+
static public function toString():String throw "Not implemented. See https://github.com/RealyUniqueName/JStack/issues/10";
131+
#end
125132
}

test.hxml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ extraParams.hxml
1313

1414
--next
1515

16+
-main Test
17+
-D php7
18+
-php build/php
19+
20+
--next
21+
1622
-D JSTACK_ASYNC_ENTRY
1723
-main TestAsync
1824
-js build/test-async.js

test/Test.hx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class Test {
88
static var pos:PosInfos;
99

1010
static public function main() {
11+
testMacroIssue10();
1112
try {
1213
throwException();
1314
} catch(e:Int) {
@@ -28,4 +29,8 @@ class Test {
2829
Test.pos = pos;
2930
throw 10;
3031
}
32+
33+
macro static function testMacroIssue10() {
34+
return macro {};
35+
}
3136
}

0 commit comments

Comments
 (0)