📄 js.c
字号:
* SrcNotes assumes that SRC_METHODBASE should be distinguished from SRC_LABEL * using the bytecode the source note points to. */JS_STATIC_ASSERT(SRC_LABEL == SRC_METHODBASE);static voidSrcNotes(JSContext *cx, JSScript *script){ uintN offset, delta, caseOff, switchTableStart, switchTableEnd; jssrcnote *notes, *sn; JSSrcNoteType type; const char *name; JSOp op; jsatomid atomIndex; JSAtom *atom; fprintf(gOutFile, "\nSource notes:\n"); offset = 0; notes = SCRIPT_NOTES(script); switchTableEnd = switchTableStart = 0; for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { delta = SN_DELTA(sn); offset += delta; type = (JSSrcNoteType) SN_TYPE(sn); name = js_SrcNoteSpec[type].name; if (type == SRC_LABEL) { /* Heavily overloaded case. */ if (switchTableStart <= offset && offset < switchTableEnd) { name = "case"; } else { op = script->code[offset]; if (op == JSOP_GETMETHOD || op == JSOP_SETMETHOD) { /* This is SRC_METHODBASE which we print as SRC_PCBASE. */ type = SRC_PCBASE; name = "methodbase"; } else { JS_ASSERT(op == JSOP_NOP); } } } fprintf(gOutFile, "%3u: %5u [%4u] %-8s", PTRDIFF(sn, notes, jssrcnote), offset, delta, name); switch (type) { case SRC_SETLINE: fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0)); break; case SRC_FOR: fprintf(gOutFile, " cond %u update %u tail %u", (uintN) js_GetSrcNoteOffset(sn, 0), (uintN) js_GetSrcNoteOffset(sn, 1), (uintN) js_GetSrcNoteOffset(sn, 2)); break; case SRC_IF_ELSE: fprintf(gOutFile, " else %u elseif %u", (uintN) js_GetSrcNoteOffset(sn, 0), (uintN) js_GetSrcNoteOffset(sn, 1)); break; case SRC_COND: case SRC_WHILE: case SRC_PCBASE: case SRC_PCDELTA: case SRC_DECL: case SRC_BRACE: fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0)); break; case SRC_LABEL: case SRC_LABELBRACE: case SRC_BREAK2LABEL: case SRC_CONT2LABEL: case SRC_FUNCDEF: { const char *bytes; JSFunction *fun; JSString *str; atomIndex = (jsatomid) js_GetSrcNoteOffset(sn, 0); atom = js_GetAtom(cx, &script->atomMap, atomIndex); if (type != SRC_FUNCDEF) { bytes = js_AtomToPrintableString(cx, atom); } else { fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom)); str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT); bytes = str ? JS_GetStringBytes(str) : "N/A"; } fprintf(gOutFile, " atom %u (%s)", (uintN)atomIndex, bytes); break; } case SRC_SWITCH: fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0)); caseOff = (uintN) js_GetSrcNoteOffset(sn, 1); if (caseOff) fprintf(gOutFile, " first case offset %u", caseOff); GetSwitchTableBounds(script, offset, &switchTableStart, &switchTableEnd); break; case SRC_CATCH: delta = (uintN) js_GetSrcNoteOffset(sn, 0); if (delta) { if (script->main[offset] == JSOP_LEAVEBLOCK) fprintf(gOutFile, " stack depth %u", delta); else fprintf(gOutFile, " guard delta %u", delta); } break; default:; } fputc('\n', gOutFile); }}static JSBoolNotes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ uintN i; JSScript *script; for (i = 0; i < argc; i++) { script = ValueToScript(cx, argv[i]); if (!script) continue; SrcNotes(cx, script); } return JS_TRUE;}static JSBoolTryNotes(JSContext *cx, JSScript *script){ JSTryNote *tn = script->trynotes; if (!tn) return JS_TRUE; fprintf(gOutFile, "\nException table:\nstart\tend\tcatch\n"); while (tn->start && tn->catchStart) { fprintf(gOutFile, " %d\t%d\t%d\n", tn->start, tn->start + tn->length, tn->catchStart); tn++; } return JS_TRUE;}static JSBoolDisassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSBool lines; uintN i; JSScript *script; if (argc > 0 && JSVAL_IS_STRING(argv[0]) && !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) { lines = JS_TRUE; argv++, argc--; } else { lines = JS_FALSE; } for (i = 0; i < argc; i++) { script = ValueToScript(cx, argv[i]); if (!script) return JS_FALSE; if (VALUE_IS_FUNCTION(cx, argv[i])) { JSFunction *fun = JS_ValueToFunction(cx, argv[i]); if (fun && (fun->flags & JSFUN_FLAGS_MASK)) { uint16 flags = fun->flags; fputs("flags:", stdout);#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout); SHOW_FLAG(LAMBDA); SHOW_FLAG(SETTER); SHOW_FLAG(GETTER); SHOW_FLAG(BOUND_METHOD); SHOW_FLAG(HEAVYWEIGHT); SHOW_FLAG(THISP_STRING); SHOW_FLAG(THISP_NUMBER); SHOW_FLAG(THISP_BOOLEAN); SHOW_FLAG(INTERPRETED);#undef SHOW_FLAG putchar('\n'); } } if (!js_Disassemble(cx, script, lines, stdout)) return JS_FALSE; SrcNotes(cx, script); TryNotes(cx, script); } return JS_TRUE;}static JSBoolDisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){#define LINE_BUF_LEN 512 uintN i, len, line1, line2, bupline; JSScript *script; FILE *file; char linebuf[LINE_BUF_LEN]; jsbytecode *pc, *end; static char sep[] = ";-------------------------"; for (i = 0; i < argc; i++) { script = ValueToScript(cx, argv[i]); if (!script) return JS_FALSE; if (!script || !script->filename) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_FILE_SCRIPTS_ONLY); return JS_FALSE; } file = fopen(script->filename, "r"); if (!file) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_CANT_OPEN, script->filename, strerror(errno)); return JS_FALSE; } pc = script->code; end = pc + script->length; /* burn the leading lines */ line2 = JS_PCToLineNumber(cx, script, pc); for (line1 = 0; line1 < line2 - 1; line1++) fgets(linebuf, LINE_BUF_LEN, file); bupline = 0; while (pc < end) { line2 = JS_PCToLineNumber(cx, script, pc); if (line2 < line1) { if (bupline != line2) { bupline = line2; fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2); } } else { if (bupline && line1 == line2) fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2); bupline = 0; while (line1 < line2) { if (!fgets(linebuf, LINE_BUF_LEN, file)) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_UNEXPECTED_EOF, script->filename); goto bail; } line1++; fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf); } } len = js_Disassemble1(cx, script, pc, PTRDIFF(pc, script->code, jsbytecode), JS_TRUE, stdout); if (!len) return JS_FALSE; pc += len; } bail: fclose(file); } return JS_TRUE;#undef LINE_BUF_LEN}static JSBoolTracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSBool bval; JSString *str; if (argc == 0) { *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0); return JS_TRUE; } switch (JS_TypeOfValue(cx, argv[0])) { case JSTYPE_NUMBER: bval = JSVAL_IS_INT(argv[0]) ? JSVAL_TO_INT(argv[0]) : (jsint) *JSVAL_TO_DOUBLE(argv[0]); break; case JSTYPE_BOOLEAN: bval = JSVAL_TO_BOOLEAN(argv[0]); break; default: str = JS_ValueToString(cx, argv[0]); if (!str) return JS_FALSE; fprintf(gErrFile, "tracing: illegal argument %s\n", JS_GetStringBytes(str)); return JS_TRUE; } cx->tracefp = bval ? stderr : NULL; return JS_TRUE;}typedef struct DumpAtomArgs { JSContext *cx; FILE *fp;} DumpAtomArgs;static intDumpAtom(JSHashEntry *he, int i, void *arg){ DumpAtomArgs *args = (DumpAtomArgs *)arg; FILE *fp = args->fp; JSAtom *atom = (JSAtom *)he; fprintf(fp, "%3d %08x %5lu ", i, (uintN)he->keyHash, (unsigned long)atom->number); if (ATOM_IS_STRING(atom)) fprintf(fp, "\"%s\"\n", js_AtomToPrintableString(args->cx, atom)); else if (ATOM_IS_INT(atom)) fprintf(fp, "%ld\n", (long)ATOM_TO_INT(atom)); else fprintf(fp, "%.16g\n", *ATOM_TO_DOUBLE(atom)); return HT_ENUMERATE_NEXT;}static voidDumpScope(JSContext *cx, JSObject *obj, FILE *fp){ uintN i; JSScope *scope; JSScopeProperty *sprop; i = 0; scope = OBJ_SCOPE(obj); for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) { if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop)) continue; fprintf(fp, "%3u %p", i, (void *)sprop); if (JSID_IS_INT(sprop->id)) { fprintf(fp, " [%ld]", (long)JSVAL_TO_INT(sprop->id)); } else if (JSID_IS_ATOM(sprop->id)) { JSAtom *atom = JSID_TO_ATOM(sprop->id); fprintf(fp, " \"%s\"", js_AtomToPrintableString(cx, atom)); } else { jsval v = OBJECT_TO_JSVAL(JSID_TO_OBJECT(sprop->id)); fprintf(fp, " \"%s\"", js_ValueToPrintableString(cx, v)); }#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp) DUMP_ATTR(ENUMERATE); DUMP_ATTR(READONLY); DUMP_ATTR(PERMANENT); DUMP_ATTR(EXPORTED); DUMP_ATTR(GETTER); DUMP_ATTR(SETTER);#undef DUMP_ATTR fprintf(fp, " slot %lu flags %x shortid %d\n", (unsigned long)sprop->slot, sprop->flags, sprop->shortid); }}static JSBoolDumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ uintN i; JSString *str; const char *bytes; JSAtom *atom; JSObject *obj2; JSProperty *prop; jsval value; for (i = 0; i < argc; i++) { str = JS_ValueToString(cx, argv[i]); if (!str) return JS_FALSE; bytes = JS_GetStringBytes(str); if (strcmp(bytes, "arena") == 0) {#ifdef JS_ARENAMETER JS_DumpArenaStats(stdout);#endif } else if (strcmp(bytes, "atom") == 0) { DumpAtomArgs args; fprintf(gOutFile, "\natom table contents:\n"); args.cx = cx; args.fp = stdout; JS_HashTableEnumerateEntries(cx->runtime->atomState.table, DumpAtom, &args);#ifdef HASHMETER JS_HashTableDumpMeter(cx->runtime->atomState.table, DumpAtom, stdout);#endif } else if (strcmp(bytes, "global") == 0) { DumpScope(cx, cx->globalObject, stdout); } else { atom = js_Atomize(cx, bytes, JS_GetStringLength(str), 0); if (!atom) return JS_FALSE; if (!js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop)) return JS_FALSE; if (prop) { OBJ_DROP_PROPERTY(cx, obj2, prop); if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &value)) return JS_FALSE; } if (!prop || !JSVAL_IS_OBJECT(value)) { fprintf(gErrFile, "js: invalid stats argument %s\n", bytes); continue; } obj = JSVAL_TO_OBJECT(value); if (obj) DumpScope(cx, obj, stdout); } } return JS_TRUE;}#endif /* DEBUG */#ifdef TEST_EXPORTstatic JSBoolDoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSAtom *atom; JSObject *obj2; JSProperty *prop; JSBool ok; uintN attrs; if (argc != 2) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_DOEXP_USAGE); return JS_FALSE; } if (!JS_ValueToObject(cx, argv[0], &obj)) return JS_FALSE; argv[0] = OBJECT_TO_JSVAL(obj); atom = js_ValueToStringAtom(cx, argv[1]); if (!atom) return JS_FALSE; if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) return JS_FALSE; if (!prop) { ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, JSPROP_EXPORTED, NULL); } else { ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); if (ok) { attrs |= JSPROP_EXPORTED; ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); } OBJ_DROP_PROPERTY(cx, obj2, prop); } return ok;}#endif#ifdef TEST_CVTARGS#include <ctype.h>static const char *EscapeWideString(jschar *w){ static char enuf[80];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -