shithub: libmujs

Download patch

ref: 5ce44f9d4a73250fefc15a6102e60773f7b3b8db
parent: 10ffd559dea1f37fe3f0b7d6a5b179b956ebd2b5
author: Tor Andersson <[email protected]>
date: Fri Jan 17 11:00:51 EST 2014

Remember file name and line where a function object came from.

Make "debugger" statement useful: dump current function bytecode,
stack, and environment scope chain.

--- a/jscompile.c
+++ b/jscompile.c
@@ -18,7 +18,8 @@
 	js_Function *F = malloc(sizeof *F);
 	memset(F, 0, sizeof *F);
 
-	F->name = name ? name->string : "<anonymous>";
+	F->filename = js_intern(J, J->filename);
+	F->line = name ? name->line : params ? params->line : body->line;
 
 	F->next = J->fun;
 	J->fun = F;
@@ -727,8 +728,11 @@
 static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
 {
 	if (name) {
+		F->name = name->string;
 		emitfunction(J, F, F);
 		emitstring(J, F, OP_FUNDEC, name->string);
+	} else {
+		F->name = "<anonymous>";
 	}
 
 	cparams(J, F, params);
--- a/jscompile.h
+++ b/jscompile.h
@@ -90,6 +90,7 @@
 struct js_Function
 {
 	const char *name;
+
 	int numparams;
 	const char **params;
 
@@ -104,6 +105,9 @@
 
 	const char **strtab;
 	int strcap, strlen;
+
+	const char *filename;
+	int line;
 
 	js_Function *next; /* alloc list */
 };
--- a/jsdump.c
+++ b/jsdump.c
@@ -599,12 +599,12 @@
 	for (i = 0; i < F->numparams; ++i)
 		printf("%s%s", i > 0 ? ", " : "", F->params[i]);
 	printf(")\n");
+	printf("\tsource %s:%d\n", F->filename, F->line);
 	for (i = 0; i < F->funlen; ++i)
 		printf("\tfunction %p %s\n", F->funtab[i], F->funtab[i]->name);
 	for (i = 0; i < F->strlen; ++i) {
 		ps("\tstring "); pstr(F->strtab[i]); ps("\n");
 	}
-	// TODO: regexp
 	for (i = 0; i < F->numlen; ++i)
 		printf("\tnumber %.9g\n", F->numtab[i]);
 
@@ -652,7 +652,6 @@
 
 	for (i = 0; i < F->funlen; ++i) {
 		if (F->funtab[i] != F) {
-			nl();
 			jsC_dumpfunction(J, F->funtab[i]);
 		}
 	}
@@ -672,7 +671,14 @@
 		switch (v.u.object->type) {
 		case JS_COBJECT: printf("object(%p)", v.u.object); break;
 		case JS_CARRAY: printf("array(%p)", v.u.object); break;
-		case JS_CFUNCTION: printf("function(%s)", v.u.object->function->name); break;
+		case JS_CFUNCTION:
+			printf("function(%p, %s, %s:%d)",
+				v.u.object,
+				v.u.object->function->name,
+				v.u.object->function->filename,
+				v.u.object->function->line);
+			break;
+		case JS_CSCRIPT: printf("script(%s)", v.u.object->function->filename); break;
 		case JS_CCFUNCTION: printf("cfunction(%p)", v.u.object->cfunction); break;
 		case JS_CBOOLEAN: printf("boolean(%d)", v.u.object->primitive.boolean); break;
 		case JS_CNUMBER: printf("number(%g)", v.u.object->primitive.number); break;
--- a/jsrun.c
+++ b/jsrun.c
@@ -386,21 +386,36 @@
 
 /* Main interpreter loop */
 
-void js_dumpstack(js_State *J)
+void jsR_dumpstack(js_State *J)
 {
 	int i;
+	printf("stack {\n");
 	for (i = 0; i < top; ++i) {
-		printf("stack %d: ", i);
+		putchar(i == bot ? '>' : ' ');
+		printf("% 3d: ", i);
 		js_dumpvalue(J, stack[i]);
 		putchar('\n');
 	}
+	printf("}\n");
 }
 
-void js_trap(js_State *J)
+void jsR_dumpenvironment(js_State *J, js_Environment *E, int d)
 {
-	fprintf(stderr, "trap!\n");
+	printf("scope %d ", d);
+	js_dumpobject(J, E->variables);
+	if (E->outer)
+		jsR_dumpenvironment(J, E->outer, d+1);
 }
 
+void js_trap(js_State *J, int pc)
+{
+	fprintf(stderr, "trap at %d in ", pc);
+	js_Function *F = stack[bot-1].u.object->function;
+	jsC_dumpfunction(J, F);
+	jsR_dumpstack(J);
+	jsR_dumpenvironment(J, J->E, 0);
+}
+
 static void jsR_run(js_State *J, js_Function *F)
 {
 	js_Function **FT = F->funtab;
@@ -691,7 +706,7 @@
 		/* Branching */
 
 		case OP_DEBUGGER:
-			js_trap(J);
+			js_trap(J, (int)(pc - pcstart) - 1);
 			break;
 
 		case OP_JUMP: