本文整理汇总了C++中JSString::ensureLinear方法的典型用法代码示例。如果您正苦于以下问题:C++ JSString::ensureLinear方法的具体用法?C++ JSString::ensureLinear怎么用?C++ JSString::ensureLinear使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类JSString
的用法示例。
在下文中一共展示了JSString::ensureLinear方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: fprintf
void
Shape::dump(JSContext *cx, FILE *fp) const
{
JS_ASSERT(!JSID_IS_VOID(id));
if (JSID_IS_INT(id)) {
fprintf(fp, "[%ld]", (long) JSID_TO_INT(id));
} else if (JSID_IS_DEFAULT_XML_NAMESPACE(id)) {
fprintf(fp, "<default XML namespace>");
} else {
JSLinearString *str;
if (JSID_IS_ATOM(id)) {
str = JSID_TO_ATOM(id);
} else {
JS_ASSERT(JSID_IS_OBJECT(id));
JSString *s = js_ValueToString(cx, IdToValue(id));
fputs("object ", fp);
str = s ? s->ensureLinear(cx) : NULL;
}
if (!str)
fputs("<error>", fp);
else
FileEscapedString(fp, str, '"');
}
fprintf(fp, " g/s %p/%p slot %u attrs %x ",
JS_FUNC_TO_DATA_PTR(void *, rawGetter),
JS_FUNC_TO_DATA_PTR(void *, rawSetter),
slot, attrs);
if (attrs) {
int first = 1;
fputs("(", fp);
#define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(" " #display + first, fp), first = 0
DUMP_ATTR(ENUMERATE, enumerate);
DUMP_ATTR(READONLY, readonly);
DUMP_ATTR(PERMANENT, permanent);
DUMP_ATTR(GETTER, getter);
DUMP_ATTR(SETTER, setter);
DUMP_ATTR(SHARED, shared);
#undef DUMP_ATTR
fputs(") ", fp);
}
fprintf(fp, "flags %x ", flags);
if (flags) {
int first = 1;
fputs("(", fp);
#define DUMP_FLAG(name, display) if (flags & name) fputs(" " #display + first, fp), first = 0
DUMP_FLAG(ALIAS, alias);
DUMP_FLAG(HAS_SHORTID, has_shortid);
DUMP_FLAG(METHOD, method);
DUMP_FLAG(MARK, mark);
DUMP_FLAG(SHAPE_REGEN, shape_regen);
DUMP_FLAG(IN_DICTIONARY, in_dictionary);
#undef DUMP_FLAG
fputs(") ", fp);
}
fprintf(fp, "shortid %d\n", shortid);
}
示例2: reviver
JSBool
js_json_parse(JSContext *cx, uintN argc, Value *vp)
{
JSString *s = NULL;
Value *argv = vp + 2;
AutoValueRooter reviver(cx);
if (!JS_ConvertArguments(cx, argc, Jsvalify(argv), "S / v", &s, reviver.addr()))
return JS_FALSE;
JSLinearString *linearStr = s->ensureLinear(cx);
if (!linearStr)
return JS_FALSE;
JSONParser *jp = js_BeginJSONParse(cx, vp);
JSBool ok = jp != NULL;
if (ok) {
const jschar *chars = linearStr->chars();
size_t length = linearStr->length();
ok = js_ConsumeJSONText(cx, jp, chars, length);
ok &= !!js_FinishJSONParse(cx, jp, reviver.value());
}
return ok;
}
示例3: fprintf
void
Shape::dump(JSContext *cx, FILE *fp) const
{
jsid propid = this->propid();
JS_ASSERT(!JSID_IS_VOID(propid));
if (JSID_IS_INT(propid)) {
fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid));
} else if (JSID_IS_DEFAULT_XML_NAMESPACE(propid)) {
fprintf(fp, "<default XML namespace>");
} else {
JSLinearString *str;
if (JSID_IS_ATOM(propid)) {
str = JSID_TO_ATOM(propid);
} else {
JS_ASSERT(JSID_IS_OBJECT(propid));
JSString *s = ToStringSlow<CanGC>(cx, IdToValue(propid));
fputs("object ", fp);
str = s ? s->ensureLinear(cx) : NULL;
}
if (!str)
fputs("<error>", fp);
else
FileEscapedString(fp, str, '"');
}
fprintf(fp, " g/s %p/%p slot %d attrs %x ",
JS_FUNC_TO_DATA_PTR(void *, base()->rawGetter),
JS_FUNC_TO_DATA_PTR(void *, base()->rawSetter),
hasSlot() ? slot() : -1, attrs);
if (attrs) {
int first = 1;
fputs("(", fp);
#define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(&(" " #display)[first], fp), first = 0
DUMP_ATTR(ENUMERATE, enumerate);
DUMP_ATTR(READONLY, readonly);
DUMP_ATTR(PERMANENT, permanent);
DUMP_ATTR(GETTER, getter);
DUMP_ATTR(SETTER, setter);
DUMP_ATTR(SHARED, shared);
#undef DUMP_ATTR
fputs(") ", fp);
}
fprintf(fp, "flags %x ", flags);
if (flags) {
int first = 1;
fputs("(", fp);
#define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0
DUMP_FLAG(HAS_SHORTID, has_shortid);
DUMP_FLAG(IN_DICTIONARY, in_dictionary);
#undef DUMP_FLAG
fputs(") ", fp);
}
fprintf(fp, "shortid %d\n", maybeShortid());
}
示例4: suppress
void
Shape::dump(JSContext *cx, FILE *fp) const
{
/* This is only used from gdb, so allowing GC here would just be confusing. */
gc::AutoSuppressGC suppress(cx);
jsid propid = this->propid();
JS_ASSERT(!JSID_IS_VOID(propid));
if (JSID_IS_INT(propid)) {
fprintf(fp, "[%ld]", (long) JSID_TO_INT(propid));
} else {
JSLinearString *str;
if (JSID_IS_ATOM(propid)) {
str = JSID_TO_ATOM(propid);
} else {
JS_ASSERT(JSID_IS_OBJECT(propid));
Value v = IdToValue(propid);
JSString *s = ToStringSlow<NoGC>(cx, v);
fputs("object ", fp);
str = s ? s->ensureLinear(cx) : nullptr;
}
if (!str)
fputs("<error>", fp);
else
FileEscapedString(fp, str, '"');
}
fprintf(fp, " g/s %p/%p slot %d attrs %x ",
JS_FUNC_TO_DATA_PTR(void *, base()->rawGetter),
JS_FUNC_TO_DATA_PTR(void *, base()->rawSetter),
hasSlot() ? slot() : -1, attrs);
if (attrs) {
int first = 1;
fputs("(", fp);
#define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(&(" " #display)[first], fp), first = 0
DUMP_ATTR(ENUMERATE, enumerate);
DUMP_ATTR(READONLY, readonly);
DUMP_ATTR(PERMANENT, permanent);
DUMP_ATTR(GETTER, getter);
DUMP_ATTR(SETTER, setter);
DUMP_ATTR(SHARED, shared);
#undef DUMP_ATTR
fputs(") ", fp);
}
fprintf(fp, "flags %x ", flags);
if (flags) {
int first = 1;
fputs("(", fp);
#define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0
DUMP_FLAG(IN_DICTIONARY, in_dictionary);
#undef DUMP_FLAG
fputs(") ", fp);
}
}
示例5: key
bool
JSCompartment::wrap(JSContext *cx, JSString **strp)
{
JS_ASSERT(!cx->runtime()->isAtomsCompartment(this));
JS_ASSERT(cx->compartment() == this);
/* If the string is already in this compartment, we are done. */
JSString *str = *strp;
if (str->zone() == zone())
return true;
/* If the string is an atom, we don't have to copy. */
if (str->isAtom()) {
JS_ASSERT(cx->runtime()->isAtomsZone(str->zone()));
return true;
}
/* Check the cache. */
RootedValue key(cx, StringValue(str));
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) {
*strp = p->value().get().toString();
return true;
}
/* No dice. Make a copy, and cache it. */
Rooted<JSLinearString *> linear(cx, str->ensureLinear(cx));
if (!linear)
return false;
JSString *copy = js_NewStringCopyN<CanGC>(cx, linear->chars(),
linear->length());
if (!copy)
return false;
if (!putWrapper(key, StringValue(copy)))
return false;
if (linear->zone()->isGCMarking()) {
/*
* All string wrappers are dropped when collection starts, but we
* just created a new one. Mark the wrapped string to stop it being
* finalized, because if it was then the pointer in this
* compartment's wrapper map would be left dangling.
*/
JSString *tmp = linear;
MarkStringUnbarriered(&cx->runtime()->gcMarker, &tmp, "wrapped string");
JS_ASSERT(tmp == linear);
}
*strp = copy;
return true;
}
示例6: ParseJSONWithReviver
/* ES5 15.12.2. */
JSBool
js_json_parse(JSContext *cx, unsigned argc, Value *vp)
{
/* Step 1. */
JSLinearString *linear;
if (argc >= 1) {
JSString *str = ToString(cx, vp[2]);
if (!str)
return false;
linear = str->ensureLinear(cx);
if (!linear)
return false;
} else {
linear = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
}
JS::Anchor<JSString *> anchor(linear);
Value reviver = (argc >= 2) ? vp[3] : UndefinedValue();
/* Steps 2-5. */
return ParseJSONWithReviver(cx, linear->chars(), linear->length(), reviver, vp);
}
示例7: reviver
/* ES5 15.12.2. */
JSBool
js_json_parse(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
/* Step 1. */
JSLinearString *linear;
if (argc >= 1) {
JSString *str = ToString(cx, args[0]);
if (!str)
return false;
linear = str->ensureLinear(cx);
if (!linear)
return false;
} else {
linear = cx->names().undefined;
}
JS::Anchor<JSString *> anchor(linear);
RootedValue reviver(cx, (argc >= 2) ? args[1] : UndefinedValue());
/* Steps 2-5. */
return ParseJSONWithReviver(cx, linear->chars(), linear->length(), reviver, args.rval());
}
示例8: detector
JSString *
js::ObjectToSource(JSContext *cx, HandleObject obj)
{
/* If outermost, we need parentheses to be an expression, not a block. */
bool outermost = (cx->cycleDetectorSet.count() == 0);
AutoCycleDetector detector(cx, obj);
if (!detector.init())
return nullptr;
if (detector.foundCycle())
return js_NewStringCopyZ<CanGC>(cx, "{}");
StringBuffer buf(cx);
if (outermost && !buf.append('('))
return nullptr;
if (!buf.append('{'))
return nullptr;
RootedValue v0(cx), v1(cx);
MutableHandleValue val[2] = {&v0, &v1};
RootedString str0(cx), str1(cx);
MutableHandleString gsop[2] = {&str0, &str1};
AutoIdVector idv(cx);
if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &idv))
return nullptr;
bool comma = false;
for (size_t i = 0; i < idv.length(); ++i) {
RootedId id(cx, idv[i]);
RootedObject obj2(cx);
RootedShape shape(cx);
if (!JSObject::lookupGeneric(cx, obj, id, &obj2, &shape))
return nullptr;
/* Decide early whether we prefer get/set or old getter/setter syntax. */
int valcnt = 0;
if (shape) {
bool doGet = true;
if (obj2->isNative() && !IsImplicitDenseElement(shape)) {
unsigned attrs = shape->attributes();
if (attrs & JSPROP_GETTER) {
doGet = false;
val[valcnt].set(shape->getterValue());
gsop[valcnt].set(cx->names().get);
valcnt++;
}
if (attrs & JSPROP_SETTER) {
doGet = false;
val[valcnt].set(shape->setterValue());
gsop[valcnt].set(cx->names().set);
valcnt++;
}
}
if (doGet) {
valcnt = 1;
gsop[0].set(nullptr);
if (!JSObject::getGeneric(cx, obj, obj, id, val[0]))
return nullptr;
}
}
/* Convert id to a linear string. */
RootedValue idv(cx, IdToValue(id));
JSString *s = ToString<CanGC>(cx, idv);
if (!s)
return nullptr;
Rooted<JSLinearString*> idstr(cx, s->ensureLinear(cx));
if (!idstr)
return nullptr;
/*
* If id is a string that's not an identifier, or if it's a negative
* integer, then it must be quoted.
*/
if (JSID_IS_ATOM(id)
? !IsIdentifier(idstr)
: (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0))
{
s = js_QuoteString(cx, idstr, jschar('\''));
if (!s || !(idstr = s->ensureLinear(cx)))
return nullptr;
}
for (int j = 0; j < valcnt; j++) {
/*
* Censor an accessor descriptor getter or setter part if it's
* undefined.
*/
if (gsop[j] && val[j].isUndefined())
continue;
/* Convert val[j] to its canonical source form. */
RootedString valstr(cx, ValueToSource(cx, val[j]));
if (!valstr)
return nullptr;
const jschar *vchars = valstr->getChars(cx);
if (!vchars)
return nullptr;
//.........这里部分代码省略.........
示例9: ToString
/*
* Compile a new |RegExpPrivate| for the |RegExpObject|.
*
* Per ECMAv5 15.10.4.1, we act on combinations of (pattern, flags) as
* arguments:
*
* RegExp, undefined => flags := pattern.flags
* RegExp, _ => throw TypeError
* _ => pattern := ToString(pattern) if defined(pattern) else ''
* flags := ToString(flags) if defined(flags) else ''
*/
static bool
CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder,
uintN argc, Value *argv, Value *rval)
{
if (argc == 0) {
RegExpStatics *res = cx->regExpStatics();
RegExpObject *reobj = builder.build(cx->runtime->emptyString, res->getFlags());
if (!reobj)
return false;
*rval = ObjectValue(*reobj);
return true;
}
Value sourceValue = argv[0];
if (ValueIsRegExp(sourceValue)) {
/*
* If we get passed in a |RegExpObject| source we return a new
* object with the same source/flags.
*
* Note: the regexp static flags are not taken into consideration here.
*/
JSObject &sourceObj = sourceValue.toObject();
if (argc >= 2 && !argv[1].isUndefined()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED);
return false;
}
RegExpObject *reobj = builder.build(sourceObj.asRegExp());
if (!reobj)
return false;
*rval = ObjectValue(*reobj);
return true;
}
JSLinearString *sourceStr;
if (sourceValue.isUndefined()) {
sourceStr = cx->runtime->emptyString;
} else {
/* Coerce to string and compile. */
JSString *str = ToString(cx, sourceValue);
if (!str)
return false;
sourceStr = str->ensureLinear(cx);
if (!sourceStr)
return false;
}
RegExpFlag flags = RegExpFlag(0);
if (argc > 1 && !argv[1].isUndefined()) {
JSString *flagStr = ToString(cx, argv[1]);
if (!flagStr)
return false;
argv[1].setString(flagStr);
if (!ParseRegExpFlags(cx, flagStr, &flags))
return false;
}
JSLinearString *escapedSourceStr = EscapeNakedForwardSlashes(cx, sourceStr);
if (!escapedSourceStr)
return false;
if (!CheckRegExpSyntax(cx, escapedSourceStr))
return false;
RegExpStatics *res = cx->regExpStatics();
RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
if (!reobj)
return NULL;
*rval = ObjectValue(*reobj);
return true;
}
示例10: detector
//.........这里部分代码省略.........
}
if (doGet) {
valcnt = 1;
gsop[0].set(nullptr);
if (!JSObject::getGeneric(cx, obj, obj, id, val[0]))
return nullptr;
}
}
/* Convert id to a string. */
RootedString idstr(cx);
if (JSID_IS_SYMBOL(id)) {
RootedValue v(cx, SymbolValue(JSID_TO_SYMBOL(id)));
idstr = ValueToSource(cx, v);
if (!idstr)
return nullptr;
} else {
RootedValue idv(cx, IdToValue(id));
idstr = ToString<CanGC>(cx, idv);
if (!idstr)
return nullptr;
/*
* If id is a string that's not an identifier, or if it's a negative
* integer, then it must be quoted.
*/
if (JSID_IS_ATOM(id)
? !IsIdentifier(JSID_TO_ATOM(id))
: JSID_TO_INT(id) < 0)
{
idstr = js_QuoteString(cx, idstr, char16_t('\''));
if (!idstr)
return nullptr;
}
}
for (int j = 0; j < valcnt; j++) {
/*
* Censor an accessor descriptor getter or setter part if it's
* undefined.
*/
if (gsop[j] && val[j].isUndefined())
continue;
/* Convert val[j] to its canonical source form. */
JSString *valsource = ValueToSource(cx, val[j]);
if (!valsource)
return nullptr;
RootedLinearString valstr(cx, valsource->ensureLinear(cx));
if (!valstr)
return nullptr;
size_t voffset = 0;
size_t vlength = valstr->length();
/*
* Remove '(function ' from the beginning of valstr and ')' from the
* end so that we can put "get" in front of the function definition.
*/
if (gsop[j] && IsFunctionObject(val[j])) {
bool success;
JS::AutoCheckCannotGC nogc;
if (valstr->hasLatin1Chars())
success = ArgsAndBodySubstring(valstr->latin1Range(nogc), &voffset, &vlength);
else
success = ArgsAndBodySubstring(valstr->twoByteRange(nogc), &voffset, &vlength);
if (!success)
gsop[j].set(nullptr);
}
if (comma && !buf.append(", "))
return nullptr;
comma = true;
if (gsop[j]) {
if (!buf.append(gsop[j]) || !buf.append(' '))
return nullptr;
}
if (JSID_IS_SYMBOL(id) && !buf.append('['))
return nullptr;
if (!buf.append(idstr))
return nullptr;
if (JSID_IS_SYMBOL(id) && !buf.append(']'))
return nullptr;
if (!buf.append(gsop[j] ? ' ' : ':'))
return nullptr;
if (!buf.appendSubstring(valstr, voffset, vlength))
return nullptr;
}
}
if (!buf.append('}'))
return nullptr;
if (outermost && !buf.append(')'))
return nullptr;
return buf.finishString();
}
示例11: detector
JSString*
js::ObjectToSource(JSContext* cx, HandleObject obj)
{
/* If outermost, we need parentheses to be an expression, not a block. */
bool outermost = (cx->cycleDetectorSet.count() == 0);
AutoCycleDetector detector(cx, obj);
if (!detector.init())
return nullptr;
if (detector.foundCycle())
return NewStringCopyZ<CanGC>(cx, "{}");
StringBuffer buf(cx);
if (outermost && !buf.append('('))
return nullptr;
if (!buf.append('{'))
return nullptr;
RootedValue v0(cx), v1(cx);
MutableHandleValue val[2] = {&v0, &v1};
RootedString str0(cx), str1(cx);
MutableHandleString gsop[2] = {&str0, &str1};
AutoIdVector idv(cx);
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_SYMBOLS, &idv))
return nullptr;
bool comma = false;
for (size_t i = 0; i < idv.length(); ++i) {
RootedId id(cx, idv[i]);
Rooted<PropertyDescriptor> desc(cx);
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
return nullptr;
int valcnt = 0;
if (desc.object()) {
if (desc.isAccessorDescriptor()) {
if (desc.hasGetterObject() && desc.getterObject()) {
val[valcnt].setObject(*desc.getterObject());
gsop[valcnt].set(cx->names().get);
valcnt++;
}
if (desc.hasSetterObject() && desc.setterObject()) {
val[valcnt].setObject(*desc.setterObject());
gsop[valcnt].set(cx->names().set);
valcnt++;
}
} else {
valcnt = 1;
val[0].set(desc.value());
gsop[0].set(nullptr);
}
}
/* Convert id to a string. */
RootedString idstr(cx);
if (JSID_IS_SYMBOL(id)) {
RootedValue v(cx, SymbolValue(JSID_TO_SYMBOL(id)));
idstr = ValueToSource(cx, v);
if (!idstr)
return nullptr;
} else {
RootedValue idv(cx, IdToValue(id));
idstr = ToString<CanGC>(cx, idv);
if (!idstr)
return nullptr;
/*
* If id is a string that's not an identifier, or if it's a negative
* integer, then it must be quoted.
*/
if (JSID_IS_ATOM(id)
? !IsIdentifier(JSID_TO_ATOM(id))
: JSID_TO_INT(id) < 0)
{
idstr = QuoteString(cx, idstr, char16_t('\''));
if (!idstr)
return nullptr;
}
}
for (int j = 0; j < valcnt; j++) {
/* Convert val[j] to its canonical source form. */
JSString* valsource = ValueToSource(cx, val[j]);
if (!valsource)
return nullptr;
RootedLinearString valstr(cx, valsource->ensureLinear(cx));
if (!valstr)
return nullptr;
size_t voffset = 0;
size_t vlength = valstr->length();
/*
* Remove '(function ' from the beginning of valstr and ')' from the
* end so that we can put "get" in front of the function definition.
*/
if (gsop[j] && IsFunctionObject(val[j])) {
//.........这里部分代码省略.........
示例12: thisv
// Common code implementing direct and indirect eval.
//
// Evaluate call.argv[2], if it is a string, in the context of the given calling
// frame, with the provided scope chain, with the semantics of either a direct
// or indirect eval (see ES5 10.4.2). If this is an indirect eval, scopeobj
// must be a global object.
//
// On success, store the completion value in call.rval and return true.
static bool
EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *caller,
HandleObject scopeobj)
{
JS_ASSERT((evalType == INDIRECT_EVAL) == (caller == NULL));
JS_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->isGlobal());
AssertInnerizedScopeChain(cx, *scopeobj);
if (!scopeobj->global().isRuntimeCodeGenEnabled(cx)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
return false;
}
// ES5 15.1.2.1 step 1.
if (args.length() < 1) {
args.rval().setUndefined();
return true;
}
if (!args[0].isString()) {
args.rval().set(args[0]);
return true;
}
JSString *str = args[0].toString();
// ES5 15.1.2.1 steps 2-8.
// Per ES5, indirect eval runs in the global scope. (eval is specified this
// way so that the compiler can make assumptions about what bindings may or
// may not exist in the current frame if it doesn't see 'eval'.)
unsigned staticLevel;
RootedValue thisv(cx);
if (evalType == DIRECT_EVAL) {
staticLevel = caller->script()->staticLevel + 1;
// Direct calls to eval are supposed to see the caller's |this|. If we
// haven't wrapped that yet, do so now, before we make a copy of it for
// the eval code to use.
if (!ComputeThis(cx, caller))
return false;
thisv = caller->thisValue();
} else {
JS_ASSERT(args.callee().global() == *scopeobj);
staticLevel = 0;
// Use the global as 'this', modulo outerization.
JSObject *thisobj = scopeobj->thisObject(cx);
if (!thisobj)
return false;
thisv = ObjectValue(*thisobj);
}
Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
if (!linearStr)
return false;
const jschar *chars = linearStr->chars();
size_t length = linearStr->length();
SkipRoot skip(cx, &chars);
// If the eval string starts with '(' or '[' and ends with ')' or ']', it may be JSON.
// Try the JSON parser first because it's much faster. If the eval string
// isn't JSON, JSON parsing will probably fail quickly, so little time
// will be lost.
//
// Don't use the JSON parser if the caller is strict mode code, because in
// strict mode object literals must not have repeated properties, and the
// JSON parser cheerfully (and correctly) accepts them. If you're parsing
// JSON with eval and using strict mode, you deserve to be slow.
if (length > 2 &&
((chars[0] == '[' && chars[length - 1] == ']') ||
(chars[0] == '(' && chars[length - 1] == ')')) &&
(!caller || !caller->script()->strictModeCode))
{
// Remarkably, JavaScript syntax is not a superset of JSON syntax:
// strings in JavaScript cannot contain the Unicode line and paragraph
// terminator characters U+2028 and U+2029, but strings in JSON can.
// Rather than force the JSON parser to handle this quirk when used by
// eval, we simply don't use the JSON parser when either character
// appears in the provided string. See bug 657367.
for (const jschar *cp = &chars[1], *end = &chars[length - 2]; ; cp++) {
if (*cp == 0x2028 || *cp == 0x2029)
break;
if (cp == end) {
bool isArray = (chars[0] == '[');
JSONParser parser(cx, isArray ? chars : chars + 1, isArray ? length : length - 2,
JSONParser::StrictJSON, JSONParser::NoError);
RootedValue tmp(cx);
if (!parser.parse(&tmp))
return false;
if (tmp.isUndefined())
break;
//.........这里部分代码省略.........