static JSString * ValueToShortSource(JSContext *cx, jsval v) { JSString *str; /* Avoid toSource bloat and fallibility for object types. */ if (JSVAL_IS_PRIMITIVE(v)) { str = js_ValueToSource(cx, v); } else if (VALUE_IS_FUNCTION(cx, v)) { /* * XXX Avoid function decompilation bloat for now. */ str = JS_GetFunctionId(JS_ValueToFunction(cx, v)); if (!str && !(str = js_ValueToSource(cx, v))) { /* * Continue to soldier on if the function couldn't be * converted into a string. */ JS_ClearPendingException(cx); str = JS_NewStringCopyZ(cx, "[unknown function]"); } } else { /* * XXX Avoid toString on objects, it takes too long and uses too much * memory, for too many classes (see Mozilla bug 166743). */ char buf[100]; JS_snprintf(buf, sizeof buf, "[object %s]", OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v))->name); str = JS_NewStringCopyZ(cx, buf); } return str; }
NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse (void *p, nsCycleCollectionTraversalCallback &cb) { nsISupports *s = static_cast<nsISupports*>(p); NS_ASSERTION(CheckForRightISupports(s), "not the nsISupports pointer we expect"); nsXPCWrappedJS *tmp = Downcast(s); nsrefcnt refcnt = tmp->mRefCnt.get(); if (cb.WantDebugInfo()) { char name[72]; if (tmp->GetClass()) JS_snprintf(name, sizeof(name), "nsXPCWrappedJS (%s)", tmp->GetClass()->GetInterfaceName()); else JS_snprintf(name, sizeof(name), "nsXPCWrappedJS"); cb.DescribeRefCountedNode(refcnt, sizeof(nsXPCWrappedJS), name); } else { NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsXPCWrappedJS, refcnt) } // nsXPCWrappedJS keeps its own refcount artificially at or above 1, see the // comment above nsXPCWrappedJS::AddRef. NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "self"); cb.NoteXPCOMChild(s); if (refcnt > 1) { // nsXPCWrappedJS roots its mJSObj when its refcount is > 1, see // the comment above nsXPCWrappedJS::AddRef. NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mJSObj"); cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->GetJSObjectPreserveColor()); } nsXPCWrappedJS* root = tmp->GetRootWrapper(); if (root == tmp) { // The root wrapper keeps the aggregated native object alive. NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "aggregated native"); cb.NoteXPCOMChild(tmp->GetAggregatedNativeObject()); } else { // Non-root wrappers keep their root alive. NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "root"); cb.NoteXPCOMChild(static_cast<nsIXPConnectWrappedJS*>(root)); } return NS_OK; }
static void printTraceName(JSTracer* trc, char* buf, size_t bufsize) { JS_snprintf(buf, bufsize, "TracedObject(%p)", trc->debugPrintArg); }
// static void nsXPCWrappedJS::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize) { const nsXPCWrappedJS* self = static_cast<const nsXPCWrappedJS*> (trc->debugPrintArg); JS_snprintf(buf, bufsize, "nsXPCWrappedJS[%s,0x%p:0x%p].mJSObj", self->GetClass()->GetInterfaceName(), self, self->mXPTCStub); }
JSBool SJS_PluginInit(JSContext *cx, sjs_data *rtd) { PLUGIN_API_CHECK; grtd = rtd; JS_snprintf(version, 200, "zlib/%s", zlibVersion()); zip = JSZip::JSInit(cx, JS_GetGlobalObject(cx), NULL); return (zip != NULL); }
static JSBool mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence) { switch (whence) { case JSXDR_SEEK_CUR: if ((int32)MEM_COUNT(xdr) + offset < 0) { JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_SEEK_BEYOND_START); return JS_FALSE; } if (offset > 0) MEM_NEED(xdr, offset); MEM_COUNT(xdr) += offset; return JS_TRUE; case JSXDR_SEEK_SET: if (offset < 0) { JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_SEEK_BEYOND_START); return JS_FALSE; } if (xdr->mode == JSXDR_ENCODE) { if ((uint32)offset > MEM_COUNT(xdr)) MEM_NEED(xdr, offset - MEM_COUNT(xdr)); MEM_COUNT(xdr) = offset; } else { if ((uint32)offset > MEM_LIMIT(xdr)) { JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_SEEK_BEYOND_END); return JS_FALSE; } MEM_COUNT(xdr) = offset; } return JS_TRUE; case JSXDR_SEEK_END: if (offset >= 0 || xdr->mode == JSXDR_ENCODE || (int32)MEM_LIMIT(xdr) + offset < 0) { JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_END_SEEK); return JS_FALSE; } MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset; return JS_TRUE; default: { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%d", whence); JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, JSMSG_WHITHER_WHENCE, numBuf); return JS_FALSE; } } }
/* string toString (); */ NS_IMETHODIMP JSStackFrame::ToString(char** _retval) { const char* frametype = IsJSFrame() ? "JS" : "native"; const char* filename = mFilename ? mFilename : "<unknown filename>"; const char* funname = mFunname ? mFunname : "<TOP_LEVEL>"; static const char format[] = "%s frame :: %s :: %s :: line %d"; int len = sizeof(char)* (strlen(frametype) + strlen(filename) + strlen(funname)) + sizeof(format) + 3 * sizeof(mLineno); char* buf = (char*) nsMemory::Alloc(len); JS_snprintf(buf, len, format, frametype, filename, funname, mLineno); *_retval = buf; return NS_OK; }
jsval get_opcode_arg(JSContext *cx, JSScript *script, jsbytecode *pc) { JSOp op; const JSCodeSpec *cs; ptrdiff_t len; uint32 type; JSAtom *atom; jsval v; op = (JSOp)*pc; if (op >= JSOP_LIMIT) { char numBuf1[12], numBuf2[12]; JS_snprintf(numBuf1, sizeof numBuf1, "%d", op); JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT); fprintf(stderr,"ERROR in get_opcode_arg: unknown bytecode %s %s\n",numBuf1,numBuf2); return 0; } cs = &js_CodeSpec[op]; len = (ptrdiff_t) cs->length; type = cs->format & JOF_TYPEMASK; switch (type) { case JOF_CONST: atom = GET_ATOM(cx, script, pc); v = ATOM_KEY(atom); return v; break; default: { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format); fprintf(stderr,"ERROR in get_opcode_arg: Unknown format %s\n",numBuf); return 0; } } }
js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i) { JSAtom *atom; static JSAtom dummy; JS_ASSERT(map->vector && i < map->length); if (!map->vector || i >= map->length) { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ATOMIC_NUMBER, numBuf); return &dummy; } atom = map->vector[i]; JS_ASSERT(atom); return atom; }
bool LCovRuntime::fillWithFilename(char *name, size_t length) { const char* outDir = getenv("JS_CODE_COVERAGE_OUTPUT_DIR"); if (!outDir || *outDir == 0) return false; int64_t timestamp = static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_SEC; static mozilla::Atomic<size_t> globalRuntimeId(0); size_t rid = globalRuntimeId++; size_t len = JS_snprintf(name, length, "%s/%" PRId64 "-%" PRIuSIZE "-%" PRIuSIZE ".info", outDir, timestamp, pid_, rid); if (length <= len) { fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name."); return false; } return true; }
static JSBool write_string(JSContext *cx, JSONWriteCallback callback, void *data, const jschar *buf, uint32 len) { if (!callback("e, 1, data)) return JS_FALSE; uint32 mark = 0; uint32 i; for (i = 0; i < len; ++i) { if (buf[i] == quote || buf[i] == backslash) { if (!callback(&buf[mark], i - mark, data) || !callback(&backslash, 1, data) || !callback(&buf[i], 1, data)) { return JS_FALSE; } mark = i + 1; } else if (buf[i] <= 31 || buf[i] == 127) { if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data)) return JS_FALSE; char ubuf[3]; size_t len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]); JS_ASSERT(len == 2); jschar wbuf[3]; size_t wbufSize = JS_ARRAY_LENGTH(wbuf); if (!js_InflateStringToBuffer(cx, ubuf, len, wbuf, &wbufSize) || !callback(wbuf, wbufSize, data)) { return JS_FALSE; } mark = i + 1; } } if (mark < len && !callback(&buf[mark], len - mark, data)) return JS_FALSE; if (!callback("e, 1, data)) return JS_FALSE; return JS_TRUE; }
static JSBool bool_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { jsval v; char buf[32]; JSString *str; if (!JS_InstanceOf(cx, obj, &boolean_class, argv)) return JS_FALSE; v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE); if (!JSVAL_IS_BOOLEAN(v)) return js_obj_toSource(cx, obj, argc, argv, rval); JS_snprintf(buf, sizeof buf, "(new %s(%s))", boolean_class.name, js_boolean_str[JSVAL_TO_BOOLEAN(v) ? 1 : 0]); str = JS_NewStringCopyZ(cx, buf); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); return JS_TRUE; }
static JSBool write_string(JSContext *cx, JSCharBuffer &cb, const jschar *buf, uint32 len) { if (!cb.append(quote)) return JS_FALSE; uint32 mark = 0; uint32 i; for (i = 0; i < len; ++i) { if (buf[i] == quote || buf[i] == backslash) { if (!cb.append(&buf[mark], i - mark) || !cb.append(backslash) || !cb.append(buf[i])) { return JS_FALSE; } mark = i + 1; } else if (buf[i] <= 31 || buf[i] == 127) { if (!cb.append(&buf[mark], i - mark) || !js_AppendLiteral(cb, unicodeEscape)) { return JS_FALSE; } char ubuf[3]; size_t len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]); JS_ASSERT(len == 2); jschar wbuf[3]; size_t wbufSize = JS_ARRAY_LENGTH(wbuf); if (!js_InflateStringToBuffer(cx, ubuf, len, wbuf, &wbufSize) || !cb.append(wbuf, wbufSize)) { return JS_FALSE; } mark = i + 1; } } if (mark < len && !cb.append(&buf[mark], len - mark)) return JS_FALSE; return cb.append(quote); }
static JSBool write_string(JSContext *cx, JSONWriteCallback callback, void *data, const jschar *buf, uint32 len) { if (!callback("e, 1, data)) return JS_FALSE; uint32 mark = 0; uint32 i; for (i = 0; i < len; ++i) { if (buf[i] == quote || buf[i] == backslash) { if (!callback(&buf[mark], i - mark, data) || !callback(&backslash, 1, data) || !callback(&buf[i], 1, data)) { return JS_FALSE; } mark = i + 1; } else if (buf[i] <= 31 || buf[i] == 127) { if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data)) return JS_FALSE; char ubuf[10]; unsigned int len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]); JS_ASSERT(len == 2); // TODO: don't allocate a JSString just to inflate (js_InflateStringToBuffer on static?) JSString *us = JS_NewStringCopyN(cx, ubuf, len); if (!callback(JS_GetStringChars(us), len, data)) return JS_FALSE; mark = i + 1; } } if (mark < len && !callback(&buf[mark], len - mark, data)) return JS_FALSE; if (!callback("e, 1, data)) return JS_FALSE; return JS_TRUE; }
static JSBool InitExceptionObject(JSContext *cx, JSObject *obj, JSString *message, JSString *filename, uintN lineno) { JSCheckAccessOp checkAccess; JSErrorReporter older; JSExceptionState *state; jschar *stackbuf; size_t stacklen, stackmax; JSStackFrame *fp; jsval callerid, v; JSBool ok; JSString *argsrc, *stack; uintN i, ulineno; const char *cp; char ulnbuf[11]; if (!JS_DefineProperty(cx, obj, js_message_str, STRING_TO_JSVAL(message), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } if (!JS_DefineProperty(cx, obj, js_filename_str, STRING_TO_JSVAL(filename), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } if (!JS_DefineProperty(cx, obj, js_lineno_str, INT_TO_JSVAL(lineno), NULL, NULL, JSPROP_ENUMERATE)) { return JS_FALSE; } /* * Set the 'stack' property. * * First, set aside any error reporter for cx and save its exception state * so we can suppress any checkAccess failures. Such failures should stop * the backtrace procedure, not result in a failure of this constructor. */ checkAccess = cx->runtime->checkObjectAccess; if (checkAccess) { older = JS_SetErrorReporter(cx, NULL); state = JS_SaveExceptionState(cx); } #ifdef __GNUC__ /* suppress bogus gcc warnings */ else { older = NULL; state = NULL; } #endif callerid = ATOM_KEY(cx->runtime->atomState.callerAtom); /* * Prepare to allocate a jschar buffer at stackbuf, where stacklen indexes * the next free jschar slot, and with room for at most stackmax non-null * jschars. If stackbuf is non-null, it always contains an extra slot for * the null terminator we'll store at the end, as a backstop. * * All early returns must goto done after this point, till the after-loop * cleanup code has run! */ stackbuf = NULL; stacklen = stackmax = 0; ok = JS_TRUE; #define APPEND_CHAR_TO_STACK(c) \ JS_BEGIN_MACRO \ if (stacklen == stackmax) { \ void *ptr_; \ stackmax = stackmax ? 2 * stackmax : 64; \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ stackbuf[stacklen++] = (c); \ JS_END_MACRO #define APPEND_STRING_TO_STACK(str) \ JS_BEGIN_MACRO \ JSString *str_ = str; \ size_t length_ = JSSTRING_LENGTH(str_); \ if (stacklen + length_ > stackmax) { \ void *ptr_; \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ js_strncpy(stackbuf + stacklen, JSSTRING_CHARS(str_), length_); \ stacklen += length_; \ JS_END_MACRO for (fp = cx->fp; fp; fp = fp->down) { if (checkAccess) { v = (fp->fun && fp->argv) ? fp->argv[-2] : JSVAL_NULL; if (!JSVAL_IS_PRIMITIVE(v)) { ok = checkAccess(cx, fp->fun->object, callerid, JSACC_READ, &v); if (!ok) { ok = JS_TRUE; break; } } } if (fp->fun) { if (fp->fun->atom) APPEND_STRING_TO_STACK(ATOM_TO_STRING(fp->fun->atom)); APPEND_CHAR_TO_STACK('('); for (i = 0; i < fp->argc; i++) { argsrc = js_ValueToSource(cx, fp->argv[i]); if (!argsrc) { ok = JS_FALSE; goto done; } if (i > 0) APPEND_CHAR_TO_STACK(','); APPEND_STRING_TO_STACK(argsrc); } APPEND_CHAR_TO_STACK(')'); } APPEND_CHAR_TO_STACK('@'); if (fp->script && fp->script->filename) { for (cp = fp->script->filename; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } APPEND_CHAR_TO_STACK(':'); if (fp->script && fp->pc) { ulineno = js_PCToLineNumber(fp->script, fp->pc); JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", ulineno); for (cp = ulnbuf; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } else { APPEND_CHAR_TO_STACK('0'); } APPEND_CHAR_TO_STACK('\n'); } #undef APPEND_CHAR_TO_STACK #undef APPEND_STRING_TO_STACK done: if (checkAccess) { if (ok) JS_RestoreExceptionState(cx, state); else JS_DropExceptionState(cx, state); JS_SetErrorReporter(cx, older); } if (!ok) { JS_free(cx, stackbuf); return JS_FALSE; } if (!stackbuf) { stack = cx->runtime->emptyString; } else { /* NB: if stackbuf was allocated, it has room for the terminator. */ JS_ASSERT(stacklen <= stackmax); if (stacklen < stackmax) { /* * Realloc can fail when shrinking on some FreeBSD versions, so * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ void *shrunk = realloc(stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = shrunk; } stackbuf[stacklen] = 0; stack = js_NewString(cx, stackbuf, stacklen, 0); if (!stack) { JS_free(cx, stackbuf); return JS_FALSE; } } return JS_DefineProperty(cx, obj, js_stack_str, STRING_TO_JSVAL(stack), NULL, NULL, JSPROP_ENUMERATE); }
JSTokenType js_GetToken(JSContext *cx, JSTokenStream *ts) { JSTokenType tt; JSToken *tp; int32 c; JSAtom *atom; JSBool hadUnicodeEscape; #define INIT_TOKENBUF(tb) ((tb)->ptr = (tb)->base) #define FINISH_TOKENBUF(tb) if (!AddToTokenBuf(cx, tb, 0)) RETURN(TOK_ERROR) #define TOKEN_LENGTH(tb) ((tb)->ptr - (tb)->base - 1) #define RETURN(tt) { if (tt == TOK_ERROR) ts->flags |= TSF_ERROR; \ tp->pos.end.index = ts->linepos + \ (ts->linebuf.ptr - ts->linebuf.base) - \ ts->ungetpos; \ return (tp->type = tt); } /* If there was a fatal error, keep returning TOK_ERROR. */ if (ts->flags & TSF_ERROR) return TOK_ERROR; /* Check for a pushed-back token resulting from mismatching lookahead. */ while (ts->lookahead != 0) { ts->lookahead--; ts->cursor = (ts->cursor + 1) & NTOKENS_MASK; tt = CURRENT_TOKEN(ts).type; if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES)) return tt; } retry: do { c = GetChar(ts); if (c == '\n') { ts->flags &= ~TSF_DIRTYLINE; if (ts->flags & TSF_NEWLINES) break; } } while (JS_ISSPACE(c)); ts->cursor = (ts->cursor + 1) & NTOKENS_MASK; tp = &CURRENT_TOKEN(ts); tp->ptr = ts->linebuf.ptr - 1; tp->pos.begin.index = ts->linepos + (tp->ptr - ts->linebuf.base); tp->pos.begin.lineno = tp->pos.end.lineno = ts->lineno; if (c == EOF) RETURN(TOK_EOF); if (c != '-' && c != '\n') ts->flags |= TSF_DIRTYLINE; hadUnicodeEscape = JS_FALSE; if (JS_ISIDENT_START(c) || (c == '\\' && (c = GetUnicodeEscape(ts), hadUnicodeEscape = JS_ISIDENT_START(c)))) { INIT_TOKENBUF(&ts->tokenbuf); for (;;) { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); if (c == '\\') { c = GetUnicodeEscape(ts); if (!JS_ISIDENT(c)) break; hadUnicodeEscape = JS_TRUE; } else { if (!JS_ISIDENT(c)) break; } } UngetChar(ts, c); FINISH_TOKENBUF(&ts->tokenbuf); atom = js_AtomizeChars(cx, ts->tokenbuf.base, TOKEN_LENGTH(&ts->tokenbuf), 0); if (!atom) RETURN(TOK_ERROR); if (!hadUnicodeEscape && ATOM_KEYWORD(atom)) { struct keyword *kw = ATOM_KEYWORD(atom); if (JSVERSION_IS_ECMA(cx->version) || kw->version <= cx->version) { tp->t_op = (JSOp) kw->op; RETURN(kw->tokentype); } } tp->t_op = JSOP_NAME; tp->t_atom = atom; RETURN(TOK_NAME); } if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) { jsint radix; const jschar *endptr; jsdouble dval; radix = 10; INIT_TOKENBUF(&ts->tokenbuf); if (c == '0') { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); if (JS_TOLOWER(c) == 'x') { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); radix = 16; } else if (JS7_ISDEC(c)) { radix = 8; } } while (JS7_ISHEX(c)) { if (radix < 16) { if (JS7_ISLET(c)) break; /* * We permit 08 and 09 as decimal numbers, which makes our * behaviour a superset of the ECMA numeric grammar. We might * not always be so permissive, so we warn about it. */ if (radix == 8 && c >= '8') { if (!js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_WARNING, JSMSG_BAD_OCTAL, c == '8' ? "08" : "09")) { RETURN(TOK_ERROR); } radix = 10; } } if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); } if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) { if (c == '.') { do { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); } while (JS7_ISDEC(c)); } if (JS_TOLOWER(c) == 'e') { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); if (c == '+' || c == '-') { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); } if (!JS7_ISDEC(c)) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_MISSING_EXPONENT); RETURN(TOK_ERROR); } do { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); } while (JS7_ISDEC(c)); } } UngetChar(ts, c); FINISH_TOKENBUF(&ts->tokenbuf); if (radix == 10) { if (!js_strtod(cx, ts->tokenbuf.base, &endptr, &dval)) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_OUT_OF_MEMORY); RETURN(TOK_ERROR); } } else { if (!js_strtointeger(cx, ts->tokenbuf.base, &endptr, radix, &dval)) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_OUT_OF_MEMORY); RETURN(TOK_ERROR); } } tp->t_dval = dval; RETURN(TOK_NUMBER); } if (c == '"' || c == '\'') { int32 val, qc = c; INIT_TOKENBUF(&ts->tokenbuf); while ((c = GetChar(ts)) != qc) { if (c == '\n' || c == EOF) { UngetChar(ts, c); js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_UNTERMINATED_STRING); RETURN(TOK_ERROR); } if (c == '\\') { switch (c = GetChar(ts)) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; default: if ('0' <= c && c < '8') { val = JS7_UNDEC(c); c = PeekChar(ts); if ('0' <= c && c < '8') { val = 8 * val + JS7_UNDEC(c); GetChar(ts); c = PeekChar(ts); if ('0' <= c && c < '8') { int32 save = val; val = 8 * val + JS7_UNDEC(c); if (val <= 0377) GetChar(ts); else val = save; } } c = (jschar)val; } else if (c == 'u') { jschar cp[4]; if (PeekChars(ts, 4, cp) && JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3])) { c = (((((JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1])) << 4) + JS7_UNHEX(cp[2])) << 4) + JS7_UNHEX(cp[3]); SkipChars(ts, 4); } } else if (c == 'x') { jschar cp[2]; if (PeekChars(ts, 2, cp) && JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) { c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]); SkipChars(ts, 2); } } else if (c == '\n' && JSVERSION_IS_ECMA(cx->version)) { /* ECMA follows C by removing escaped newlines. */ continue; } break; } } if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); } FINISH_TOKENBUF(&ts->tokenbuf); atom = js_AtomizeChars(cx, ts->tokenbuf.base, TOKEN_LENGTH(&ts->tokenbuf), 0); if (!atom) RETURN(TOK_ERROR); tp->pos.end.lineno = ts->lineno; tp->t_op = JSOP_STRING; tp->t_atom = atom; RETURN(TOK_STRING); } switch (c) { case '\n': c = TOK_EOL; break; case ';': c = TOK_SEMI; break; case '.': c = TOK_DOT; break; case '[': c = TOK_LB; break; case ']': c = TOK_RB; break; case '{': c = TOK_LC; break; case '}': c = TOK_RC; break; case '(': c = TOK_LP; break; case ')': c = TOK_RP; break; case ',': c = TOK_COMMA; break; case '?': c = TOK_HOOK; break; case ':': /* * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an * object initializer, likewise for setter. */ tp->t_op = JSOP_NOP; c = TOK_COLON; break; case '|': if (MatchChar(ts, c)) { c = TOK_OR; } else if (MatchChar(ts, '=')) { tp->t_op = JSOP_BITOR; c = TOK_ASSIGN; } else { c = TOK_BITOR; } break; case '^': if (MatchChar(ts, '=')) { tp->t_op = JSOP_BITXOR; c = TOK_ASSIGN; } else { c = TOK_BITXOR; } break; case '&': if (MatchChar(ts, c)) { c = TOK_AND; } else if (MatchChar(ts, '=')) { tp->t_op = JSOP_BITAND; c = TOK_ASSIGN; } else { c = TOK_BITAND; } break; case '=': if (MatchChar(ts, c)) { #if JS_HAS_TRIPLE_EQOPS tp->t_op = MatchChar(ts, c) ? JSOP_NEW_EQ : (JSOp)cx->jsop_eq; #else tp->t_op = cx->jsop_eq; #endif c = TOK_EQOP; } else { tp->t_op = JSOP_NOP; c = TOK_ASSIGN; } break; case '!': if (MatchChar(ts, '=')) { #if JS_HAS_TRIPLE_EQOPS tp->t_op = MatchChar(ts, '=') ? JSOP_NEW_NE : (JSOp)cx->jsop_ne; #else tp->t_op = cx->jsop_ne; #endif c = TOK_EQOP; } else { tp->t_op = JSOP_NOT; c = TOK_UNARYOP; } break; case '<': /* NB: treat HTML begin-comment as comment-till-end-of-line */ if (MatchChar(ts, '!')) { if (MatchChar(ts, '-')) { if (MatchChar(ts, '-')) goto skipline; UngetChar(ts, '-'); } UngetChar(ts, '!'); } if (MatchChar(ts, c)) { tp->t_op = JSOP_LSH; c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP; } else { tp->t_op = MatchChar(ts, '=') ? JSOP_LE : JSOP_LT; c = TOK_RELOP; } break; case '>': if (MatchChar(ts, c)) { tp->t_op = MatchChar(ts, c) ? JSOP_URSH : JSOP_RSH; c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP; } else { tp->t_op = MatchChar(ts, '=') ? JSOP_GE : JSOP_GT; c = TOK_RELOP; } break; case '*': tp->t_op = JSOP_MUL; c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_STAR; break; case '/': if (MatchChar(ts, '/')) { skipline: while ((c = GetChar(ts)) != EOF && c != '\n') /* skip to end of line */; UngetChar(ts, c); goto retry; } if (MatchChar(ts, '*')) { while ((c = GetChar(ts)) != EOF && !(c == '*' && MatchChar(ts, '/'))) { /* Ignore all characters until comment close. */ } if (c == EOF) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_UNTERMINATED_COMMENT); RETURN(TOK_ERROR); } goto retry; } #if JS_HAS_REGEXPS if (ts->flags & TSF_REGEXP) { JSObject *obj; uintN flags; INIT_TOKENBUF(&ts->tokenbuf); while ((c = GetChar(ts)) != '/') { if (c == '\n' || c == EOF) { UngetChar(ts, c); js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_UNTERMINATED_REGEXP); RETURN(TOK_ERROR); } if (c == '\\') { if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); c = GetChar(ts); } if (!AddToTokenBuf(cx, &ts->tokenbuf, (jschar)c)) RETURN(TOK_ERROR); } FINISH_TOKENBUF(&ts->tokenbuf); for (flags = 0; ; ) { if (MatchChar(ts, 'g')) flags |= JSREG_GLOB; else if (MatchChar(ts, 'i')) flags |= JSREG_FOLD; else if (MatchChar(ts, 'm')) flags |= JSREG_MULTILINE; else break; } c = PeekChar(ts); if (JS7_ISLET(c)) { tp->ptr = ts->linebuf.ptr - 1; js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_BAD_REGEXP_FLAG); (void) GetChar(ts); RETURN(TOK_ERROR); } obj = js_NewRegExpObject(cx, ts, ts->tokenbuf.base, TOKEN_LENGTH(&ts->tokenbuf), flags); if (!obj) RETURN(TOK_ERROR); atom = js_AtomizeObject(cx, obj, 0); if (!atom) RETURN(TOK_ERROR); tp->t_op = JSOP_OBJECT; tp->t_atom = atom; RETURN(TOK_OBJECT); } #endif /* JS_HAS_REGEXPS */ tp->t_op = JSOP_DIV; c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP; break; case '%': tp->t_op = JSOP_MOD; c = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP; break; case '~': tp->t_op = JSOP_BITNOT; c = TOK_UNARYOP; break; case '+': if (MatchChar(ts, '=')) { tp->t_op = JSOP_ADD; c = TOK_ASSIGN; } else if (MatchChar(ts, c)) { c = TOK_INC; } else { tp->t_op = JSOP_POS; c = TOK_PLUS; } break; case '-': if (MatchChar(ts, '=')) { tp->t_op = JSOP_SUB; c = TOK_ASSIGN; } else if (MatchChar(ts, c)) { if (PeekChar(ts) == '>' && !(ts->flags & TSF_DIRTYLINE)) goto skipline; c = TOK_DEC; } else { tp->t_op = JSOP_NEG; c = TOK_MINUS; } ts->flags |= TSF_DIRTYLINE; break; #if JS_HAS_SHARP_VARS case '#': { uint32 n; c = GetChar(ts); if (!JS7_ISDEC(c)) { UngetChar(ts, c); goto badchar; } n = (uint32)JS7_UNDEC(c); for (;;) { c = GetChar(ts); if (!JS7_ISDEC(c)) break; n = 10 * n + JS7_UNDEC(c); if (n >= ATOM_INDEX_LIMIT) { js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_SHARPVAR_TOO_BIG); RETURN(TOK_ERROR); } } tp->t_dval = (jsdouble) n; if (JS_HAS_STRICT_OPTION(cx) && (c == '=' || c == '#')) { char buf[20]; JS_snprintf(buf, sizeof buf, "#%u%c", n, c); if (!js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_WARNING | JSREPORT_STRICT, JSMSG_DEPRECATED_USAGE, buf)) { RETURN(TOK_ERROR); } } if (c == '=') RETURN(TOK_DEFSHARP); if (c == '#') RETURN(TOK_USESHARP); goto badchar; } badchar: #endif /* JS_HAS_SHARP_VARS */ default: js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, JSMSG_ILLEGAL_CHARACTER); RETURN(TOK_ERROR); } JS_ASSERT(c < TOK_LIMIT); RETURN((JSTokenType)c); #undef INIT_TOKENBUF #undef FINISH_TOKENBUF #undef TOKEN_LENGTH #undef RETURN }
static char* FormatJSFrame(JSContext* cx, JSStackFrame* fp, char* buf, int num, JSBool showArgs, JSBool showLocals, JSBool showThisProps) { JSPropertyDescArray callProps = {0, nsnull}; JSPropertyDescArray thisProps = {0, nsnull}; JSBool gotThisVal = JS_FALSE; jsval thisVal; JSObject* callObj = nsnull; JSString* funname = nsnull; JSAutoByteString funbytes; const char* filename = nsnull; PRInt32 lineno = 0; JSFunction* fun = nsnull; uint32 namedArgCount = 0; jsval val; JSBool isString; // get the info for this stack frame JSScript* script = JS_GetFrameScript(cx, fp); jsbytecode* pc = JS_GetFramePC(cx, fp); JSAutoRequest ar(cx); JSAutoEnterCompartment ac; if(!ac.enter(cx, JS_GetFrameScopeChain(cx, fp))) return buf; if(script && pc) { filename = JS_GetScriptFilename(cx, script); lineno = (PRInt32) JS_PCToLineNumber(cx, script, pc); fun = JS_GetFrameFunction(cx, fp); if(fun) funname = JS_GetFunctionId(fun); if(showArgs || showLocals) { callObj = JS_GetFrameCallObject(cx, fp); if(callObj) if(!JS_GetPropertyDescArray(cx, callObj, &callProps)) callProps.array = nsnull; // just to be sure } gotThisVal = JS_GetFrameThis(cx, fp, &thisVal); if (!gotThisVal || !showThisProps || JSVAL_IS_PRIMITIVE(thisVal) || !JS_GetPropertyDescArray(cx, JSVAL_TO_OBJECT(thisVal), &thisProps)) { thisProps.array = nsnull; // just to be sure } } // print the frame number and function name if(funname) buf = JS_sprintf_append(buf, "%d %s(", num, funbytes.encode(cx, funname)); else if(fun) buf = JS_sprintf_append(buf, "%d anonymous(", num); else buf = JS_sprintf_append(buf, "%d <TOP LEVEL>", num); if(!buf) goto out; // print the function arguments if(showArgs && callObj) { for(uint32 i = 0; i < callProps.length; i++) { JSPropertyDesc* desc = &callProps.array[i]; if(desc->flags & JSPD_ARGUMENT) { JSAutoByteString nameBytes; const char* name = JSVAL2String(cx, desc->id, &isString, &nameBytes); if(!isString) name = nsnull; JSAutoByteString valueBytes; const char* value = JSVAL2String(cx, desc->value, &isString, &valueBytes); buf = JS_sprintf_append(buf, "%s%s%s%s%s%s", namedArgCount ? ", " : "", name ? name :"", name ? " = " : "", isString ? "\"" : "", value ? value : "?unknown?", isString ? "\"" : ""); if(!buf) goto out; namedArgCount++; } } // print any unnamed trailing args (found in 'arguments' object) if(JS_GetProperty(cx, callObj, "arguments", &val) && JSVAL_IS_OBJECT(val)) { uint32 argCount; JSObject* argsObj = JSVAL_TO_OBJECT(val); if(JS_GetProperty(cx, argsObj, "length", &val) && JS_ValueToECMAUint32(cx, val, &argCount) && argCount > namedArgCount) { for(uint32 k = namedArgCount; k < argCount; k++) { char number[8]; JS_snprintf(number, 8, "%d", (int) k); if(JS_GetProperty(cx, argsObj, number, &val)) { JSAutoByteString valueBytes; const char *value = JSVAL2String(cx, val, &isString, &valueBytes); buf = JS_sprintf_append(buf, "%s%s%s%s", k ? ", " : "", isString ? "\"" : "", value ? value : "?unknown?", isString ? "\"" : ""); if(!buf) goto out; } } } } } // print filename and line number buf = JS_sprintf_append(buf, "%s [\"%s\":%d]\n", fun ? ")" : "", filename ? filename : "<unknown>", lineno); if(!buf) goto out; // print local variables if(showLocals && callProps.array) { for(uint32 i = 0; i < callProps.length; i++) { JSPropertyDesc* desc = &callProps.array[i]; if(desc->flags & JSPD_VARIABLE) { JSAutoByteString nameBytes; JSAutoByteString valueBytes; const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes); const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes); if(name && value) { buf = JS_sprintf_append(buf, TAB "%s = %s%s%s\n", name, isString ? "\"" : "", value, isString ? "\"" : ""); if(!buf) goto out; } } } } // print the value of 'this' if(showLocals) { if(gotThisVal) { JSString* thisValStr; JSAutoByteString thisValBytes; if(nsnull != (thisValStr = JS_ValueToString(cx, thisVal)) && thisValBytes.encode(cx, thisValStr)) { buf = JS_sprintf_append(buf, TAB "this = %s\n", thisValBytes.ptr()); if(!buf) goto out; } } else buf = JS_sprintf_append(buf, TAB "<failed to get 'this' value>\n"); } // print the properties of 'this', if it is an object if(showThisProps && thisProps.array) { for(uint32 i = 0; i < thisProps.length; i++) { JSPropertyDesc* desc = &thisProps.array[i]; if(desc->flags & JSPD_ENUMERATE) { JSAutoByteString nameBytes; JSAutoByteString valueBytes; const char *name = JSVAL2String(cx, desc->id, nsnull, &nameBytes); const char *value = JSVAL2String(cx, desc->value, &isString, &valueBytes); if(name && value) { buf = JS_sprintf_append(buf, TAB "this.%s = %s%s%s\n", name, isString ? "\"" : "", value, isString ? "\"" : ""); if(!buf) goto out; } } } } out: if(callProps.array) JS_PutPropertyDescArray(cx, &callProps); if(thisProps.array) JS_PutPropertyDescArray(cx, &thisProps); return buf; }
// static void XPCTraceableVariant::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize) { JS_snprintf(buf, bufsize, "XPCVariant[0x%p].mJSVal", trc->debugPrintArg); }
static JSString * StackTraceToString(JSContext *cx, JSExnPrivate *priv) { jschar *stackbuf; size_t stacklen, stackmax; JSStackTraceElem *elem, *endElem; jsval *values; size_t i; JSString *str; const char *cp; char ulnbuf[11]; /* After this point, failing control flow must goto bad. */ stackbuf = NULL; stacklen = stackmax = 0; /* Limit the stackbuf length to a reasonable value to avoid overflow checks. */ #define STACK_LENGTH_LIMIT JS_BIT(20) #define APPEND_CHAR_TO_STACK(c) \ JS_BEGIN_MACRO \ if (stacklen == stackmax) { \ void *ptr_; \ if (stackmax >= STACK_LENGTH_LIMIT) \ goto done; \ stackmax = stackmax ? 2 * stackmax : 64; \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ } \ stackbuf[stacklen++] = (c); \ JS_END_MACRO #define APPEND_STRING_TO_STACK(str) \ JS_BEGIN_MACRO \ JSString *str_ = str; \ jschar *chars_; \ size_t length_; \ \ JSSTRING_CHARS_AND_LENGTH(str_, chars_, length_); \ if (length_ > stackmax - stacklen) { \ void *ptr_; \ if (stackmax >= STACK_LENGTH_LIMIT || \ length_ >= STACK_LENGTH_LIMIT - stacklen) { \ goto done; \ } \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) \ goto bad; \ stackbuf = (jschar *) ptr_; \ } \ js_strncpy(stackbuf + stacklen, chars_, length_); \ stacklen += length_; \ JS_END_MACRO values = GetStackTraceValueBuffer(priv); elem = priv->stackElems; for (endElem = elem + priv->stackDepth; elem != endElem; elem++) { if (elem->funName) { APPEND_STRING_TO_STACK(elem->funName); APPEND_CHAR_TO_STACK('('); for (i = 0; i != elem->argc; i++, values++) { if (i > 0) APPEND_CHAR_TO_STACK(','); str = ValueToShortSource(cx, *values); if (!str) goto bad; APPEND_STRING_TO_STACK(str); } APPEND_CHAR_TO_STACK(')'); } APPEND_CHAR_TO_STACK('@'); if (elem->filename) { for (cp = elem->filename; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } APPEND_CHAR_TO_STACK(':'); JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", elem->ulineno); for (cp = ulnbuf; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); APPEND_CHAR_TO_STACK('\n'); } #undef APPEND_CHAR_TO_STACK #undef APPEND_STRING_TO_STACK #undef STACK_LENGTH_LIMIT done: if (stacklen == 0) { JS_ASSERT(!stackbuf); return cx->runtime->emptyString; } if (stacklen < stackmax) { /* * Realloc can fail when shrinking on some FreeBSD versions, so * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = (jschar *) shrunk; } stackbuf[stacklen] = 0; str = js_NewString(cx, stackbuf, stacklen); if (str) return str; bad: if (stackbuf) JS_free(cx, stackbuf); return NULL; }