EjsArray *ejsCaptureStack(Ejs *ejs, int uplevels) { EjsFrame *fp; EjsState *state; EjsArray *stack; wchar *source; EjsObj *frame; char *filename; int index, lineNumber; assert(ejs); stack = ejsCreateArray(ejs, 0); index = 0; for (state = ejs->state; state; state = state->prev) { for (fp = state->fp; fp; fp = fp->caller) { if (uplevels-- <= 0) { frame = ejsCreateEmptyPot(ejs); if (ejsGetDebugInfo(ejs, (EjsFunction*) fp, fp->pc, &filename, &lineNumber, &source) >= 0) { ejsSetPropertyByName(ejs, frame, EN("filename"), ejsCreatePathFromAsc(ejs, filename)); ejsSetPropertyByName(ejs, frame, EN("lineno"), ejsCreateNumber(ejs, lineNumber)); ejsSetPropertyByName(ejs, frame, EN("code"), ejsCreateString(ejs, source, wlen(source))); } else { ejsSetPropertyByName(ejs, frame, EN("filename"), EST(undefined)); } ejsSetPropertyByName(ejs, frame, EN("func"), fp->function.name); ejsSetProperty(ejs, stack, index++, frame); } } } return stack; }
static EjsAny *createException(Ejs *ejs, EjsType *type, cchar* fmt, va_list fmtArgs) { EjsError *error; EjsAny *argv[1]; char *msg; assert(type); #if ME_DEBUG /* Breakpoint opportunity */ if (!ejs->empty) { mprNop(0); } #endif msg = sfmtv(fmt, fmtArgs); argv[0] = ejsCreateStringFromAsc(ejs, msg); if (argv[0] == 0) { assert(argv[0]); return 0; } if (EST(Error)->constructor.body.proc) { error = (EjsError*) ejsCreateInstance(ejs, type, 1, argv); } else { error = ejsCreatePot(ejs, type, 0); ejsSetProperty(ejs, error, ES_Error_message, ejsCreateStringFromAsc(ejs, msg)); } return error; }
static void lstVarSlot(EjsMod *mp, EjsModule *module, EjsName *qname, EjsTrait *trait, int slotNum) { Ejs *ejs; EjsString *space; mprAssert(slotNum >= 0); mprAssert(qname); ejs = mp->ejs; space = mapSpace(ejs, qname->space); if (qname->name == 0 || qname->name->value[0] == '\0') { mprFprintf(mp->file, "%04d <inherited>\n", slotNum); } else if (trait && trait->type) { if (trait->type == EST(Function)) { mprFprintf(mp->file, "%04d %@ function %@\n", slotNum, space, qname->name); } else { mprFprintf(mp->file, "%04d %@ var %@: %@\n", slotNum, space, qname->name, trait->type->qname.name); } } else { mprFprintf(mp->file, "%04d %@ var %@\n", slotNum, space, qname->name); } }
EjsAny *ejsCreateException(Ejs *ejs, int slot, cchar *fmt, va_list fmtArgs) { EjsType *type; EjsAny *error; if (ejs->exception) { mprLog("ejs vm", 0, "Double exception: %s", sfmtv(fmt, fmtArgs)); return ejs->exception; } type = (ejs->initialized) ? ejsGetProperty(ejs, ejs->global, slot) : NULL; if (type == 0) { type = EST(Error); } error = createException(ejs, type, fmt, fmtArgs); if (error) { ejsThrowException(ejs, error); } return error; }
/* Get the current exception error. May be an Error object or may be any other object that is thrown. Caller must NOT free. */ cchar *ejsGetErrorMsg(Ejs *ejs, int withStack) { EjsString *str, *tag, *msg, *message; EjsAny *stack, *error, *saveException; char *buf, *stackStr; error = ejs->exception; message = 0; stack = 0; tag = NULL; if (error) { tag = TYPE(error)->qname.name; if (ejsIs(ejs, error, Error)) { message = ejsGetProperty(ejs, error, ES_Error_message); if (withStack && ejs->initialized && ejs->state) { saveException = ejs->exception; ejsClearException(ejs); stack = ejsRunFunctionBySlot(ejs, error, ES_Error_formatStack, 0, NULL); ejsThrowException(ejs, saveException); } } else if (ejsIs(ejs, error, String)) { tag = ejsCreateStringFromAsc(ejs, "Error"); message = (EjsString*) error; } else if (ejsIs(ejs, error, Number)) { tag = ejsCreateStringFromAsc(ejs, "Error"); message = (EjsString*) error; } else if (error == EST(StopIteration)) { message = ejsCreateStringFromAsc(ejs, "Uncaught StopIteration exception"); } } if (message == ESV(null) || message == 0) { msg = ejsCreateStringFromAsc(ejs, "Exception"); } else{ msg = ejsToString(ejs, message); } if (ejsIs(ejs, error, Error)) { stackStr = (stack) ? ejsToMulti(ejs, stack) : 0; if (stackStr && *stackStr) { buf = sfmt("%@: %@\nStack:\n%s", tag, msg, (stack) ? ejsToMulti(ejs, stack) : ""); } else { buf = sfmt("%@: %@", tag, msg); } } else if (message && ejsIs(ejs, message, String)){ buf = sfmt("%@: %@", tag, msg); } else if (message && ejsIs(ejs, message, Number)){ buf = sfmt("%@: %g", tag, ((EjsNumber*) msg)->value); } else if (error) { EjsObj *saveException = ejs->exception; ejs->exception = 0; str = ejsToString(ejs, error); buf = sclone(ejsToMulti(ejs, str)); ejs->exception = saveException; } else { buf = sclone(""); } ejs->errorMsg = buf; return buf; }
static void lstFunction(EjsMod *mp, EjsModule *module, EjsObj *block, int slotNum, EjsName qname, EjsFunction *fun, int attributes) { Ejs *ejs; EjsTrait *trait; EjsName lname; EjsType *resultType; EjsPot *activation; EjsString *space, *blockName; int i, numLocals, numProp; ejs = mp->ejs; activation = fun->activation; numProp = activation ? activation->numProp : 0; space = mapSpace(ejs, qname.space); mprFprintf(mp->file, "\nFUNCTION: "); /* Do the function declaration */ if (attributes) { if (slotNum < 0) { /* Special just for global initializers */ mprFprintf(mp->file, "[initializer] %@ %sfunction %@(", space, getAttributeString(mp, attributes), qname.name); } else { blockName = getBlockName(mp, block, slotNum); mprFprintf(mp->file, "[%@-%02d] %@ %sfunction %@(", blockName, slotNum, space, getAttributeString(mp, attributes), qname.name); } } else { blockName = getBlockName(mp, block, slotNum); mprFprintf(mp->file, "[%@-%02d] %@ function %@(", blockName, slotNum, space, qname.name); } for (i = 0; i < (int) fun->numArgs; ) { lname = ejsGetPropertyName(ejs, activation, i); trait = ejsGetPropertyTraits(ejs, activation, i); if (trait->type) { mprFprintf(mp->file, "%@: %@", lname.name, trait->type->qname.name); } else { mprFprintf(mp->file, "%@", lname.name); } if (++i < (int) fun->numArgs) { mprFprintf(mp->file, ", "); } } resultType = fun->resultType; mprFprintf(mp->file, ") : %@\n", resultType ? resultType->qname.name : EST(Void)->qname.name); /* Repeat the args */ for (i = 0; i < (int) fun->numArgs; i++) { lname = ejsGetPropertyName(ejs, activation, i); trait = ejsGetPropertyTraits(ejs, activation, i); mprFprintf(mp->file, " ARG: [arg-%02d] %@ %@", i, lname.space, lname.name); if (trait->type) { mprFprintf(mp->file, " : %@", trait->type->qname.name); } mprFprintf(mp->file, "\n"); } numLocals = numProp - fun->numArgs; for (i = 0; i < numLocals; i++) { lname = ejsGetPropertyName(ejs, activation, i + fun->numArgs); trait = ejsGetPropertyTraits(ejs, activation, i + fun->numArgs); mprFprintf(mp->file, " LOCAL: [local-%02d] var %@", i + fun->numArgs, lname.name); if (trait->type) { mprFprintf(mp->file, " : %@", trait->type->qname.name); } mprFprintf(mp->file, "\n"); } if (fun->body.code) { mprFprintf(mp->file, "\n"); interp(mp, module, fun); } mprFprintf(mp->file, "\n"); }