mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 609440, part 4 - make JSString::chars() fallible (r=waldo,dvander,igor,dwitte,njn)
This commit is contained in:
parent
56b2810a26
commit
e4bb2ca2a9
@ -1292,7 +1292,10 @@ StringToInteger(JSContext* cx, JSString* string, IntegerType* result)
|
|||||||
{
|
{
|
||||||
JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
|
JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
|
||||||
|
|
||||||
const jschar* cp = string->chars();
|
const jschar* cp = string->getChars(NULL);
|
||||||
|
if (!cp)
|
||||||
|
return false;
|
||||||
|
|
||||||
const jschar* end = cp + string->length();
|
const jschar* end = cp + string->length();
|
||||||
if (cp == end)
|
if (cp == end)
|
||||||
return false;
|
return false;
|
||||||
@ -1780,9 +1783,10 @@ ImplicitConvert(JSContext* cx,
|
|||||||
JSString* str = JSVAL_TO_STRING(val); \
|
JSString* str = JSVAL_TO_STRING(val); \
|
||||||
if (str->length() != 1) \
|
if (str->length() != 1) \
|
||||||
return TypeError(cx, #name, val); \
|
return TypeError(cx, #name, val); \
|
||||||
\
|
const jschar *chars = str->getChars(cx); \
|
||||||
result = str->chars()[0]; \
|
if (!chars) \
|
||||||
\
|
return false; \
|
||||||
|
result = chars[0]; \
|
||||||
} else if (!jsvalToInteger(cx, val, &result)) { \
|
} else if (!jsvalToInteger(cx, val, &result)) { \
|
||||||
return TypeError(cx, #name, val); \
|
return TypeError(cx, #name, val); \
|
||||||
} \
|
} \
|
||||||
@ -1824,8 +1828,10 @@ ImplicitConvert(JSContext* cx,
|
|||||||
// which the caller assumes ownership of.
|
// which the caller assumes ownership of.
|
||||||
// TODO: Extend this so we can safely convert strings at other times also.
|
// TODO: Extend this so we can safely convert strings at other times also.
|
||||||
JSString* sourceString = JSVAL_TO_STRING(val);
|
JSString* sourceString = JSVAL_TO_STRING(val);
|
||||||
const jschar* sourceChars = sourceString->chars();
|
|
||||||
size_t sourceLength = sourceString->length();
|
size_t sourceLength = sourceString->length();
|
||||||
|
const jschar* sourceChars = sourceString->getChars(cx);
|
||||||
|
if (!sourceChars)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (CType::GetTypeCode(cx, baseType)) {
|
switch (CType::GetTypeCode(cx, baseType)) {
|
||||||
case TYPE_char:
|
case TYPE_char:
|
||||||
@ -1879,8 +1885,10 @@ ImplicitConvert(JSContext* cx,
|
|||||||
|
|
||||||
if (JSVAL_IS_STRING(val)) {
|
if (JSVAL_IS_STRING(val)) {
|
||||||
JSString* sourceString = JSVAL_TO_STRING(val);
|
JSString* sourceString = JSVAL_TO_STRING(val);
|
||||||
const jschar* sourceChars = sourceString->chars();
|
|
||||||
size_t sourceLength = sourceString->length();
|
size_t sourceLength = sourceString->length();
|
||||||
|
const jschar* sourceChars = sourceString->getChars(cx);
|
||||||
|
if (!sourceChars)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (CType::GetTypeCode(cx, baseType)) {
|
switch (CType::GetTypeCode(cx, baseType)) {
|
||||||
case TYPE_char:
|
case TYPE_char:
|
||||||
@ -1989,21 +1997,18 @@ ImplicitConvert(JSContext* cx,
|
|||||||
if (JSID_IS_VOID(id))
|
if (JSID_IS_VOID(id))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
js::AutoValueRooter fieldVal(cx);
|
if (!JSID_IS_STRING(id)) {
|
||||||
JS_IdToValue(cx, id, fieldVal.jsval_addr());
|
|
||||||
if (!JSVAL_IS_STRING(fieldVal.jsval_value())) {
|
|
||||||
JS_ReportError(cx, "property name is not a string");
|
JS_ReportError(cx, "property name is not a string");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FieldInfo* field = StructType::LookupField(cx, targetType,
|
JSFlatString *name = JSID_TO_FLAT_STRING(id);
|
||||||
JSVAL_TO_STRING(fieldVal.jsval_value()));
|
const FieldInfo* field = StructType::LookupField(cx, targetType, name);
|
||||||
if (!field)
|
if (!field)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSString* name = JSVAL_TO_STRING(fieldVal.jsval_value());
|
|
||||||
js::AutoValueRooter prop(cx);
|
js::AutoValueRooter prop(cx);
|
||||||
if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), prop.jsval_addr()))
|
if (!JS_GetPropertyById(cx, obj, id, prop.jsval_addr()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Convert the field via ImplicitConvert().
|
// Convert the field via ImplicitConvert().
|
||||||
@ -3567,8 +3572,10 @@ ArrayType::ConstructData(JSContext* cx,
|
|||||||
// We were given a string. Size the array to the appropriate length,
|
// We were given a string. Size the array to the appropriate length,
|
||||||
// including space for the terminator.
|
// including space for the terminator.
|
||||||
JSString* sourceString = JSVAL_TO_STRING(argv[0]);
|
JSString* sourceString = JSVAL_TO_STRING(argv[0]);
|
||||||
const jschar* sourceChars = sourceString->chars();
|
|
||||||
size_t sourceLength = sourceString->length();
|
size_t sourceLength = sourceString->length();
|
||||||
|
const jschar* sourceChars = sourceString->getChars(cx);
|
||||||
|
if (!sourceChars)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (CType::GetTypeCode(cx, baseType)) {
|
switch (CType::GetTypeCode(cx, baseType)) {
|
||||||
case TYPE_char:
|
case TYPE_char:
|
||||||
@ -3871,7 +3878,7 @@ ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
|
|
||||||
// For a struct field descriptor 'val' of the form { name : type }, extract
|
// For a struct field descriptor 'val' of the form { name : type }, extract
|
||||||
// 'name' and 'type'.
|
// 'name' and 'type'.
|
||||||
static JSString*
|
static JSFlatString*
|
||||||
ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
||||||
{
|
{
|
||||||
if (JSVAL_IS_PRIMITIVE(val)) {
|
if (JSVAL_IS_PRIMITIVE(val)) {
|
||||||
@ -3885,23 +3892,21 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||||||
return NULL;
|
return NULL;
|
||||||
js::AutoObjectRooter iterroot(cx, iter);
|
js::AutoObjectRooter iterroot(cx, iter);
|
||||||
|
|
||||||
jsid id;
|
jsid nameid;
|
||||||
if (!JS_NextProperty(cx, iter, &id))
|
if (!JS_NextProperty(cx, iter, &nameid))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (JSID_IS_VOID(id)) {
|
if (JSID_IS_VOID(nameid)) {
|
||||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
js::AutoValueRooter nameVal(cx);
|
if (!JSID_IS_STRING(nameid)) {
|
||||||
JS_IdToValue(cx, id, nameVal.jsval_addr());
|
|
||||||
if (!JSVAL_IS_STRING(nameVal.jsval_value())) {
|
|
||||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
JSString* name = JSVAL_TO_STRING(nameVal.jsval_value());
|
|
||||||
|
|
||||||
// make sure we have one, and only one, property
|
// make sure we have one, and only one, property
|
||||||
|
jsid id;
|
||||||
if (!JS_NextProperty(cx, iter, &id))
|
if (!JS_NextProperty(cx, iter, &id))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!JSID_IS_VOID(id)) {
|
if (!JSID_IS_VOID(id)) {
|
||||||
@ -3910,7 +3915,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
js::AutoValueRooter propVal(cx);
|
js::AutoValueRooter propVal(cx);
|
||||||
if (!JS_GetUCProperty(cx, obj, name->chars(), name->length(), propVal.jsval_addr()))
|
if (!JS_GetPropertyById(cx, obj, nameid, propVal.jsval_addr()))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (propVal.value().isPrimitive() ||
|
if (propVal.value().isPrimitive() ||
|
||||||
@ -3929,7 +3934,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return JSID_TO_FLAT_STRING(nameid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For a struct field with 'name' and 'type', add an element of the form
|
// For a struct field with 'name' and 'type', add an element of the form
|
||||||
@ -3937,7 +3942,7 @@ ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
|
|||||||
static JSBool
|
static JSBool
|
||||||
AddFieldToArray(JSContext* cx,
|
AddFieldToArray(JSContext* cx,
|
||||||
jsval* element,
|
jsval* element,
|
||||||
JSString* name,
|
JSFlatString* name,
|
||||||
JSObject* typeObj)
|
JSObject* typeObj)
|
||||||
{
|
{
|
||||||
JSObject* fieldObj = JS_NewObject(cx, NULL, NULL, NULL);
|
JSObject* fieldObj = JS_NewObject(cx, NULL, NULL, NULL);
|
||||||
@ -4048,7 +4053,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
JSObject* fieldType = NULL;
|
JSObject* fieldType = NULL;
|
||||||
JSString* name = ExtractStructField(cx, item.jsval_value(), &fieldType);
|
JSFlatString* name = ExtractStructField(cx, item.jsval_value(), &fieldType);
|
||||||
if (!name)
|
if (!name)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
fieldRootsArray[i] = OBJECT_TO_JSVAL(fieldType);
|
fieldRootsArray[i] = OBJECT_TO_JSVAL(fieldType);
|
||||||
@ -4321,7 +4326,7 @@ StructType::GetFieldInfo(JSContext* cx, JSObject* obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FieldInfo*
|
const FieldInfo*
|
||||||
StructType::LookupField(JSContext* cx, JSObject* obj, JSString *name)
|
StructType::LookupField(JSContext* cx, JSObject* obj, JSFlatString *name)
|
||||||
{
|
{
|
||||||
JS_ASSERT(CType::IsCType(cx, obj));
|
JS_ASSERT(CType::IsCType(cx, obj));
|
||||||
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_struct);
|
JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_struct);
|
||||||
@ -4417,7 +4422,7 @@ StructType::FieldGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_STRING(idval));
|
const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_FLAT_STRING(idval));
|
||||||
if (!field)
|
if (!field)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -4439,7 +4444,7 @@ StructType::FieldSetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_STRING(idval));
|
const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_FLAT_STRING(idval));
|
||||||
if (!field)
|
if (!field)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -4467,8 +4472,11 @@ StructType::AddressOfField(JSContext* cx, uintN argc, jsval* vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FieldInfo* field = LookupField(cx, typeObj,
|
JSFlatString *str = JS_FlattenString(cx, JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]));
|
||||||
JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]));
|
if (!str)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
const FieldInfo* field = LookupField(cx, typeObj, str);
|
||||||
if (!field)
|
if (!field)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -4611,18 +4619,23 @@ PrepareReturnType(JSContext* cx, jsval type)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE bool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
IsEllipsis(jsval v)
|
IsEllipsis(JSContext* cx, jsval v, bool* isEllipsis)
|
||||||
{
|
{
|
||||||
|
*isEllipsis = false;
|
||||||
if (!JSVAL_IS_STRING(v))
|
if (!JSVAL_IS_STRING(v))
|
||||||
return false;
|
return true;
|
||||||
JSString* str = JSVAL_TO_STRING(v);
|
JSString* str = JSVAL_TO_STRING(v);
|
||||||
if (str->length() != 3)
|
if (str->length() != 3)
|
||||||
|
return true;
|
||||||
|
const jschar* chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
const jschar* chars = str->chars(), dot('.');
|
jschar dot = '.';
|
||||||
return (chars[0] == dot &&
|
*isEllipsis = (chars[0] == dot &&
|
||||||
chars[1] == dot &&
|
chars[1] == dot &&
|
||||||
chars[2] == dot);
|
chars[2] == dot);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
@ -4737,7 +4750,10 @@ NewFunctionInfo(JSContext* cx,
|
|||||||
fninfo->mIsVariadic = false;
|
fninfo->mIsVariadic = false;
|
||||||
|
|
||||||
for (JSUint32 i = 0; i < argLength; ++i) {
|
for (JSUint32 i = 0; i < argLength; ++i) {
|
||||||
if (IsEllipsis(argTypes[i])) {
|
bool isEllipsis;
|
||||||
|
if (!IsEllipsis(cx, argTypes[i], &isEllipsis))
|
||||||
|
return false;
|
||||||
|
if (isEllipsis) {
|
||||||
fninfo->mIsVariadic = true;
|
fninfo->mIsVariadic = true;
|
||||||
if (i < 1) {
|
if (i < 1) {
|
||||||
JS_ReportError(cx, "\"...\" may not be the first and only parameter "
|
JS_ReportError(cx, "\"...\" may not be the first and only parameter "
|
||||||
|
@ -141,7 +141,10 @@ void
|
|||||||
AppendString(Vector<jschar, N, AP> &v, JSString* str)
|
AppendString(Vector<jschar, N, AP> &v, JSString* str)
|
||||||
{
|
{
|
||||||
JS_ASSERT(str);
|
JS_ASSERT(str);
|
||||||
v.append(str->chars(), str->length());
|
const jschar *chars = str->getChars(NULL);
|
||||||
|
if (!chars)
|
||||||
|
return;
|
||||||
|
v.append(chars, str->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N, class AP>
|
template <size_t N, class AP>
|
||||||
@ -154,8 +157,12 @@ AppendString(Vector<char, N, AP> &v, JSString* str)
|
|||||||
if (!v.resize(vlen + alen))
|
if (!v.resize(vlen + alen))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const jschar *chars = str->getChars(NULL);
|
||||||
|
if (!chars)
|
||||||
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; i < alen; ++i)
|
for (size_t i = 0; i < alen; ++i)
|
||||||
v[i + vlen] = char(str->chars()[i]);
|
v[i + vlen] = char(chars[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, size_t N, class AP, size_t ArrayLength>
|
template <class T, size_t N, class AP, size_t ArrayLength>
|
||||||
@ -186,33 +193,15 @@ PrependString(Vector<jschar, N, AP> &v, JSString* str)
|
|||||||
if (!v.resize(vlen + alen))
|
if (!v.resize(vlen + alen))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const jschar *chars = str->getChars(NULL);
|
||||||
|
if (!chars)
|
||||||
|
return;
|
||||||
|
|
||||||
// Move vector data forward. This is safe since we've already resized.
|
// Move vector data forward. This is safe since we've already resized.
|
||||||
memmove(v.begin() + alen, v.begin(), vlen * sizeof(jschar));
|
memmove(v.begin() + alen, v.begin(), vlen * sizeof(jschar));
|
||||||
|
|
||||||
// Copy data to insert.
|
// Copy data to insert.
|
||||||
memcpy(v.begin(), str->chars(), alen * sizeof(jschar));
|
memcpy(v.begin(), chars, alen * sizeof(jschar));
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, size_t N, size_t M, class AP>
|
|
||||||
bool
|
|
||||||
StringsEqual(Vector<T, N, AP> &v, Vector<T, M, AP> &w)
|
|
||||||
{
|
|
||||||
if (v.length() != w.length())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return memcmp(v.begin(), w.begin(), v.length() * sizeof(T)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N, class AP>
|
|
||||||
bool
|
|
||||||
StringsEqual(Vector<jschar, N, AP> &v, JSString* str)
|
|
||||||
{
|
|
||||||
JS_ASSERT(str);
|
|
||||||
size_t length = str->length();
|
|
||||||
if (v.length() != length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return memcmp(v.begin(), str->chars(), length * sizeof(jschar)) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -274,7 +263,7 @@ struct FieldInfo
|
|||||||
// Hash policy for FieldInfos.
|
// Hash policy for FieldInfos.
|
||||||
struct FieldHashPolicy
|
struct FieldHashPolicy
|
||||||
{
|
{
|
||||||
typedef JSString* Key;
|
typedef JSFlatString* Key;
|
||||||
typedef Key Lookup;
|
typedef Key Lookup;
|
||||||
|
|
||||||
static uint32 hash(const Lookup &l) {
|
static uint32 hash(const Lookup &l) {
|
||||||
@ -297,7 +286,7 @@ struct FieldHashPolicy
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef HashMap<JSString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy> FieldInfoHash;
|
typedef HashMap<JSFlatString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy> FieldInfoHash;
|
||||||
|
|
||||||
// Descriptor of ABI, return type, argument types, and variadicity for a
|
// Descriptor of ABI, return type, argument types, and variadicity for a
|
||||||
// FunctionType.
|
// FunctionType.
|
||||||
@ -482,7 +471,7 @@ namespace StructType {
|
|||||||
JSBool DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj);
|
JSBool DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj);
|
||||||
|
|
||||||
const FieldInfoHash* GetFieldInfo(JSContext* cx, JSObject* obj);
|
const FieldInfoHash* GetFieldInfo(JSContext* cx, JSObject* obj);
|
||||||
const FieldInfo* LookupField(JSContext* cx, JSObject* obj, JSString *name);
|
const FieldInfo* LookupField(JSContext* cx, JSObject* obj, JSFlatString *name);
|
||||||
JSObject* BuildFieldsArray(JSContext* cx, JSObject* obj);
|
JSObject* BuildFieldsArray(JSContext* cx, JSObject* obj);
|
||||||
ffi_type* BuildFFIType(JSContext* cx, JSObject* obj);
|
ffi_type* BuildFFIType(JSContext* cx, JSObject* obj);
|
||||||
}
|
}
|
||||||
|
@ -133,12 +133,13 @@ Library::Create(JSContext* cx, jsval path, JSCTypesCallbacks* callbacks)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRLibSpec libSpec;
|
PRLibSpec libSpec;
|
||||||
JSString* pathStr = JSVAL_TO_STRING(path);
|
JSFlatString* pathStr = JS_FlattenString(cx, JSVAL_TO_STRING(path));
|
||||||
|
if (!pathStr)
|
||||||
|
return NULL;
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// On Windows, converting to native charset may corrupt path string.
|
// On Windows, converting to native charset may corrupt path string.
|
||||||
// So, we have to use Unicode path directly.
|
// So, we have to use Unicode path directly.
|
||||||
const PRUnichar* pathChars = reinterpret_cast<const PRUnichar*>(
|
const PRUnichar* pathChars = JS_GetFlatStringChars(pathStr);
|
||||||
JS_GetStringCharsZ(cx, pathStr));
|
|
||||||
if (!pathChars)
|
if (!pathChars)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -584,16 +584,14 @@ JS_PUBLIC_API(JSBool)
|
|||||||
JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
|
JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
|
||||||
{
|
{
|
||||||
assertSameCompartment(cx, v1, v2);
|
assertSameCompartment(cx, v1, v2);
|
||||||
*equal = StrictlyEqual(cx, Valueify(v1), Valueify(v2));
|
return StrictlyEqual(cx, Valueify(v1), Valueify(v2), equal);
|
||||||
return JS_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same)
|
JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same)
|
||||||
{
|
{
|
||||||
assertSameCompartment(cx, v1, v2);
|
assertSameCompartment(cx, v1, v2);
|
||||||
*same = SameValue(Valueify(v1), Valueify(v2), cx);
|
return SameValue(cx, Valueify(v1), Valueify(v2), same);
|
||||||
return JS_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@ -2239,8 +2237,14 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
case JSTRACE_STRING:
|
case JSTRACE_STRING:
|
||||||
PutEscapedString(buf, bufsize, (JSString *)thing, 0);
|
{
|
||||||
|
JSString *str = (JSString *)thing;
|
||||||
|
if (str->isLinear())
|
||||||
|
PutEscapedString(buf, bufsize, str->assertIsLinear(), 0);
|
||||||
|
else
|
||||||
|
JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
case JSTRACE_XML:
|
case JSTRACE_XML:
|
||||||
@ -5208,17 +5212,8 @@ JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
|
|||||||
JS_PUBLIC_API(JSString *)
|
JS_PUBLIC_API(JSString *)
|
||||||
JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
|
JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
|
||||||
{
|
{
|
||||||
jschar *js;
|
|
||||||
JSString *str;
|
|
||||||
|
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
js = js_InflateString(cx, s, &n);
|
return js_NewStringCopyN(cx, s, n);
|
||||||
if (!js)
|
|
||||||
return NULL;
|
|
||||||
str = js_NewString(cx, js, n);
|
|
||||||
if (!str)
|
|
||||||
cx->free(js);
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSString *)
|
JS_PUBLIC_API(JSString *)
|
||||||
@ -5338,9 +5333,8 @@ JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
|
|||||||
{
|
{
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, str);
|
assertSameCompartment(cx, str);
|
||||||
const jschar *chars;
|
*plength = str->length();
|
||||||
str->getCharsAndLength(chars, *plength);
|
return str->getChars(cx);
|
||||||
return chars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(const jschar *)
|
JS_PUBLIC_API(const jschar *)
|
||||||
@ -5369,26 +5363,29 @@ JS_FlattenString(JSContext *cx, JSString *str)
|
|||||||
extern JS_PUBLIC_API(const jschar *)
|
extern JS_PUBLIC_API(const jschar *)
|
||||||
JS_GetFlatStringChars(JSFlatString *str)
|
JS_GetFlatStringChars(JSFlatString *str)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<JSString *>(str)->flatChars();
|
return str->chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32 *result)
|
JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32 *result)
|
||||||
{
|
{
|
||||||
*result = js_CompareStrings(str1, str2);
|
return CompareStrings(cx, str1, str2, result);
|
||||||
return JS_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, JSBool *match)
|
JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, JSBool *match)
|
||||||
{
|
{
|
||||||
return MatchStringAndAscii(str, asciiBytes);
|
JSLinearString *linearStr = str->ensureLinear(cx);
|
||||||
|
if (!linearStr)
|
||||||
|
return false;
|
||||||
|
*match = StringEqualsAscii(linearStr, asciiBytes);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
|
JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
|
||||||
{
|
{
|
||||||
return MatchStringAndAscii(str, asciiBytes);
|
return StringEqualsAscii(str, asciiBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
@ -5400,13 +5397,17 @@ JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote
|
|||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
|
JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
|
||||||
{
|
{
|
||||||
return PutEscapedString(buffer, size, str, quote);
|
JSLinearString *linearStr = str->ensureLinear(cx);
|
||||||
|
if (!linearStr)
|
||||||
|
return size_t(-1);
|
||||||
|
return PutEscapedString(buffer, size, linearStr, quote);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_FileEscapedString(FILE *fp, JSString *str, char quote)
|
JS_FileEscapedString(FILE *fp, JSString *str, char quote)
|
||||||
{
|
{
|
||||||
return FileEscapedString(fp, str, quote);
|
JSLinearString *linearStr = str->ensureLinear(NULL);
|
||||||
|
return linearStr && FileEscapedString(fp, linearStr, quote);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSString *)
|
JS_PUBLIC_API(JSString *)
|
||||||
@ -5470,13 +5471,19 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
|
|||||||
JS_PUBLIC_API(char *)
|
JS_PUBLIC_API(char *)
|
||||||
JS_EncodeString(JSContext *cx, JSString *str)
|
JS_EncodeString(JSContext *cx, JSString *str)
|
||||||
{
|
{
|
||||||
return js_DeflateString(cx, str->chars(), str->length());
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return NULL;
|
||||||
|
return js_DeflateString(cx, chars, str->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||||
{
|
{
|
||||||
return js_GetDeflatedStringLength(cx, str->chars(), str->length());
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return size_t(-1);
|
||||||
|
return js_GetDeflatedStringLength(cx, chars, str->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(size_t)
|
JS_PUBLIC_API(size_t)
|
||||||
@ -5488,12 +5495,15 @@ JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
|
|||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
size_t writtenLength = length;
|
size_t writtenLength = length;
|
||||||
if (js_DeflateStringToBuffer(NULL, str->chars(), str->length(), buffer, &writtenLength)) {
|
const jschar *chars = str->getChars(NULL);
|
||||||
|
if (!chars)
|
||||||
|
return size_t(-1);
|
||||||
|
if (js_DeflateStringToBuffer(NULL, chars, str->length(), buffer, &writtenLength)) {
|
||||||
JS_ASSERT(writtenLength <= length);
|
JS_ASSERT(writtenLength <= length);
|
||||||
return writtenLength;
|
return writtenLength;
|
||||||
}
|
}
|
||||||
JS_ASSERT(writtenLength <= length);
|
JS_ASSERT(writtenLength <= length);
|
||||||
size_t necessaryLength = js_GetDeflatedStringLength(NULL, str->chars(), str->length());
|
size_t necessaryLength = js_GetDeflatedStringLength(NULL, chars, str->length());
|
||||||
if (necessaryLength == size_t(-1))
|
if (necessaryLength == size_t(-1))
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
if (writtenLength != length) {
|
if (writtenLength != length) {
|
||||||
|
@ -143,10 +143,10 @@ ENSURE_SLOW_ARRAY(JSContext *cx, JSObject *obj)
|
|||||||
* 'id' is passed as a jsboxedword since the given id need not necessarily hold
|
* 'id' is passed as a jsboxedword since the given id need not necessarily hold
|
||||||
* an atomized string.
|
* an atomized string.
|
||||||
*/
|
*/
|
||||||
JSBool
|
bool
|
||||||
js_StringIsIndex(JSString *str, jsuint *indexp)
|
js_StringIsIndex(JSLinearString *str, jsuint *indexp)
|
||||||
{
|
{
|
||||||
jschar *cp = str->chars();
|
const jschar *cp = str->chars();
|
||||||
if (JS7_ISDEC(*cp) && str->length() < sizeof(MAXSTR)) {
|
if (JS7_ISDEC(*cp) && str->length() < sizeof(MAXSTR)) {
|
||||||
jsuint index = JS7_UNDEC(*cp++);
|
jsuint index = JS7_UNDEC(*cp++);
|
||||||
jsuint oldIndex = 0;
|
jsuint oldIndex = 0;
|
||||||
@ -166,10 +166,10 @@ js_StringIsIndex(JSString *str, jsuint *indexp)
|
|||||||
(oldIndex == (MAXINDEX / 10) && c < (MAXINDEX % 10))))
|
(oldIndex == (MAXINDEX / 10) && c < (MAXINDEX % 10))))
|
||||||
{
|
{
|
||||||
*indexp = index;
|
*indexp = index;
|
||||||
return JS_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return JS_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -1149,12 +1149,13 @@ array_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
vp->setString(str);
|
vp->setString(str);
|
||||||
const jschar *chars;
|
|
||||||
size_t charlen;
|
const jschar *chars = str->getChars(cx);
|
||||||
str->getCharsAndLength(chars, charlen);
|
if (!chars)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Append element to buffer. */
|
/* Append element to buffer. */
|
||||||
if (!cb.append(chars, charlen))
|
if (!cb.append(chars, chars + str->length()))
|
||||||
goto out;
|
goto out;
|
||||||
if (index + 1 != length) {
|
if (index + 1 != length) {
|
||||||
if (!js_AppendLiteral(cb, ", "))
|
if (!js_AppendLiteral(cb, ", "))
|
||||||
@ -1188,6 +1189,20 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
|
|||||||
{
|
{
|
||||||
JS_CHECK_RECURSION(cx, return false);
|
JS_CHECK_RECURSION(cx, return false);
|
||||||
|
|
||||||
|
/* Get characters to use for the separator. */
|
||||||
|
static const jschar comma = ',';
|
||||||
|
const jschar *sep;
|
||||||
|
size_t seplen;
|
||||||
|
if (sepstr) {
|
||||||
|
seplen = sepstr->length();
|
||||||
|
sep = sepstr->getChars(cx);
|
||||||
|
if (!sep)
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
sep = ,
|
||||||
|
seplen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use HashTable entry as the cycle indicator. On first visit, create the
|
* Use HashTable entry as the cycle indicator. On first visit, create the
|
||||||
* entry, and, when leaving, remove the entry.
|
* entry, and, when leaving, remove the entry.
|
||||||
@ -1197,10 +1212,8 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
|
|||||||
uint32 genBefore;
|
uint32 genBefore;
|
||||||
if (!hashp) {
|
if (!hashp) {
|
||||||
/* Not in hash table, so not a cycle. */
|
/* Not in hash table, so not a cycle. */
|
||||||
if (!cx->busyArrays.add(hashp, obj)) {
|
if (!cx->busyArrays.add(hashp, obj))
|
||||||
JS_ReportOutOfMemory(cx);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
genBefore = cx->busyArrays.generation();
|
genBefore = cx->busyArrays.generation();
|
||||||
} else {
|
} else {
|
||||||
/* Cycle, so return empty string. */
|
/* Cycle, so return empty string. */
|
||||||
@ -1214,17 +1227,6 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
|
|||||||
MUST_FLOW_THROUGH("out");
|
MUST_FLOW_THROUGH("out");
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
/* Get characters to use for the separator. */
|
|
||||||
static const jschar comma = ',';
|
|
||||||
const jschar *sep;
|
|
||||||
size_t seplen;
|
|
||||||
if (sepstr) {
|
|
||||||
sepstr->getCharsAndLength(sep, seplen);
|
|
||||||
} else {
|
|
||||||
sep = ,
|
|
||||||
seplen = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This object will take responsibility for the jschar buffer until the
|
* This object will take responsibility for the jschar buffer until the
|
||||||
* buffer is transferred to the returned JSString.
|
* buffer is transferred to the returned JSString.
|
||||||
@ -1710,15 +1712,10 @@ comparator_stack_cast(JSRedComparator func)
|
|||||||
static int
|
static int
|
||||||
sort_compare_strings(void *arg, const void *a, const void *b, int *result)
|
sort_compare_strings(void *arg, const void *a, const void *b, int *result)
|
||||||
{
|
{
|
||||||
const Value *av = (const Value *)a, *bv = (const Value *)b;
|
JSContext *cx = (JSContext *)arg;
|
||||||
|
JSString *astr = ((const Value *)a)->toString();
|
||||||
JS_ASSERT(av->isString());
|
JSString *bstr = ((const Value *)b)->toString();
|
||||||
JS_ASSERT(bv->isString());
|
return JS_CHECK_OPERATION_LIMIT(cx) && CompareStrings(cx, astr, bstr, result);
|
||||||
if (!JS_CHECK_OPERATION_LIMIT((JSContext *)arg))
|
|
||||||
return JS_FALSE;
|
|
||||||
|
|
||||||
*result = (int) js_CompareStrings(av->toString(), bv->toString());
|
|
||||||
return JS_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
@ -2615,9 +2612,14 @@ array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, Value *vp)
|
|||||||
!GetElement(cx, obj, (jsuint)i, &hole, vp)) {
|
!GetElement(cx, obj, (jsuint)i, &hole, vp)) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
if (!hole && StrictlyEqual(cx, *vp, tosearch)) {
|
if (!hole) {
|
||||||
vp->setNumber(i);
|
JSBool equal;
|
||||||
return JS_TRUE;
|
if (!StrictlyEqual(cx, *vp, tosearch, &equal))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (equal) {
|
||||||
|
vp->setNumber(i);
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (i == stop)
|
if (i == stop)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "jsprvtd.h"
|
#include "jsprvtd.h"
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
#include "jsatom.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
|
||||||
@ -87,8 +88,8 @@ JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
|
|||||||
return growSlots(cx, requiredCapacity) ? ED_OK : ED_FAILED;
|
return growSlots(cx, requiredCapacity) ? ED_OK : ED_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern JSBool
|
extern bool
|
||||||
js_StringIsIndex(JSString *str, jsuint *indexp);
|
js_StringIsIndex(JSLinearString *str, jsuint *indexp);
|
||||||
|
|
||||||
inline JSBool
|
inline JSBool
|
||||||
js_IdIsIndex(jsid id, jsuint *indexp)
|
js_IdIsIndex(jsid id, jsuint *indexp)
|
||||||
@ -105,26 +106,36 @@ js_IdIsIndex(jsid id, jsuint *indexp)
|
|||||||
if (JS_UNLIKELY(!JSID_IS_STRING(id)))
|
if (JS_UNLIKELY(!JSID_IS_STRING(id)))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
return js_StringIsIndex(JSID_TO_STRING(id), indexp);
|
return js_StringIsIndex(JSID_TO_ATOM(id), indexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XML really wants to pretend jsvals are jsids. */
|
/* XML really wants to pretend jsvals are jsids. */
|
||||||
inline JSBool
|
inline bool
|
||||||
js_IdValIsIndex(jsval id, jsuint *indexp)
|
js_IdValIsIndex(JSContext *cx, jsval id, jsuint *indexp, bool *isIndex)
|
||||||
{
|
{
|
||||||
if (JSVAL_IS_INT(id)) {
|
if (JSVAL_IS_INT(id)) {
|
||||||
jsint i;
|
jsint i;
|
||||||
i = JSVAL_TO_INT(id);
|
i = JSVAL_TO_INT(id);
|
||||||
if (i < 0)
|
if (i < 0) {
|
||||||
return JS_FALSE;
|
*isIndex = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
*indexp = (jsuint)i;
|
*indexp = (jsuint)i;
|
||||||
return JS_TRUE;
|
*isIndex = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JSVAL_IS_STRING(id))
|
if (!JSVAL_IS_STRING(id)) {
|
||||||
return JS_FALSE;
|
*isIndex = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return js_StringIsIndex(JSVAL_TO_STRING(id), indexp);
|
JSLinearString *str = JSVAL_TO_STRING(id)->ensureLinear(cx);
|
||||||
|
if (!str)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*isIndex = js_StringIsIndex(str, indexp);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern js::Class js_ArrayClass, js_SlowArrayClass;
|
extern js::Class js_ArrayClass, js_SlowArrayClass;
|
||||||
|
@ -457,17 +457,20 @@ js_SweepAtomState(JSContext *cx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSAtom *
|
JSAtom *
|
||||||
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
js_AtomizeString(JSContext *cx, JSString *strArg, uintN flags)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY)));
|
JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY)));
|
||||||
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
|
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
|
||||||
|
|
||||||
if (str->isAtomized())
|
if (strArg->isAtomized())
|
||||||
return STRING_TO_ATOM(str);
|
return STRING_TO_ATOM(strArg);
|
||||||
|
|
||||||
const jschar *chars;
|
JSLinearString *str = strArg->ensureLinear(cx);
|
||||||
size_t length;
|
if (!str)
|
||||||
str->getCharsAndLength(chars, length);
|
return NULL;
|
||||||
|
|
||||||
|
const jschar *chars = str->chars();
|
||||||
|
size_t length = str->length();
|
||||||
|
|
||||||
JSString *staticStr = JSString::lookupStaticString(chars, length);
|
JSString *staticStr = JSString::lookupStaticString(chars, length);
|
||||||
if (staticStr)
|
if (staticStr)
|
||||||
@ -482,7 +485,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||||||
/* Hashing the string should have flattened it if it was a rope. */
|
/* Hashing the string should have flattened it if it was a rope. */
|
||||||
JS_ASSERT(str->isFlat() || str->isDependent());
|
JS_ASSERT(str->isFlat() || str->isDependent());
|
||||||
|
|
||||||
JSString *key;
|
JSLinearString *key;
|
||||||
if (p) {
|
if (p) {
|
||||||
key = AtomEntryToKey(*p);
|
key = AtomEntryToKey(*p);
|
||||||
} else {
|
} else {
|
||||||
@ -506,9 +509,8 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||||||
} else {
|
} else {
|
||||||
if (needNewString) {
|
if (needNewString) {
|
||||||
SwitchToCompartment sc(cx, cx->runtime->defaultCompartment);
|
SwitchToCompartment sc(cx, cx->runtime->defaultCompartment);
|
||||||
jschar *chars = str->chars();
|
|
||||||
if (flags & ATOM_NOCOPY) {
|
if (flags & ATOM_NOCOPY) {
|
||||||
key = js_NewString(cx, chars, length);
|
key = js_NewString(cx, const_cast<jschar *>(str->flatChars()), length);
|
||||||
if (!key)
|
if (!key)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -537,7 +539,6 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
|
|||||||
|
|
||||||
AddAtomEntryFlags(*p, flags & (ATOM_PINNED | ATOM_INTERNED));
|
AddAtomEntryFlags(*p, flags & (ATOM_PINNED | ATOM_INTERNED));
|
||||||
|
|
||||||
JS_ASSERT(key->isAtomized());
|
|
||||||
JSAtom *atom = STRING_TO_ATOM(key);
|
JSAtom *atom = STRING_TO_ATOM(key);
|
||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
@ -607,7 +608,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
|
|||||||
state = &cx->runtime->atomState;
|
state = &cx->runtime->atomState;
|
||||||
|
|
||||||
JS_LOCK(cx, &state->lock);
|
JS_LOCK(cx, &state->lock);
|
||||||
AtomSet::Ptr p = state->atoms.lookup(&str);
|
AtomSet::Ptr p = state->atoms.lookup(str.assertIsFlat());
|
||||||
str2 = p ? AtomEntryToKey(*p) : NULL;
|
str2 = p ? AtomEntryToKey(*p) : NULL;
|
||||||
JS_UNLOCK(cx, &state->lock);
|
JS_UNLOCK(cx, &state->lock);
|
||||||
|
|
||||||
@ -628,7 +629,7 @@ js_DumpAtoms(JSContext *cx, FILE *fp)
|
|||||||
if (entry == 0) {
|
if (entry == 0) {
|
||||||
fputs("<uninitialized>", fp);
|
fputs("<uninitialized>", fp);
|
||||||
} else {
|
} else {
|
||||||
JSString *key = AtomEntryToKey(entry);
|
JSAtom *key = AtomEntryToKey(entry);
|
||||||
FileEscapedString(fp, key, '"');
|
FileEscapedString(fp, key, '"');
|
||||||
uintN flags = AtomEntryFlags(entry);
|
uintN flags = AtomEntryFlags(entry);
|
||||||
if (flags != 0) {
|
if (flags != 0) {
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \
|
#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \
|
||||||
(JSAtom *)str)
|
(JSAtom *)str)
|
||||||
#define ATOM_TO_STRING(atom) (JS_ASSERT_STRING_IS_FLAT((JSString *)(atom)))
|
#define ATOM_TO_STRING(atom) (atom)
|
||||||
#define ATOM_TO_JSVAL(atom) STRING_TO_JSVAL(ATOM_TO_STRING(atom))
|
#define ATOM_TO_JSVAL(atom) STRING_TO_JSVAL(ATOM_TO_STRING(atom))
|
||||||
|
|
||||||
/* Engine-internal extensions of jsid */
|
/* Engine-internal extensions of jsid */
|
||||||
@ -265,23 +265,23 @@ JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JS_GCTHING_ALIGN);
|
|||||||
|
|
||||||
typedef uintptr_t AtomEntryType;
|
typedef uintptr_t AtomEntryType;
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSString *
|
static JS_ALWAYS_INLINE JSAtom *
|
||||||
AtomEntryToKey(AtomEntryType entry)
|
AtomEntryToKey(AtomEntryType entry)
|
||||||
{
|
{
|
||||||
JS_ASSERT(entry != 0);
|
JS_ASSERT(entry != 0);
|
||||||
return (JSString *)(entry & ~ATOM_ENTRY_FLAG_MASK);
|
return (JSAtom *)(entry & ~ATOM_ENTRY_FLAG_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AtomHasher
|
struct AtomHasher
|
||||||
{
|
{
|
||||||
typedef JSString *Lookup;
|
typedef JSLinearString *Lookup;
|
||||||
|
|
||||||
static HashNumber hash(JSString *str) {
|
static HashNumber hash(JSLinearString *str) {
|
||||||
return js_HashString(str);
|
return js_HashString(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match(AtomEntryType entry, JSString *lookup) {
|
static bool match(AtomEntryType entry, JSLinearString *lookup) {
|
||||||
return entry ? js_EqualStrings(AtomEntryToKey(entry), lookup) : false;
|
return entry ? EqualStrings(AtomEntryToKey(entry), lookup) : false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,18 +168,22 @@ js_DoubleToUint32(jsdouble d)
|
|||||||
JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACCSET_NONE)
|
JS_DEFINE_CALLINFO_1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, ACCSET_NONE)
|
||||||
|
|
||||||
jsdouble FASTCALL
|
jsdouble FASTCALL
|
||||||
js_StringToNumber(JSContext* cx, JSString* str)
|
js_StringToNumber(JSContext* cx, JSString* str, JSBool *ok)
|
||||||
{
|
{
|
||||||
return StringToNumberType<jsdouble>(cx, str);
|
double out = 0; /* silence warnings. */
|
||||||
|
*ok = StringToNumberType<jsdouble>(cx, str, &out);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
JS_DEFINE_CALLINFO_2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, ACCSET_NONE)
|
JS_DEFINE_CALLINFO_3(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, BOOLPTR, 1, ACCSET_NONE)
|
||||||
|
|
||||||
int32 FASTCALL
|
int32 FASTCALL
|
||||||
js_StringToInt32(JSContext* cx, JSString* str)
|
js_StringToInt32(JSContext* cx, JSString* str, JSBool *ok)
|
||||||
{
|
{
|
||||||
return StringToNumberType<int32>(cx, str);
|
int32 out = 0; /* silence warnings. */
|
||||||
|
*ok = StringToNumberType<int32>(cx, str, &out);
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACCSET_NONE)
|
JS_DEFINE_CALLINFO_3(extern, INT32, js_StringToInt32, CONTEXT, STRING, BOOLPTR, 1, ACCSET_NONE)
|
||||||
|
|
||||||
/* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */
|
/* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */
|
||||||
static inline JSBool
|
static inline JSBool
|
||||||
|
@ -547,7 +547,7 @@ struct ClosureVarInfo;
|
|||||||
#define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
|
#define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
|
||||||
|
|
||||||
jsdouble FASTCALL
|
jsdouble FASTCALL
|
||||||
js_StringToNumber(JSContext* cx, JSString* str);
|
js_StringToNumber(JSContext* cx, JSString* str, JSBool *ok);
|
||||||
|
|
||||||
/* Extern version of SetBuiltinError. */
|
/* Extern version of SetBuiltinError. */
|
||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
@ -623,9 +623,9 @@ JS_DECLARE_CALLINFO(js_CloneRegExpObject)
|
|||||||
|
|
||||||
/* Defined in jsstr.cpp. */
|
/* Defined in jsstr.cpp. */
|
||||||
JS_DECLARE_CALLINFO(js_String_tn)
|
JS_DECLARE_CALLINFO(js_String_tn)
|
||||||
JS_DECLARE_CALLINFO(js_CompareStrings)
|
JS_DECLARE_CALLINFO(js_CompareStringsOnTrace)
|
||||||
JS_DECLARE_CALLINFO(js_ConcatStrings)
|
JS_DECLARE_CALLINFO(js_ConcatStrings)
|
||||||
JS_DECLARE_CALLINFO(js_EqualStrings)
|
JS_DECLARE_CALLINFO(js_EqualStringsOnTrace)
|
||||||
JS_DECLARE_CALLINFO(js_Flatten)
|
JS_DECLARE_CALLINFO(js_Flatten)
|
||||||
|
|
||||||
/* Defined in jstypedarray.cpp. */
|
/* Defined in jstypedarray.cpp. */
|
||||||
|
@ -350,9 +350,10 @@ JS_STATIC_ASSERT(JSString::MAX_LENGTH < UINT32_MAX);
|
|||||||
bool
|
bool
|
||||||
JSStructuredCloneWriter::writeString(uint32_t tag, JSString *str)
|
JSStructuredCloneWriter::writeString(uint32_t tag, JSString *str)
|
||||||
{
|
{
|
||||||
const jschar *chars;
|
size_t length = str->length();
|
||||||
size_t length;
|
const jschar *chars = str->getChars(context());
|
||||||
str->getCharsAndLength(chars, length);
|
if (!chars)
|
||||||
|
return false;
|
||||||
return out.writePair(tag, uint32_t(length)) && out.writeChars(chars, length);
|
return out.writePair(tag, uint32_t(length)) && out.writeChars(chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,9 +751,10 @@ JSStructuredCloneReader::startRead(Value *vp)
|
|||||||
JSString *str = readString(nchars);
|
JSString *str = readString(nchars);
|
||||||
if (!str)
|
if (!str)
|
||||||
return false;
|
return false;
|
||||||
const jschar *chars;
|
size_t length = str->length();
|
||||||
size_t length;
|
const jschar *chars = str->getChars(context());
|
||||||
str->getCharsAndLength(chars, length);
|
if (!chars)
|
||||||
|
return false;
|
||||||
JSObject *obj = RegExp::createObjectNoStatics(context(), chars, length, data);
|
JSObject *obj = RegExp::createObjectNoStatics(context(), chars, length, data);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1369,7 +1369,7 @@ struct JSRuntime {
|
|||||||
js::Value negativeInfinityValue;
|
js::Value negativeInfinityValue;
|
||||||
js::Value positiveInfinityValue;
|
js::Value positiveInfinityValue;
|
||||||
|
|
||||||
JSString *emptyString;
|
JSFlatString *emptyString;
|
||||||
|
|
||||||
/* List of active contexts sharing this runtime; protected by gcLock. */
|
/* List of active contexts sharing this runtime; protected by gcLock. */
|
||||||
JSCList contextList;
|
JSCList contextList;
|
||||||
@ -2386,10 +2386,10 @@ struct JSContext
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
volatile DollarPath *dollarPath;
|
volatile DollarPath *dollarPath;
|
||||||
volatile JSSubString *sub;
|
volatile JSSubString *sub;
|
||||||
volatile jschar *blackBox;
|
volatile const jschar *blackBox;
|
||||||
volatile jschar **repstrChars;
|
volatile const jschar **repstrChars;
|
||||||
volatile jschar **repstrDollar;
|
volatile const jschar **repstrDollar;
|
||||||
volatile jschar **repstrDollarEnd;
|
volatile const jschar **repstrDollarEnd;
|
||||||
volatile size_t *peekLen;
|
volatile size_t *peekLen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -204,7 +204,10 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
|||||||
if (vp->isString()) {
|
if (vp->isString()) {
|
||||||
Value orig = *vp;
|
Value orig = *vp;
|
||||||
JSString *str = vp->toString();
|
JSString *str = vp->toString();
|
||||||
JSString *wrapped = js_NewStringCopyN(cx, str->chars(), str->length());
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return false;
|
||||||
|
JSString *wrapped = js_NewStringCopyN(cx, chars, str->length());
|
||||||
if (!wrapped)
|
if (!wrapped)
|
||||||
return false;
|
return false;
|
||||||
vp->setString(wrapped);
|
vp->setString(wrapped);
|
||||||
|
@ -750,7 +750,7 @@ ndigits(size_t n, size_t *result, const jschar *s, size_t* i, size_t limit)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
date_parseISOString(JSString *str, jsdouble *result, JSContext *cx)
|
date_parseISOString(JSLinearString *str, jsdouble *result, JSContext *cx)
|
||||||
{
|
{
|
||||||
jsdouble msec;
|
jsdouble msec;
|
||||||
|
|
||||||
@ -792,7 +792,8 @@ date_parseISOString(JSString *str, jsdouble *result, JSContext *cx)
|
|||||||
if (!ndigits(n, &field, s, &i, limit)) { goto syntax; } \
|
if (!ndigits(n, &field, s, &i, limit)) { goto syntax; } \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
str->getCharsAndLength(s, limit);
|
s = str->chars();
|
||||||
|
limit = str->length();
|
||||||
|
|
||||||
if (PEEK('+') || PEEK('-')) {
|
if (PEEK('+') || PEEK('-')) {
|
||||||
if (PEEK('-'))
|
if (PEEK('-'))
|
||||||
@ -883,7 +884,7 @@ date_parseISOString(JSString *str, jsdouble *result, JSContext *cx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
date_parseString(JSString *str, jsdouble *result, JSContext *cx)
|
date_parseString(JSLinearString *str, jsdouble *result, JSContext *cx)
|
||||||
{
|
{
|
||||||
jsdouble msec;
|
jsdouble msec;
|
||||||
|
|
||||||
@ -907,7 +908,8 @@ date_parseString(JSString *str, jsdouble *result, JSContext *cx)
|
|||||||
if (date_parseISOString(str, result, cx))
|
if (date_parseISOString(str, result, cx))
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
|
|
||||||
str->getCharsAndLength(s, limit);
|
s = str->chars();
|
||||||
|
limit = str->length();
|
||||||
if (limit == 0)
|
if (limit == 0)
|
||||||
goto syntax;
|
goto syntax;
|
||||||
while (i < limit) {
|
while (i < limit) {
|
||||||
@ -1167,7 +1169,11 @@ date_parse(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
vp[2].setString(str);
|
vp[2].setString(str);
|
||||||
if (!date_parseString(str, &result, cx)) {
|
JSLinearString *linearStr = str->ensureLinear(cx);
|
||||||
|
if (!linearStr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!date_parseString(linearStr, &result, cx)) {
|
||||||
vp->setDouble(js_NaN);
|
vp->setDouble(js_NaN);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2377,8 +2383,6 @@ date_toString(JSContext *cx, uintN argc, Value *vp)
|
|||||||
static JSBool
|
static JSBool
|
||||||
date_valueOf(JSContext *cx, uintN argc, Value *vp)
|
date_valueOf(JSContext *cx, uintN argc, Value *vp)
|
||||||
{
|
{
|
||||||
JSString *str, *number_str;
|
|
||||||
|
|
||||||
/* It is an error to call date_valueOf on a non-date object, but we don't
|
/* It is an error to call date_valueOf on a non-date object, but we don't
|
||||||
* need to check for that explicitly here because every path calls
|
* need to check for that explicitly here because every path calls
|
||||||
* GetUTCTime, which does the check.
|
* GetUTCTime, which does the check.
|
||||||
@ -2389,11 +2393,14 @@ date_valueOf(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return date_getTime(cx, argc, vp);
|
return date_getTime(cx, argc, vp);
|
||||||
|
|
||||||
/* Convert to number only if the hint was given, otherwise favor string. */
|
/* Convert to number only if the hint was given, otherwise favor string. */
|
||||||
str = js_ValueToString(cx, vp[2]);
|
JSString *str = js_ValueToString(cx, vp[2]);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
|
JSLinearString *linear_str = str->ensureLinear(cx);
|
||||||
if (js_EqualStrings(str, number_str))
|
if (!linear_str)
|
||||||
|
return JS_FALSE;
|
||||||
|
JSAtom *number_str = cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER];
|
||||||
|
if (EqualStrings(linear_str, number_str))
|
||||||
return date_getTime(cx, argc, vp);
|
return date_getTime(cx, argc, vp);
|
||||||
return date_toString(cx, argc, vp);
|
return date_toString(cx, argc, vp);
|
||||||
}
|
}
|
||||||
@ -2487,8 +2494,11 @@ js_Date(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (!str)
|
if (!str)
|
||||||
return false;
|
return false;
|
||||||
argv[0].setString(str);
|
argv[0].setString(str);
|
||||||
|
JSLinearString *linearStr = str->ensureLinear(cx);
|
||||||
|
if (!linearStr)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!date_parseString(str, &d, cx))
|
if (!date_parseString(linearStr, &d, cx))
|
||||||
d = js_NaN;
|
d = js_NaN;
|
||||||
else
|
else
|
||||||
d = TIMECLIP(d);
|
d = TIMECLIP(d);
|
||||||
|
@ -612,10 +612,11 @@ StackTraceToString(JSContext *cx, JSExnPrivate *priv)
|
|||||||
#define APPEND_STRING_TO_STACK(str) \
|
#define APPEND_STRING_TO_STACK(str) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
JSString *str_ = str; \
|
JSString *str_ = str; \
|
||||||
const jschar *chars_; \
|
size_t length_ = str_->length(); \
|
||||||
size_t length_; \
|
const jschar *chars_ = str_->getChars(cx); \
|
||||||
|
if (!chars_) \
|
||||||
|
goto bad; \
|
||||||
\
|
\
|
||||||
str_->getCharsAndLength(chars_, length_); \
|
|
||||||
if (length_ > stackmax - stacklen) { \
|
if (length_ > stackmax - stacklen) { \
|
||||||
void *ptr_; \
|
void *ptr_; \
|
||||||
if (stackmax >= STACK_LENGTH_LIMIT || \
|
if (stackmax >= STACK_LENGTH_LIMIT || \
|
||||||
@ -813,11 +814,17 @@ exn_toString(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
if (name_length) {
|
if (name_length) {
|
||||||
js_strncpy(cp, name->chars(), name_length);
|
const jschar *name_chars = name->getChars(cx);
|
||||||
|
if (!name_chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
js_strncpy(cp, name_chars, name_length);
|
||||||
cp += name_length;
|
cp += name_length;
|
||||||
*cp++ = ':'; *cp++ = ' ';
|
*cp++ = ':'; *cp++ = ' ';
|
||||||
}
|
}
|
||||||
js_strncpy(cp, message->chars(), message_length);
|
const jschar *message_chars = message->getChars(cx);
|
||||||
|
if (!message_chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
js_strncpy(cp, message_chars, message_length);
|
||||||
cp += message_length;
|
cp += message_length;
|
||||||
*cp = 0;
|
*cp = 0;
|
||||||
|
|
||||||
@ -917,18 +924,27 @@ exn_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
*cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
|
*cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
|
||||||
js_strncpy(cp, name->chars(), name_length);
|
const jschar *name_chars = name->getChars(cx);
|
||||||
|
if (!name_chars)
|
||||||
|
return false;
|
||||||
|
js_strncpy(cp, name_chars, name_length);
|
||||||
cp += name_length;
|
cp += name_length;
|
||||||
*cp++ = '(';
|
*cp++ = '(';
|
||||||
|
const jschar *message_chars = message->getChars(cx);
|
||||||
|
if (!message_chars)
|
||||||
|
return false;
|
||||||
if (message_length != 0) {
|
if (message_length != 0) {
|
||||||
js_strncpy(cp, message->chars(), message_length);
|
js_strncpy(cp, message_chars, message_length);
|
||||||
cp += message_length;
|
cp += message_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename_length != 0) {
|
if (filename_length != 0) {
|
||||||
/* append filename as ``, {filename}'' */
|
/* append filename as ``, {filename}'' */
|
||||||
*cp++ = ','; *cp++ = ' ';
|
*cp++ = ','; *cp++ = ' ';
|
||||||
js_strncpy(cp, filename->chars(), filename_length);
|
const jschar *filename_chars = filename->getChars(cx);
|
||||||
|
if (!filename_chars)
|
||||||
|
return false;
|
||||||
|
js_strncpy(cp, filename_chars, filename_length);
|
||||||
cp += filename_length;
|
cp += filename_length;
|
||||||
} else {
|
} else {
|
||||||
if (lineno_as_str) {
|
if (lineno_as_str) {
|
||||||
@ -942,7 +958,10 @@ exn_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (lineno_as_str) {
|
if (lineno_as_str) {
|
||||||
/* append lineno as ``, {lineno_as_str}'' */
|
/* append lineno as ``, {lineno_as_str}'' */
|
||||||
*cp++ = ','; *cp++ = ' ';
|
*cp++ = ','; *cp++ = ' ';
|
||||||
js_strncpy(cp, lineno_as_str->chars(), lineno_length);
|
const jschar *lineno_chars = lineno_as_str->getChars(cx);
|
||||||
|
if (!lineno_chars)
|
||||||
|
return false;
|
||||||
|
js_strncpy(cp, lineno_chars, lineno_length);
|
||||||
cp += lineno_length;
|
cp += lineno_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2603,7 +2603,12 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
|||||||
for (uintN i = 0; i < n; i++) {
|
for (uintN i = 0; i < n; i++) {
|
||||||
JSString *arg = argv[i].toString();
|
JSString *arg = argv[i].toString();
|
||||||
size_t arg_length = arg->length();
|
size_t arg_length = arg->length();
|
||||||
(void) js_strncpy(cp, arg->chars(), arg_length);
|
const jschar *arg_chars = arg->getChars(cx);
|
||||||
|
if (!arg_chars) {
|
||||||
|
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
(void) js_strncpy(cp, arg_chars, arg_length);
|
||||||
cp += arg_length;
|
cp += arg_length;
|
||||||
|
|
||||||
/* Add separating comma or terminating 0. */
|
/* Add separating comma or terminating 0. */
|
||||||
@ -2690,8 +2695,11 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
|||||||
str = cx->runtime->emptyString;
|
str = cx->runtime->emptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Compiler::compileFunctionBody(cx, fun, principals,
|
size_t length = str->length();
|
||||||
str->chars(), str->length(),
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
return Compiler::compileFunctionBody(cx, fun, principals, chars, length,
|
||||||
filename, lineno);
|
filename, lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,7 +1767,7 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str)
|
|||||||
JS_ASSERT(IsFinalizableStringKind(thingKind));
|
JS_ASSERT(IsFinalizableStringKind(thingKind));
|
||||||
|
|
||||||
/* A stillborn string has null chars, so is not valid. */
|
/* A stillborn string has null chars, so is not valid. */
|
||||||
jschar *chars = str->flatChars();
|
jschar *chars = const_cast<jschar *>(str->flatChars());
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return;
|
return;
|
||||||
if (thingKind == FINALIZE_STRING) {
|
if (thingKind == FINALIZE_STRING) {
|
||||||
|
@ -362,9 +362,13 @@ GCMarker::dumpConservativeRoots()
|
|||||||
}
|
}
|
||||||
case JSTRACE_STRING: {
|
case JSTRACE_STRING: {
|
||||||
JSString *str = (JSString *) i->thing;
|
JSString *str = (JSString *) i->thing;
|
||||||
char buf[50];
|
if (str->isLinear()) {
|
||||||
PutEscapedString(buf, sizeof buf, str, '"');
|
char buf[50];
|
||||||
fprintf(fp, "string %s", buf);
|
PutEscapedString(buf, sizeof buf, str->assertIsLinear(), '"');
|
||||||
|
fprintf(fp, "string %s", buf);
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "rope: length %d", (int)str->length());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
# if JS_HAS_XML_SUPPORT
|
# if JS_HAS_XML_SUPPORT
|
||||||
|
@ -1130,40 +1130,44 @@ HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE bool
|
|
||||||
EqualObjects(JSContext *cx, JSObject *lobj, JSObject *robj)
|
|
||||||
{
|
|
||||||
return lobj == robj;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref)
|
StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref, JSBool *equal)
|
||||||
{
|
{
|
||||||
Value lval = lref, rval = rref;
|
Value lval = lref, rval = rref;
|
||||||
if (SameType(lval, rval)) {
|
if (SameType(lval, rval)) {
|
||||||
if (lval.isString())
|
if (lval.isString())
|
||||||
return js_EqualStrings(lval.toString(), rval.toString());
|
return EqualStrings(cx, lval.toString(), rval.toString(), equal);
|
||||||
if (lval.isDouble())
|
if (lval.isDouble()) {
|
||||||
return JSDOUBLE_COMPARE(lval.toDouble(), ==, rval.toDouble(), JS_FALSE);
|
*equal = JSDOUBLE_COMPARE(lval.toDouble(), ==, rval.toDouble(), JS_FALSE);
|
||||||
if (lval.isObject())
|
return true;
|
||||||
return EqualObjects(cx, &lval.toObject(), &rval.toObject());
|
}
|
||||||
if (lval.isUndefined())
|
if (lval.isObject()) {
|
||||||
return true;
|
*equal = &lval.toObject() == &rval.toObject();
|
||||||
return lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
|
return true;
|
||||||
|
}
|
||||||
|
if (lval.isUndefined()) {
|
||||||
|
*equal = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*equal = lval.payloadAsRawUint32() == rval.payloadAsRawUint32();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lval.isDouble() && rval.isInt32()) {
|
if (lval.isDouble() && rval.isInt32()) {
|
||||||
double ld = lval.toDouble();
|
double ld = lval.toDouble();
|
||||||
double rd = rval.toInt32();
|
double rd = rval.toInt32();
|
||||||
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
*equal = JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (lval.isInt32() && rval.isDouble()) {
|
if (lval.isInt32() && rval.isDouble()) {
|
||||||
double ld = lval.toInt32();
|
double ld = lval.toInt32();
|
||||||
double rd = rval.toDouble();
|
double rd = rval.toDouble();
|
||||||
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
*equal = JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
*equal = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@ -1179,15 +1183,21 @@ IsNaN(const Value &v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SameValue(const Value &v1, const Value &v2, JSContext *cx)
|
SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same)
|
||||||
{
|
{
|
||||||
if (IsNegativeZero(v1))
|
if (IsNegativeZero(v1)) {
|
||||||
return IsNegativeZero(v2);
|
*same = IsNegativeZero(v2);
|
||||||
if (IsNegativeZero(v2))
|
|
||||||
return false;
|
|
||||||
if (IsNaN(v1) && IsNaN(v2))
|
|
||||||
return true;
|
return true;
|
||||||
return StrictlyEqual(cx, v1, v2);
|
}
|
||||||
|
if (IsNegativeZero(v2)) {
|
||||||
|
*same = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (IsNaN(v1) && IsNaN(v2)) {
|
||||||
|
*same = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return StrictlyEqual(cx, v1, v2, same);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSType
|
JSType
|
||||||
@ -1516,7 +1526,6 @@ js_LogOpcode(JSContext *cx)
|
|||||||
JSStackFrame *fp;
|
JSStackFrame *fp;
|
||||||
JSFrameRegs *regs;
|
JSFrameRegs *regs;
|
||||||
intN ndefs, n, nuses;
|
intN ndefs, n, nuses;
|
||||||
JSString *str;
|
|
||||||
JSOp op;
|
JSOp op;
|
||||||
|
|
||||||
logfp = (FILE *) cx->logfp;
|
logfp = (FILE *) cx->logfp;
|
||||||
@ -1562,12 +1571,13 @@ js_LogOpcode(JSContext *cx)
|
|||||||
*/
|
*/
|
||||||
fputs("<call>", logfp);
|
fputs("<call>", logfp);
|
||||||
} else {
|
} else {
|
||||||
str = js_ValueToString(cx, *siter);
|
JSString *str = js_ValueToString(cx, *siter);
|
||||||
if (!str) {
|
JSLinearString *linearStr = str ? str->ensureLinear(cx) : NULL;
|
||||||
|
if (!linearStr) {
|
||||||
fputs("<null>", logfp);
|
fputs("<null>", logfp);
|
||||||
} else {
|
|
||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
FileEscapedString(logfp, str, 0);
|
} else {
|
||||||
|
FileEscapedString(logfp, linearStr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fputc(' ', logfp);
|
fputc(' ', logfp);
|
||||||
@ -3389,7 +3399,10 @@ END_CASE(JSOP_BITAND)
|
|||||||
if (SameType(lval, rval)) { \
|
if (SameType(lval, rval)) { \
|
||||||
if (lval.isString()) { \
|
if (lval.isString()) { \
|
||||||
JSString *l = lval.toString(), *r = rval.toString(); \
|
JSString *l = lval.toString(), *r = rval.toString(); \
|
||||||
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
JSBool equal; \
|
||||||
|
if (!EqualStrings(cx, l, r, &equal)) \
|
||||||
|
goto error; \
|
||||||
|
cond = equal OP JS_TRUE; \
|
||||||
} else if (lval.isDouble()) { \
|
} else if (lval.isDouble()) { \
|
||||||
double l = lval.toDouble(), r = rval.toDouble(); \
|
double l = lval.toDouble(), r = rval.toDouble(); \
|
||||||
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
||||||
@ -3418,7 +3431,10 @@ END_CASE(JSOP_BITAND)
|
|||||||
DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
|
DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
|
||||||
if (lval.isString() && rval.isString()) { \
|
if (lval.isString() && rval.isString()) { \
|
||||||
JSString *l = lval.toString(), *r = rval.toString(); \
|
JSString *l = lval.toString(), *r = rval.toString(); \
|
||||||
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
JSBool equal; \
|
||||||
|
if (!EqualStrings(cx, l, r, &equal)) \
|
||||||
|
goto error; \
|
||||||
|
cond = equal OP JS_TRUE; \
|
||||||
} else { \
|
} else { \
|
||||||
double l, r; \
|
double l, r; \
|
||||||
if (!ValueToNumber(cx, lval, &l) || \
|
if (!ValueToNumber(cx, lval, &l) || \
|
||||||
@ -3450,7 +3466,10 @@ END_CASE(JSOP_NE)
|
|||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
const Value &rref = regs.sp[-1]; \
|
const Value &rref = regs.sp[-1]; \
|
||||||
const Value &lref = regs.sp[-2]; \
|
const Value &lref = regs.sp[-2]; \
|
||||||
COND = StrictlyEqual(cx, lref, rref) OP true; \
|
JSBool equal; \
|
||||||
|
if (!StrictlyEqual(cx, lref, rref, &equal)) \
|
||||||
|
goto error; \
|
||||||
|
COND = equal OP true; \
|
||||||
regs.sp--; \
|
regs.sp--; \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
@ -3511,7 +3530,10 @@ END_CASE(JSOP_CASEX)
|
|||||||
DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
|
DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
|
||||||
if (lval.isString() && rval.isString()) { \
|
if (lval.isString() && rval.isString()) { \
|
||||||
JSString *l = lval.toString(), *r = rval.toString(); \
|
JSString *l = lval.toString(), *r = rval.toString(); \
|
||||||
cond = js_CompareStrings(l, r) OP 0; \
|
int32 result; \
|
||||||
|
if (!CompareStrings(cx, l, r, &result)) \
|
||||||
|
goto error; \
|
||||||
|
cond = result OP 0; \
|
||||||
} else { \
|
} else { \
|
||||||
double l, r; \
|
double l, r; \
|
||||||
if (!ValueToNumber(cx, lval, &l) || \
|
if (!ValueToNumber(cx, lval, &l) || \
|
||||||
@ -5094,12 +5116,14 @@ BEGIN_CASE(JSOP_LOOKUPSWITCH)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lval.isString()) {
|
if (lval.isString()) {
|
||||||
JSString *str = lval.toString();
|
JSLinearString *str = lval.toString()->ensureLinear(cx);
|
||||||
JSString *str2;
|
if (!str)
|
||||||
|
goto error;
|
||||||
|
JSLinearString *str2;
|
||||||
SEARCH_PAIRS(
|
SEARCH_PAIRS(
|
||||||
match = (rval.isString() &&
|
match = (rval.isString() &&
|
||||||
((str2 = rval.toString()) == str ||
|
((str2 = rval.toString()->assertIsLinear()) == str ||
|
||||||
js_EqualStrings(str2, str)));
|
EqualStrings(str2, str)));
|
||||||
)
|
)
|
||||||
} else if (lval.isNumber()) {
|
} else if (lval.isNumber()) {
|
||||||
double ldbl = lval.toNumber();
|
double ldbl = lval.toNumber();
|
||||||
|
@ -1030,11 +1030,11 @@ CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
|
|||||||
JSObject **objp, JSProperty **propp);
|
JSObject **objp, JSProperty **propp);
|
||||||
|
|
||||||
extern bool
|
extern bool
|
||||||
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval);
|
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *equal);
|
||||||
|
|
||||||
/* === except that NaN is the same as NaN and -0 is not the same as +0. */
|
/* === except that NaN is the same as NaN and -0 is not the same as +0. */
|
||||||
extern bool
|
extern bool
|
||||||
SameValue(const Value &v1, const Value &v2, JSContext *cx);
|
SameValue(JSContext *cx, const Value &v1, const Value &v2, JSBool *same);
|
||||||
|
|
||||||
extern JSType
|
extern JSType
|
||||||
TypeOfValue(JSContext *cx, const Value &v);
|
TypeOfValue(JSContext *cx, const Value &v);
|
||||||
|
@ -315,7 +315,10 @@ num_parseFloat(JSContext *cx, uintN argc, Value *vp)
|
|||||||
str = js_ValueToString(cx, vp[2]);
|
str = js_ValueToString(cx, vp[2]);
|
||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
str->getCharsAndEnd(bp, end);
|
bp = str->getChars(cx);
|
||||||
|
if (!bp)
|
||||||
|
return JS_FALSE;
|
||||||
|
end = bp + str->length();
|
||||||
if (!js_strtod(cx, bp, end, &ep, &d))
|
if (!js_strtod(cx, bp, end, &ep, &d))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
if (ep == bp) {
|
if (ep == bp) {
|
||||||
@ -330,12 +333,15 @@ num_parseFloat(JSContext *cx, uintN argc, Value *vp)
|
|||||||
static jsdouble FASTCALL
|
static jsdouble FASTCALL
|
||||||
ParseFloat(JSContext* cx, JSString* str)
|
ParseFloat(JSContext* cx, JSString* str)
|
||||||
{
|
{
|
||||||
const jschar* bp;
|
const jschar *bp = str->getChars(cx);
|
||||||
const jschar* end;
|
if (!bp) {
|
||||||
const jschar* ep;
|
SetBuiltinError(cx);
|
||||||
jsdouble d;
|
return js_NaN;
|
||||||
|
}
|
||||||
|
const jschar *end = bp + str->length();
|
||||||
|
|
||||||
str->getCharsAndEnd(bp, end);
|
const jschar *ep;
|
||||||
|
double d;
|
||||||
if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
|
if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
|
||||||
return js_NaN;
|
return js_NaN;
|
||||||
return d;
|
return d;
|
||||||
@ -451,8 +457,10 @@ num_parseInt(JSContext *cx, uintN argc, Value *vp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Steps 2-5, 9-14. */
|
/* Steps 2-5, 9-14. */
|
||||||
const jschar *ws, *end;
|
const jschar *ws = inputString->getChars(cx);
|
||||||
inputString->getCharsAndEnd(ws, end);
|
if (!ws)
|
||||||
|
return false;
|
||||||
|
const jschar *end = ws + inputString->length();
|
||||||
|
|
||||||
jsdouble number;
|
jsdouble number;
|
||||||
if (!ParseIntStringHelper(cx, ws, end, radix, stripPrefix, &number))
|
if (!ParseIntStringHelper(cx, ws, end, radix, stripPrefix, &number))
|
||||||
@ -467,8 +475,12 @@ num_parseInt(JSContext *cx, uintN argc, Value *vp)
|
|||||||
static jsdouble FASTCALL
|
static jsdouble FASTCALL
|
||||||
ParseInt(JSContext* cx, JSString* str)
|
ParseInt(JSContext* cx, JSString* str)
|
||||||
{
|
{
|
||||||
const jschar *start, *end;
|
const jschar *start = str->getChars(cx);
|
||||||
str->getCharsAndEnd(start, end);
|
if (!start) {
|
||||||
|
SetBuiltinError(cx);
|
||||||
|
return js_NaN;
|
||||||
|
}
|
||||||
|
const jschar *end = start + str->length();
|
||||||
|
|
||||||
jsdouble d;
|
jsdouble d;
|
||||||
if (!ParseIntStringHelper(cx, start, end, 0, true, &d)) {
|
if (!ParseIntStringHelper(cx, start, end, 0, true, &d)) {
|
||||||
@ -499,7 +511,7 @@ JS_DEFINE_TRCINFO_2(num_parseInt,
|
|||||||
(1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, nanojit::ACCSET_NONE)))
|
(1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, nanojit::ACCSET_NONE)))
|
||||||
|
|
||||||
JS_DEFINE_TRCINFO_1(num_parseFloat,
|
JS_DEFINE_TRCINFO_1(num_parseFloat,
|
||||||
(2, (static, DOUBLE, ParseFloat, CONTEXT, STRING, 1, nanojit::ACCSET_NONE)))
|
(2, (static, DOUBLE_FAIL, ParseFloat, CONTEXT, STRING, 1, nanojit::ACCSET_NONE)))
|
||||||
|
|
||||||
#endif /* JS_TRACER */
|
#endif /* JS_TRACER */
|
||||||
|
|
||||||
@ -1184,6 +1196,14 @@ js_NumberToString(JSContext *cx, jsdouble d)
|
|||||||
return js_NumberToStringWithBase(cx, d, 10);
|
return js_NumberToStringWithBase(cx, d, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSFlatString *
|
||||||
|
js::NumberToString(JSContext *cx, jsdouble d)
|
||||||
|
{
|
||||||
|
if (JSString *str = js_NumberToStringWithBase(cx, d, 10))
|
||||||
|
return str->assertIsFlat();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
JSBool JS_FASTCALL
|
JSBool JS_FASTCALL
|
||||||
js_NumberValueToCharBuffer(JSContext *cx, const Value &v, JSCharBuffer &cb)
|
js_NumberValueToCharBuffer(JSContext *cx, const Value &v, JSCharBuffer &cb)
|
||||||
{
|
{
|
||||||
@ -1232,13 +1252,8 @@ ValueToNumberSlow(JSContext *cx, Value v, double *out)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
skip_int_double:
|
skip_int_double:
|
||||||
if (v.isString()) {
|
if (v.isString())
|
||||||
jsdouble d = StringToNumberType<jsdouble>(cx, v.toString());
|
return StringToNumberType<jsdouble>(cx, v.toString(), out);
|
||||||
if (JSDOUBLE_IS_NaN(d))
|
|
||||||
break;
|
|
||||||
*out = d;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (v.isBoolean()) {
|
if (v.isBoolean()) {
|
||||||
if (v.toBoolean()) {
|
if (v.toBoolean()) {
|
||||||
*out = 1.0;
|
*out = 1.0;
|
||||||
|
@ -206,6 +206,10 @@ js_NumberValueToCharBuffer(JSContext *cx, const js::Value &v, JSCharBuffer &cb);
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
/* Same as js_NumberToString, different signature. */
|
||||||
|
extern JSFlatString *
|
||||||
|
NumberToString(JSContext *cx, jsdouble d);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Usually a small amount of static storage is enough, but sometimes we need
|
* Usually a small amount of static storage is enough, but sometimes we need
|
||||||
* to dynamically allocate much more. This struct encapsulates that.
|
* to dynamically allocate much more. This struct encapsulates that.
|
||||||
@ -643,35 +647,44 @@ template<> struct NumberTraits<jsdouble> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static JS_ALWAYS_INLINE T
|
static JS_ALWAYS_INLINE bool
|
||||||
StringToNumberType(JSContext *cx, JSString *str)
|
StringToNumberType(JSContext *cx, JSString *str, T *result)
|
||||||
{
|
{
|
||||||
if (str->length() == 1) {
|
size_t length = str->length();
|
||||||
jschar c = str->chars()[0];
|
const jschar *chars = str->getChars(NULL);
|
||||||
if ('0' <= c && c <= '9')
|
if (!chars)
|
||||||
return NumberTraits<T>::toSelfType(T(c - '0'));
|
return false;
|
||||||
if (JS_ISSPACE(c))
|
|
||||||
return NumberTraits<T>::toSelfType(T(0));
|
if (length == 1) {
|
||||||
return NumberTraits<T>::NaN();
|
jschar c = chars[0];
|
||||||
|
if ('0' <= c && c <= '9') {
|
||||||
|
*result = NumberTraits<T>::toSelfType(T(c - '0'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (JS_ISSPACE(c)) {
|
||||||
|
*result = NumberTraits<T>::toSelfType(T(0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*result = NumberTraits<T>::NaN();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const jschar* bp;
|
const jschar *bp = chars;
|
||||||
const jschar* end;
|
const jschar *end = chars + length;
|
||||||
const jschar* ep;
|
|
||||||
jsdouble d;
|
|
||||||
|
|
||||||
str->getCharsAndEnd(bp, end);
|
|
||||||
bp = js_SkipWhiteSpace(bp, end);
|
bp = js_SkipWhiteSpace(bp, end);
|
||||||
|
|
||||||
/* ECMA doesn't allow signed hex numbers (bug 273467). */
|
/* ECMA doesn't allow signed hex numbers (bug 273467). */
|
||||||
if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) {
|
if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) {
|
||||||
/* Looks like a hex number. */
|
/* Looks like a hex number. */
|
||||||
const jschar *endptr;
|
const jschar *endptr;
|
||||||
|
double d;
|
||||||
if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) ||
|
if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) ||
|
||||||
js_SkipWhiteSpace(endptr, end) != end) {
|
js_SkipWhiteSpace(endptr, end) != end) {
|
||||||
return NumberTraits<T>::NaN();
|
*result = NumberTraits<T>::NaN();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return NumberTraits<T>::toSelfType(d);
|
*result = NumberTraits<T>::toSelfType(d);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -681,12 +694,14 @@ StringToNumberType(JSContext *cx, JSString *str)
|
|||||||
* that have made it here (which can only be negative ones) will
|
* that have made it here (which can only be negative ones) will
|
||||||
* be treated as 0 without consuming the 'x' by js_strtod.
|
* be treated as 0 without consuming the 'x' by js_strtod.
|
||||||
*/
|
*/
|
||||||
if (!js_strtod(cx, bp, end, &ep, &d) ||
|
const jschar *ep;
|
||||||
js_SkipWhiteSpace(ep, end) != end) {
|
double d;
|
||||||
return NumberTraits<T>::NaN();
|
if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end) {
|
||||||
|
*result = NumberTraits<T>::NaN();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
*result = NumberTraits<T>::toSelfType(d);
|
||||||
return NumberTraits<T>::toSelfType(d);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
143
js/src/jsobj.cpp
143
js/src/jsobj.cpp
@ -484,7 +484,8 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
JSProperty *prop;
|
JSProperty *prop;
|
||||||
Value *val;
|
Value *val;
|
||||||
JSString *gsop[2];
|
JSString *gsop[2];
|
||||||
JSString *idstr, *valstr, *str;
|
JSString *valstr, *str;
|
||||||
|
JSLinearString *idstr;
|
||||||
|
|
||||||
JS_CHECK_RECURSION(cx, return JS_FALSE);
|
JS_CHECK_RECURSION(cx, return JS_FALSE);
|
||||||
|
|
||||||
@ -570,8 +571,8 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
* Convert id to a value and then to a string. Decide early whether we
|
* Convert id to a value and then to a string. Decide early whether we
|
||||||
* prefer get/set or old getter/setter syntax.
|
* prefer get/set or old getter/setter syntax.
|
||||||
*/
|
*/
|
||||||
idstr = js_ValueToString(cx, IdToValue(id));
|
JSString *s = js_ValueToString(cx, IdToValue(id));
|
||||||
if (!idstr) {
|
if (!s || !(idstr = s->ensureLinear(cx))) {
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -609,18 +610,23 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
* If id is a string that's not an identifier, or if it's a negative
|
* If id is a string that's not an identifier, or if it's a negative
|
||||||
* integer, then it must be quoted.
|
* integer, then it must be quoted.
|
||||||
*/
|
*/
|
||||||
bool idIsLexicalIdentifier = !!js_IsIdentifier(idstr);
|
bool idIsLexicalIdentifier = js_IsIdentifier(idstr);
|
||||||
if (JSID_IS_ATOM(id)
|
if (JSID_IS_ATOM(id)
|
||||||
? !idIsLexicalIdentifier
|
? !idIsLexicalIdentifier
|
||||||
: (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0)) {
|
: (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0)) {
|
||||||
idstr = js_QuoteString(cx, idstr, jschar('\''));
|
s = js_QuoteString(cx, idstr, jschar('\''));
|
||||||
if (!idstr) {
|
if (!s || !(idstr = s->ensureLinear(cx))) {
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
vp->setString(idstr); /* local root */
|
vp->setString(idstr); /* local root */
|
||||||
}
|
}
|
||||||
idstr->getCharsAndLength(idstrchars, idstrlength);
|
idstrlength = idstr->length();
|
||||||
|
idstrchars = idstr->getChars(cx);
|
||||||
|
if (!idstrchars) {
|
||||||
|
ok = JS_FALSE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
for (jsint j = 0; j < valcnt; j++) {
|
for (jsint j = 0; j < valcnt; j++) {
|
||||||
/*
|
/*
|
||||||
@ -637,7 +643,12 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
localroot[j].setString(valstr); /* local root */
|
localroot[j].setString(valstr); /* local root */
|
||||||
valstr->getCharsAndLength(vchars, vlength);
|
vchars = valstr->getChars(cx);
|
||||||
|
if (!vchars) {
|
||||||
|
ok = JS_FALSE;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
vlength = valstr->length();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If val[j] is a non-sharp object, and we're not serializing an
|
* If val[j] is a non-sharp object, and we're not serializing an
|
||||||
@ -727,10 +738,8 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
/* Allocate 1 + 1 at end for closing brace and terminating 0. */
|
/* Allocate 1 + 1 at end for closing brace and terminating 0. */
|
||||||
chars = (jschar *) js_realloc((ochars = chars), curlen * sizeof(jschar));
|
chars = (jschar *) js_realloc((ochars = chars), curlen * sizeof(jschar));
|
||||||
if (!chars) {
|
if (!chars) {
|
||||||
/* Save code space on error: let JS_free ignore null vsharp. */
|
chars = ochars;
|
||||||
cx->free(vsharp);
|
goto overflow;
|
||||||
js_free(ochars);
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comma) {
|
if (comma) {
|
||||||
@ -741,8 +750,10 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
|
|||||||
|
|
||||||
if (gsop[j]) {
|
if (gsop[j]) {
|
||||||
gsoplength = gsop[j]->length();
|
gsoplength = gsop[j]->length();
|
||||||
js_strncpy(&chars[nchars], gsop[j]->chars(),
|
const jschar *gsopchars = gsop[j]->getChars(cx);
|
||||||
gsoplength);
|
if (!gsopchars)
|
||||||
|
goto overflow;
|
||||||
|
js_strncpy(&chars[nchars], gsopchars, gsoplength);
|
||||||
nchars += gsoplength;
|
nchars += gsoplength;
|
||||||
chars[nchars++] = ' ';
|
chars[nchars++] = ' ';
|
||||||
}
|
}
|
||||||
@ -987,15 +998,14 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline JSScript **
|
static inline JSScript **
|
||||||
EvalCacheHash(JSContext *cx, JSString *str)
|
EvalCacheHash(JSContext *cx, JSLinearString *str)
|
||||||
{
|
{
|
||||||
const jschar *s;
|
const jschar *s = str->chars();
|
||||||
size_t n;
|
size_t n = str->length();
|
||||||
uint32 h;
|
|
||||||
|
|
||||||
str->getCharsAndLength(s, n);
|
|
||||||
if (n > 100)
|
if (n > 100)
|
||||||
n = 100;
|
n = 100;
|
||||||
|
uint32 h;
|
||||||
for (h = 0; n; s++, n--)
|
for (h = 0; n; s++, n--)
|
||||||
h = JS_ROTATE_LEFT32(h, 4) ^ *s;
|
h = JS_ROTATE_LEFT32(h, 4) ^ *s;
|
||||||
|
|
||||||
@ -1005,7 +1015,7 @@ EvalCacheHash(JSContext *cx, JSString *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSScript *
|
static JS_ALWAYS_INLINE JSScript *
|
||||||
EvalCacheLookup(JSContext *cx, JSString *str, JSStackFrame *caller, uintN staticLevel,
|
EvalCacheLookup(JSContext *cx, JSLinearString *str, JSStackFrame *caller, uintN staticLevel,
|
||||||
JSPrincipals *principals, JSObject *scopeobj, JSScript **bucket)
|
JSPrincipals *principals, JSObject *scopeobj, JSScript **bucket)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1041,9 +1051,9 @@ EvalCacheLookup(JSContext *cx, JSString *str, JSStackFrame *caller, uintN static
|
|||||||
* Get the source string passed for safekeeping in the
|
* Get the source string passed for safekeeping in the
|
||||||
* atom map by the prior eval to Compiler::compileScript.
|
* atom map by the prior eval to Compiler::compileScript.
|
||||||
*/
|
*/
|
||||||
JSString *src = ATOM_TO_STRING(script->atomMap.vector[0]);
|
JSAtom *src = script->atomMap.vector[0];
|
||||||
|
|
||||||
if (src == str || js_EqualStrings(src, str)) {
|
if (src == str || EqualStrings(src, str)) {
|
||||||
/*
|
/*
|
||||||
* Source matches, qualify by comparing scopeobj to the
|
* Source matches, qualify by comparing scopeobj to the
|
||||||
* COMPILE_N_GO-memoized parent of the first literal
|
* COMPILE_N_GO-memoized parent of the first literal
|
||||||
@ -1184,9 +1194,11 @@ EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame
|
|||||||
if (!CheckScopeChainValidity(cx, scopeobj))
|
if (!CheckScopeChainValidity(cx, scopeobj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const jschar *chars;
|
JSLinearString *linearStr = str->ensureLinear(cx);
|
||||||
size_t length;
|
if (!linearStr)
|
||||||
str->getCharsAndLength(chars, length);
|
return false;
|
||||||
|
const jschar *chars = linearStr->chars();
|
||||||
|
size_t length = linearStr->length();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the eval string starts with '(' and ends with ')', it may be JSON.
|
* If the eval string starts with '(' and ends with ')', it may be JSON.
|
||||||
@ -1214,9 +1226,9 @@ EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSScript *script = NULL;
|
JSScript *script = NULL;
|
||||||
JSScript **bucket = EvalCacheHash(cx, str);
|
JSScript **bucket = EvalCacheHash(cx, linearStr);
|
||||||
if (evalType == DIRECT_EVAL && caller->isFunctionFrame())
|
if (evalType == DIRECT_EVAL && caller->isFunctionFrame())
|
||||||
script = EvalCacheLookup(cx, str, caller, staticLevel, principals, scopeobj, bucket);
|
script = EvalCacheLookup(cx, linearStr, caller, staticLevel, principals, scopeobj, bucket);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can't have a callerFrame (down in js::Execute's terms) if we're in
|
* We can't have a callerFrame (down in js::Execute's terms) if we're in
|
||||||
@ -1229,9 +1241,8 @@ EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame
|
|||||||
|
|
||||||
uint32 tcflags = TCF_COMPILE_N_GO | TCF_NEED_MUTABLE_SCRIPT | TCF_COMPILE_FOR_EVAL;
|
uint32 tcflags = TCF_COMPILE_N_GO | TCF_NEED_MUTABLE_SCRIPT | TCF_COMPILE_FOR_EVAL;
|
||||||
script = Compiler::compileScript(cx, scopeobj, callerFrame,
|
script = Compiler::compileScript(cx, scopeobj, callerFrame,
|
||||||
principals, tcflags,
|
principals, tcflags, chars, length,
|
||||||
chars, length,
|
filename, lineno, linearStr, staticLevel);
|
||||||
filename, lineno, str, staticLevel);
|
|
||||||
if (!script)
|
if (!script)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2040,14 +2051,20 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc,
|
|||||||
if (!shape->isAccessorDescriptor())
|
if (!shape->isAccessorDescriptor())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (desc.hasGet &&
|
if (desc.hasGet) {
|
||||||
!SameValue(desc.getterValue(), shape->getterOrUndefined(), cx)) {
|
JSBool same;
|
||||||
break;
|
if (!SameValue(cx, desc.getterValue(), shape->getterOrUndefined(), &same))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!same)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.hasSet &&
|
if (desc.hasSet) {
|
||||||
!SameValue(desc.setterValue(), shape->setterOrUndefined(), cx)) {
|
JSBool same;
|
||||||
break;
|
if (!SameValue(cx, desc.setterValue(), shape->setterOrUndefined(), &same))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!same)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@ -2096,8 +2113,13 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc,
|
|||||||
if (!shape->isDataDescriptor())
|
if (!shape->isDataDescriptor())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (desc.hasValue && !SameValue(desc.value, v, cx))
|
JSBool same;
|
||||||
break;
|
if (desc.hasValue) {
|
||||||
|
if (!SameValue(cx, desc.value, v, &same))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!same)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (desc.hasWritable && desc.writable() != shape->writable())
|
if (desc.hasWritable && desc.writable() != shape->writable())
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -2144,9 +2166,14 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc,
|
|||||||
/* 8.12.9 step 10. */
|
/* 8.12.9 step 10. */
|
||||||
JS_ASSERT(shape->isDataDescriptor());
|
JS_ASSERT(shape->isDataDescriptor());
|
||||||
if (!shape->configurable() && !shape->writable()) {
|
if (!shape->configurable() && !shape->writable()) {
|
||||||
if ((desc.hasWritable && desc.writable()) ||
|
if (desc.hasWritable && desc.writable())
|
||||||
(desc.hasValue && !SameValue(desc.value, v, cx))) {
|
|
||||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
||||||
|
if (desc.hasValue) {
|
||||||
|
JSBool same;
|
||||||
|
if (!SameValue(cx, desc.value, v, &same))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!same)
|
||||||
|
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2155,11 +2182,20 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropDesc &desc,
|
|||||||
/* 8.12.9 step 11. */
|
/* 8.12.9 step 11. */
|
||||||
JS_ASSERT(desc.isAccessorDescriptor() && shape->isAccessorDescriptor());
|
JS_ASSERT(desc.isAccessorDescriptor() && shape->isAccessorDescriptor());
|
||||||
if (!shape->configurable()) {
|
if (!shape->configurable()) {
|
||||||
if ((desc.hasSet &&
|
if (desc.hasSet) {
|
||||||
!SameValue(desc.setterValue(), shape->setterOrUndefined(), cx)) ||
|
JSBool same;
|
||||||
(desc.hasGet &&
|
if (!SameValue(cx, desc.setterValue(), shape->setterOrUndefined(), &same))
|
||||||
!SameValue(desc.getterValue(), shape->getterOrUndefined(), cx))) {
|
return JS_FALSE;
|
||||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
if (!same)
|
||||||
|
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.hasGet) {
|
||||||
|
JSBool same;
|
||||||
|
if (!SameValue(cx, desc.getterValue(), shape->getterOrUndefined(), &same))
|
||||||
|
return JS_FALSE;
|
||||||
|
if (!same)
|
||||||
|
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, desc.id, rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6312,7 +6348,7 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
|||||||
if (JSID_IS_INT(id)) {
|
if (JSID_IS_INT(id)) {
|
||||||
JS_snprintf(buf, bufsize, "%ld", (long)JSID_TO_INT(id));
|
JS_snprintf(buf, bufsize, "%ld", (long)JSID_TO_INT(id));
|
||||||
} else if (JSID_IS_ATOM(id)) {
|
} else if (JSID_IS_ATOM(id)) {
|
||||||
PutEscapedString(buf, bufsize, JSID_TO_STRING(id), 0);
|
PutEscapedString(buf, bufsize, JSID_TO_ATOM(id), 0);
|
||||||
} else {
|
} else {
|
||||||
JS_snprintf(buf, bufsize, "**FINALIZED ATOM KEY**");
|
JS_snprintf(buf, bufsize, "**FINALIZED ATOM KEY**");
|
||||||
}
|
}
|
||||||
@ -6505,15 +6541,22 @@ js_DumpChars(const jschar *s, size_t n)
|
|||||||
void
|
void
|
||||||
dumpString(JSString *str)
|
dumpString(JSString *str)
|
||||||
{
|
{
|
||||||
dumpChars(str->chars(), str->length());
|
if (const jschar *chars = str->getChars(NULL))
|
||||||
|
dumpChars(chars, str->length());
|
||||||
|
else
|
||||||
|
fprintf(stderr, "(oom in dumpString)");
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(void)
|
JS_FRIEND_API(void)
|
||||||
js_DumpString(JSString *str)
|
js_DumpString(JSString *str)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "JSString* (%p) = jschar * (%p) = ",
|
if (const jschar *chars = str->getChars(NULL)) {
|
||||||
(void *) str, (void *) str->chars());
|
fprintf(stderr, "JSString* (%p) = jschar * (%p) = ",
|
||||||
dumpString(str);
|
(void *) str, (void *) chars);
|
||||||
|
dumpString(str);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "(oom in JS_DumpString)");
|
||||||
|
}
|
||||||
fputc('\n', stderr);
|
fputc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -986,17 +986,21 @@ struct JSObject : js::gc::Cell {
|
|||||||
static const uint32 NAMESPACE_CLASS_RESERVED_SLOTS = 3;
|
static const uint32 NAMESPACE_CLASS_RESERVED_SLOTS = 3;
|
||||||
static const uint32 QNAME_CLASS_RESERVED_SLOTS = 3;
|
static const uint32 QNAME_CLASS_RESERVED_SLOTS = 3;
|
||||||
|
|
||||||
inline jsval getNamePrefix() const;
|
inline JSLinearString *getNamePrefix() const;
|
||||||
inline void setNamePrefix(jsval prefix);
|
inline jsval getNamePrefixVal() const;
|
||||||
|
inline void setNamePrefix(JSLinearString *prefix);
|
||||||
|
inline void clearNamePrefix();
|
||||||
|
|
||||||
inline jsval getNameURI() const;
|
inline JSLinearString *getNameURI() const;
|
||||||
inline void setNameURI(jsval uri);
|
inline jsval getNameURIVal() const;
|
||||||
|
inline void setNameURI(JSLinearString *uri);
|
||||||
|
|
||||||
inline jsval getNamespaceDeclared() const;
|
inline jsval getNamespaceDeclared() const;
|
||||||
inline void setNamespaceDeclared(jsval decl);
|
inline void setNamespaceDeclared(jsval decl);
|
||||||
|
|
||||||
inline jsval getQNameLocalName() const;
|
inline JSLinearString *getQNameLocalName() const;
|
||||||
inline void setQNameLocalName(jsval decl);
|
inline jsval getQNameLocalNameVal() const;
|
||||||
|
inline void setQNameLocalName(JSLinearString *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Proxy-specific getters and setters.
|
* Proxy-specific getters and setters.
|
||||||
|
@ -530,32 +530,55 @@ JSObject::setNativeIterator(js::NativeIterator *ni)
|
|||||||
setPrivate(ni);
|
setPrivate(ni);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jsval
|
inline JSLinearString *
|
||||||
JSObject::getNamePrefix() const
|
JSObject::getNamePrefix() const
|
||||||
|
{
|
||||||
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
|
const js::Value &v = getSlot(JSSLOT_NAME_PREFIX);
|
||||||
|
return !v.isUndefined() ? v.toString()->assertIsLinear() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline jsval
|
||||||
|
JSObject::getNamePrefixVal() const
|
||||||
{
|
{
|
||||||
JS_ASSERT(isNamespace() || isQName());
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
return js::Jsvalify(getSlot(JSSLOT_NAME_PREFIX));
|
return js::Jsvalify(getSlot(JSSLOT_NAME_PREFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
JSObject::setNamePrefix(jsval prefix)
|
JSObject::setNamePrefix(JSLinearString *prefix)
|
||||||
{
|
{
|
||||||
JS_ASSERT(isNamespace() || isQName());
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
setSlot(JSSLOT_NAME_PREFIX, js::Valueify(prefix));
|
setSlot(JSSLOT_NAME_PREFIX, prefix ? js::StringValue(prefix) : js::UndefinedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
JSObject::clearNamePrefix()
|
||||||
|
{
|
||||||
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
|
setSlot(JSSLOT_NAME_PREFIX, js::UndefinedValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JSLinearString *
|
||||||
|
JSObject::getNameURI() const
|
||||||
|
{
|
||||||
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
|
const js::Value &v = getSlot(JSSLOT_NAME_URI);
|
||||||
|
return !v.isUndefined() ? v.toString()->assertIsLinear() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jsval
|
inline jsval
|
||||||
JSObject::getNameURI() const
|
JSObject::getNameURIVal() const
|
||||||
{
|
{
|
||||||
JS_ASSERT(isNamespace() || isQName());
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
return js::Jsvalify(getSlot(JSSLOT_NAME_URI));
|
return js::Jsvalify(getSlot(JSSLOT_NAME_URI));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
JSObject::setNameURI(jsval uri)
|
JSObject::setNameURI(JSLinearString *uri)
|
||||||
{
|
{
|
||||||
JS_ASSERT(isNamespace() || isQName());
|
JS_ASSERT(isNamespace() || isQName());
|
||||||
setSlot(JSSLOT_NAME_URI, js::Valueify(uri));
|
setSlot(JSSLOT_NAME_URI, uri ? js::StringValue(uri) : js::UndefinedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jsval
|
inline jsval
|
||||||
@ -572,18 +595,26 @@ JSObject::setNamespaceDeclared(jsval decl)
|
|||||||
setSlot(JSSLOT_NAMESPACE_DECLARED, js::Valueify(decl));
|
setSlot(JSSLOT_NAMESPACE_DECLARED, js::Valueify(decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jsval
|
inline JSLinearString *
|
||||||
JSObject::getQNameLocalName() const
|
JSObject::getQNameLocalName() const
|
||||||
|
{
|
||||||
|
JS_ASSERT(isQName());
|
||||||
|
const js::Value &v = getSlot(JSSLOT_QNAME_LOCAL_NAME);
|
||||||
|
return !v.isUndefined() ? v.toString()->assertIsLinear() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline jsval
|
||||||
|
JSObject::getQNameLocalNameVal() const
|
||||||
{
|
{
|
||||||
JS_ASSERT(isQName());
|
JS_ASSERT(isQName());
|
||||||
return js::Jsvalify(getSlot(JSSLOT_QNAME_LOCAL_NAME));
|
return js::Jsvalify(getSlot(JSSLOT_QNAME_LOCAL_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
JSObject::setQNameLocalName(jsval name)
|
JSObject::setQNameLocalName(JSLinearString *name)
|
||||||
{
|
{
|
||||||
JS_ASSERT(isQName());
|
JS_ASSERT(isQName());
|
||||||
setSlot(JSSLOT_QNAME_LOCAL_NAME, js::Valueify(name));
|
setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSObject *
|
inline JSObject *
|
||||||
|
@ -119,12 +119,15 @@ js_json_parse(JSContext *cx, uintN argc, Value *vp)
|
|||||||
if (!JS_ConvertArguments(cx, argc, Jsvalify(argv), "S / v", &s, reviver.addr()))
|
if (!JS_ConvertArguments(cx, argc, Jsvalify(argv), "S / v", &s, reviver.addr()))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JSLinearString *linearStr = s->ensureLinear(cx);
|
||||||
|
if (!linearStr)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
JSONParser *jp = js_BeginJSONParse(cx, vp);
|
JSONParser *jp = js_BeginJSONParse(cx, vp);
|
||||||
JSBool ok = jp != NULL;
|
JSBool ok = jp != NULL;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
const jschar *chars;
|
const jschar *chars = linearStr->chars();
|
||||||
size_t length;
|
size_t length = linearStr->length();
|
||||||
s->getCharsAndLength(chars, length);
|
|
||||||
ok = js_ConsumeJSONText(cx, jp, chars, length);
|
ok = js_ConsumeJSONText(cx, jp, chars, length);
|
||||||
ok &= !!js_FinishJSONParse(cx, jp, reviver.value());
|
ok &= !!js_FinishJSONParse(cx, jp, reviver.value());
|
||||||
}
|
}
|
||||||
@ -403,9 +406,11 @@ JO(JSContext *cx, Value *vp, StringifyContext *scx)
|
|||||||
if (!s)
|
if (!s)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
const jschar *chars;
|
size_t length = s->length();
|
||||||
size_t length;
|
const jschar *chars = s->getChars(cx);
|
||||||
s->getCharsAndLength(chars, length);
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
if (!write_string(cx, scx->cb, chars, length) ||
|
if (!write_string(cx, scx->cb, chars, length) ||
|
||||||
!scx->cb.append(':') ||
|
!scx->cb.append(':') ||
|
||||||
!(scx->gap.empty() || scx->cb.append(' ')) ||
|
!(scx->gap.empty() || scx->cb.append(' ')) ||
|
||||||
@ -505,9 +510,11 @@ Str(JSContext *cx, jsid id, JSObject *holder, StringifyContext *scx, Value *vp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vp->isString()) {
|
if (vp->isString()) {
|
||||||
const jschar *chars;
|
JSString *str = vp->toString();
|
||||||
size_t length;
|
size_t length = str->length();
|
||||||
vp->toString()->getCharsAndLength(chars, length);
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
return write_string(cx, scx->cb, chars, length);
|
return write_string(cx, scx->cb, chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,19 +655,16 @@ SprintCString(Sprinter *sp, const char *s)
|
|||||||
static ptrdiff_t
|
static ptrdiff_t
|
||||||
SprintString(Sprinter *sp, JSString *str)
|
SprintString(Sprinter *sp, JSString *str)
|
||||||
{
|
{
|
||||||
const jschar *chars;
|
size_t length = str->length();
|
||||||
size_t length, size;
|
const jschar *chars = str->getChars(sp->context);
|
||||||
ptrdiff_t offset;
|
if (!chars)
|
||||||
|
return -1;
|
||||||
|
|
||||||
str->getCharsAndLength(chars, length);
|
size_t size = js_GetDeflatedStringLength(sp->context, chars, length);
|
||||||
if (length == 0)
|
|
||||||
return sp->offset;
|
|
||||||
|
|
||||||
size = js_GetDeflatedStringLength(sp->context, chars, length);
|
|
||||||
if (size == (size_t)-1 || !SprintEnsureBuffer(sp, size))
|
if (size == (size_t)-1 || !SprintEnsureBuffer(sp, size))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
offset = sp->offset;
|
ptrdiff_t offset = sp->offset;
|
||||||
sp->offset += size;
|
sp->offset += size;
|
||||||
js_DeflateStringToBuffer(sp->context, chars, length, sp->base + offset,
|
js_DeflateStringToBuffer(sp->context, chars, length, sp->base + offset,
|
||||||
&size);
|
&size);
|
||||||
@ -713,39 +710,36 @@ const char js_EscapeMap[] = {
|
|||||||
static char *
|
static char *
|
||||||
QuoteString(Sprinter *sp, JSString *str, uint32 quote)
|
QuoteString(Sprinter *sp, JSString *str, uint32 quote)
|
||||||
{
|
{
|
||||||
JSBool dontEscape, ok;
|
|
||||||
jschar qc, c;
|
|
||||||
ptrdiff_t off, len;
|
|
||||||
const jschar *s, *t, *z;
|
|
||||||
const char *e;
|
|
||||||
char *bp;
|
|
||||||
|
|
||||||
/* Sample off first for later return value pointer computation. */
|
/* Sample off first for later return value pointer computation. */
|
||||||
dontEscape = (quote & DONT_ESCAPE) != 0;
|
JSBool dontEscape = (quote & DONT_ESCAPE) != 0;
|
||||||
qc = (jschar) quote;
|
jschar qc = (jschar) quote;
|
||||||
off = sp->offset;
|
ptrdiff_t off = sp->offset;
|
||||||
if (qc && Sprint(sp, "%c", (char)qc) < 0)
|
if (qc && Sprint(sp, "%c", (char)qc) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
const jschar *s = str->getChars(sp->context);
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
const jschar *z = s + str->length();
|
||||||
|
|
||||||
/* Loop control variables: z points at end of string sentinel. */
|
/* Loop control variables: z points at end of string sentinel. */
|
||||||
str->getCharsAndEnd(s, z);
|
for (const jschar *t = s; t < z; s = ++t) {
|
||||||
for (t = s; t < z; s = ++t) {
|
|
||||||
/* Move t forward from s past un-quote-worthy characters. */
|
/* Move t forward from s past un-quote-worthy characters. */
|
||||||
c = *t;
|
jschar c = *t;
|
||||||
while (JS_ISPRINT(c) && c != qc && c != '\\' && c != '\t' &&
|
while (JS_ISPRINT(c) && c != qc && c != '\\' && c != '\t' &&
|
||||||
!(c >> 8)) {
|
!(c >> 8)) {
|
||||||
c = *++t;
|
c = *++t;
|
||||||
if (t == z)
|
if (t == z)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = t - s;
|
ptrdiff_t len = t - s;
|
||||||
|
|
||||||
/* Allocate space for s, including the '\0' at the end. */
|
/* Allocate space for s, including the '\0' at the end. */
|
||||||
if (!SprintEnsureBuffer(sp, len))
|
if (!SprintEnsureBuffer(sp, len))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Advance sp->offset and copy s into sp's buffer. */
|
/* Advance sp->offset and copy s into sp's buffer. */
|
||||||
bp = sp->base + sp->offset;
|
char *bp = sp->base + sp->offset;
|
||||||
sp->offset += len;
|
sp->offset += len;
|
||||||
while (--len >= 0)
|
while (--len >= 0)
|
||||||
*bp++ = (char) *s++;
|
*bp++ = (char) *s++;
|
||||||
@ -755,6 +749,8 @@ QuoteString(Sprinter *sp, JSString *str, uint32 quote)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* Use js_EscapeMap, \u, or \x only if necessary. */
|
/* Use js_EscapeMap, \u, or \x only if necessary. */
|
||||||
|
bool ok;
|
||||||
|
const char *e;
|
||||||
if (!(c >> 8) && (e = strchr(js_EscapeMap, (int)c)) != NULL) {
|
if (!(c >> 8) && (e = strchr(js_EscapeMap, (int)c)) != NULL) {
|
||||||
ok = dontEscape
|
ok = dontEscape
|
||||||
? Sprint(sp, "%c", (char)c) >= 0
|
? Sprint(sp, "%c", (char)c) >= 0
|
||||||
@ -1580,7 +1576,6 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||||||
const char *lval;
|
const char *lval;
|
||||||
JSAtom *atom;
|
JSAtom *atom;
|
||||||
jssrcnote *sn;
|
jssrcnote *sn;
|
||||||
JSString *str;
|
|
||||||
JSBool hole;
|
JSBool hole;
|
||||||
|
|
||||||
LOCAL_ASSERT(*pc == JSOP_DUP);
|
LOCAL_ASSERT(*pc == JSOP_DUP);
|
||||||
@ -1661,18 +1656,19 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
|
|||||||
case JSOP_GETPROP:
|
case JSOP_GETPROP:
|
||||||
LOAD_ATOM(0);
|
LOAD_ATOM(0);
|
||||||
do_destructure_atom:
|
do_destructure_atom:
|
||||||
|
{
|
||||||
*OFF2STR(&ss->sprinter, head) = '{';
|
*OFF2STR(&ss->sprinter, head) = '{';
|
||||||
str = ATOM_TO_STRING(atom);
|
|
||||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||||
nameoff = ss->sprinter.offset;
|
nameoff = ss->sprinter.offset;
|
||||||
#endif
|
#endif
|
||||||
if (!QuoteString(&ss->sprinter, str,
|
if (!QuoteString(&ss->sprinter, atom,
|
||||||
js_IsIdentifier(str) ? 0 : (jschar)'\'')) {
|
js_IsIdentifier(atom) ? 0 : (jschar)'\'')) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (SprintPut(&ss->sprinter, ": ", 2) < 0)
|
if (SprintPut(&ss->sprinter, ": ", 2) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOCAL_ASSERT(0);
|
LOCAL_ASSERT(0);
|
||||||
@ -5198,7 +5194,11 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v_in,
|
|||||||
if (!fallback)
|
if (!fallback)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return js_DeflateString(cx, fallback->chars(), fallback->length());
|
size_t length = fallback->length();
|
||||||
|
const jschar *chars = fallback->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return NULL;
|
||||||
|
return js_DeflateString(cx, chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -8003,11 +8003,9 @@ Parser::xmlElementOrList(JSBool allowList)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (endAtom && startAtom && endAtom != startAtom) {
|
if (endAtom && startAtom && endAtom != startAtom) {
|
||||||
JSString *str = ATOM_TO_STRING(startAtom);
|
|
||||||
|
|
||||||
/* End vs. start tag name mismatch: point to the tag name. */
|
/* End vs. start tag name mismatch: point to the tag name. */
|
||||||
reportErrorNumber(pn2, JSREPORT_UC | JSREPORT_ERROR, JSMSG_XML_TAG_NAME_MISMATCH,
|
reportErrorNumber(pn2, JSREPORT_UC | JSREPORT_ERROR, JSMSG_XML_TAG_NAME_MISMATCH,
|
||||||
str->chars());
|
startAtom->chars());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8676,15 +8674,12 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
|
|||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
if (tokenStream.matchToken(TOK_DBLCOLON)) {
|
if (tokenStream.matchToken(TOK_DBLCOLON)) {
|
||||||
if (afterDot) {
|
if (afterDot) {
|
||||||
JSString *str;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Here primaryExpr is called after . or .. followed by a name
|
* Here primaryExpr is called after . or .. followed by a name
|
||||||
* followed by ::. This is the only case where a keyword after
|
* followed by ::. This is the only case where a keyword after
|
||||||
* . or .. is not treated as a property name.
|
* . or .. is not treated as a property name.
|
||||||
*/
|
*/
|
||||||
str = ATOM_TO_STRING(pn->pn_atom);
|
tt = js_CheckKeyword(pn->pn_atom->chars(), pn->pn_atom->length());
|
||||||
tt = js_CheckKeyword(str->chars(), str->length());
|
|
||||||
if (tt == TOK_FUNCTION) {
|
if (tt == TOK_FUNCTION) {
|
||||||
pn->pn_arity = PN_NULLARY;
|
pn->pn_arity = PN_NULLARY;
|
||||||
pn->pn_type = TOK_FUNCTION;
|
pn->pn_type = TOK_FUNCTION;
|
||||||
|
@ -480,13 +480,14 @@ Shape::dump(JSContext *cx, FILE *fp) const
|
|||||||
if (JSID_IS_INT(id)) {
|
if (JSID_IS_INT(id)) {
|
||||||
fprintf(fp, "[%ld]", (long) JSID_TO_INT(id));
|
fprintf(fp, "[%ld]", (long) JSID_TO_INT(id));
|
||||||
} else {
|
} else {
|
||||||
JSString *str;
|
JSLinearString *str;
|
||||||
if (JSID_IS_ATOM(id)) {
|
if (JSID_IS_ATOM(id)) {
|
||||||
str = JSID_TO_STRING(id);
|
str = JSID_TO_ATOM(id);
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(JSID_IS_OBJECT(id));
|
JS_ASSERT(JSID_IS_OBJECT(id));
|
||||||
str = js_ValueToString(cx, IdToValue(id));
|
JSString *s = js_ValueToString(cx, IdToValue(id));
|
||||||
fputs("object ", fp);
|
fputs("object ", fp);
|
||||||
|
str = s ? s->ensureLinear(cx) : NULL;
|
||||||
}
|
}
|
||||||
if (!str)
|
if (!str)
|
||||||
fputs("<error>", fp);
|
fputs("<error>", fp);
|
||||||
|
@ -92,6 +92,7 @@ typedef struct JSTreeContext JSTreeContext;
|
|||||||
typedef struct JSTryNote JSTryNote;
|
typedef struct JSTryNote JSTryNote;
|
||||||
|
|
||||||
/* Friend "Advanced API" typedefs. */
|
/* Friend "Advanced API" typedefs. */
|
||||||
|
typedef struct JSLinearString JSLinearString;
|
||||||
typedef struct JSAtom JSAtom;
|
typedef struct JSAtom JSAtom;
|
||||||
typedef struct JSAtomList JSAtomList;
|
typedef struct JSAtomList JSAtomList;
|
||||||
typedef struct JSAtomListElement JSAtomListElement;
|
typedef struct JSAtomListElement JSAtomListElement;
|
||||||
|
@ -2829,7 +2829,12 @@ reflect_parse(JSContext *cx, uint32 argc, jsval *vp)
|
|||||||
if (!str)
|
if (!str)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
filename = js_DeflateString(cx, str->chars(), str->length());
|
size_t length = str->length();
|
||||||
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
filename = js_DeflateString(cx, chars, length);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
filenamep.reset(filename);
|
filenamep.reset(filename);
|
||||||
@ -2844,10 +2849,10 @@ reflect_parse(JSContext *cx, uint32 argc, jsval *vp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const jschar *chars;
|
size_t length = src->length();
|
||||||
size_t length;
|
const jschar *chars = src->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
src->getCharsAndLength(chars, length);
|
return JS_FALSE;
|
||||||
|
|
||||||
Parser parser(cx);
|
Parser parser(cx);
|
||||||
|
|
||||||
|
@ -243,9 +243,11 @@ RegExp::handlePCREError(JSContext *cx, int error)
|
|||||||
bool
|
bool
|
||||||
RegExp::parseFlags(JSContext *cx, JSString *flagStr, uint32 &flagsOut)
|
RegExp::parseFlags(JSContext *cx, JSString *flagStr, uint32 &flagsOut)
|
||||||
{
|
{
|
||||||
const jschar *s;
|
size_t n = flagStr->length();
|
||||||
size_t n;
|
const jschar *s = flagStr->getChars(cx);
|
||||||
flagStr->getCharsAndLength(s, n);
|
if (!s)
|
||||||
|
return false;
|
||||||
|
|
||||||
flagsOut = 0;
|
flagsOut = 0;
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
#define HANDLE_FLAG(__name) \
|
#define HANDLE_FLAG(__name) \
|
||||||
@ -578,9 +580,12 @@ js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const jschar *source;
|
JSLinearString *src = re->getSource();
|
||||||
size_t length;
|
size_t length = src->length();
|
||||||
re->getSource()->getCharsAndLength(source, length);
|
const jschar *source = src->getChars(cx);
|
||||||
|
if (!source)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
source = empty_regexp_ucstr;
|
source = empty_regexp_ucstr;
|
||||||
length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
|
length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
|
||||||
@ -632,9 +637,11 @@ regexp_toString(JSContext *cx, uintN argc, Value *vp)
|
|||||||
static JSString *
|
static JSString *
|
||||||
EscapeNakedForwardSlashes(JSContext *cx, JSString *unescaped)
|
EscapeNakedForwardSlashes(JSContext *cx, JSString *unescaped)
|
||||||
{
|
{
|
||||||
const jschar *oldChars;
|
size_t oldLen = unescaped->length();
|
||||||
size_t oldLen;
|
const jschar *oldChars = unescaped->getChars(cx);
|
||||||
unescaped->getCharsAndLength(oldChars, oldLen);
|
if (!oldChars)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
js::Vector<jschar, 128> newChars(cx);
|
js::Vector<jschar, 128> newChars(cx);
|
||||||
for (const jschar *it = oldChars; it < oldChars + oldLen; ++it) {
|
for (const jschar *it = oldChars; it < oldChars + oldLen; ++it) {
|
||||||
if (*it == '/' && (it == oldChars || it[-1] != '\\')) {
|
if (*it == '/' && (it == oldChars || it[-1] != '\\')) {
|
||||||
|
@ -61,7 +61,7 @@ class RegExpStatics
|
|||||||
typedef Vector<int, 20, SystemAllocPolicy> MatchPairs;
|
typedef Vector<int, 20, SystemAllocPolicy> MatchPairs;
|
||||||
MatchPairs matchPairs;
|
MatchPairs matchPairs;
|
||||||
/* The input that was used to produce matchPairs. */
|
/* The input that was used to produce matchPairs. */
|
||||||
JSString *matchPairsInput;
|
JSLinearString *matchPairsInput;
|
||||||
/* The input last set on the statics. */
|
/* The input last set on the statics. */
|
||||||
JSString *pendingInput;
|
JSString *pendingInput;
|
||||||
uintN flags;
|
uintN flags;
|
||||||
@ -180,7 +180,7 @@ class RegExpStatics
|
|||||||
|
|
||||||
/* Mutators. */
|
/* Mutators. */
|
||||||
|
|
||||||
bool updateFromMatch(JSContext *cx, JSString *input, int *buf, size_t matchItemCount) {
|
bool updateFromMatch(JSContext *cx, JSLinearString *input, int *buf, size_t matchItemCount) {
|
||||||
aboutToWrite();
|
aboutToWrite();
|
||||||
pendingInput = input;
|
pendingInput = input;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ regexp_statics_construct(JSContext *cx, JSObject *parent)
|
|||||||
class RegExp
|
class RegExp
|
||||||
{
|
{
|
||||||
jsrefcount refCount;
|
jsrefcount refCount;
|
||||||
JSString *source;
|
JSLinearString *source;
|
||||||
#if ENABLE_YARR_JIT
|
#if ENABLE_YARR_JIT
|
||||||
JSC::Yarr::RegexCodeBlock compiled;
|
JSC::Yarr::RegexCodeBlock compiled;
|
||||||
#else
|
#else
|
||||||
@ -85,9 +85,9 @@ class RegExp
|
|||||||
unsigned parenCount;
|
unsigned parenCount;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
|
||||||
RegExp(JSString *source, uint32 flags)
|
RegExp(JSLinearString *source, uint32 flags)
|
||||||
: refCount(1), source(source), compiled(), parenCount(0), flags(flags) {}
|
: refCount(1), source(source), compiled(), parenCount(0), flags(flags) {}
|
||||||
bool compileHelper(JSContext *cx, UString &pattern);
|
bool compileHelper(JSContext *cx, JSLinearString &pattern);
|
||||||
bool compile(JSContext *cx);
|
bool compile(JSContext *cx);
|
||||||
static const uint32 allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_MULTILINE | JSREG_STICKY;
|
static const uint32 allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_MULTILINE | JSREG_STICKY;
|
||||||
void handlePCREError(JSContext *cx, int error);
|
void handlePCREError(JSContext *cx, int error);
|
||||||
@ -154,7 +154,7 @@ class RegExp
|
|||||||
void decref(JSContext *cx);
|
void decref(JSContext *cx);
|
||||||
|
|
||||||
/* Accessors. */
|
/* Accessors. */
|
||||||
JSString *getSource() const { return source; }
|
JSLinearString *getSource() const { return source; }
|
||||||
size_t getParenCount() const { return parenCount; }
|
size_t getParenCount() const { return parenCount; }
|
||||||
bool ignoreCase() const { return flags & JSREG_FOLD; }
|
bool ignoreCase() const { return flags & JSREG_FOLD; }
|
||||||
bool global() const { return flags & JSREG_GLOB; }
|
bool global() const { return flags & JSREG_GLOB; }
|
||||||
@ -274,7 +274,7 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
|
RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *inputstr,
|
||||||
size_t *lastIndex, bool test, Value *rval)
|
size_t *lastIndex, bool test, Value *rval)
|
||||||
{
|
{
|
||||||
#if !ENABLE_YARR_JIT
|
#if !ENABLE_YARR_JIT
|
||||||
@ -299,8 +299,12 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
|
|||||||
for (int *it = buf; it != buf + matchItemCount; ++it)
|
for (int *it = buf; it != buf + matchItemCount; ++it)
|
||||||
*it = -1;
|
*it = -1;
|
||||||
|
|
||||||
const jschar *chars = input->chars();
|
JSLinearString *input = inputstr->ensureLinear(cx);
|
||||||
|
if (!input)
|
||||||
|
return false;
|
||||||
|
|
||||||
size_t len = input->length();
|
size_t len = input->length();
|
||||||
|
const jschar *chars = input->chars();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inputOffset emulates sticky mode by matching from this offset into the char buf and
|
* inputOffset emulates sticky mode by matching from this offset into the char buf and
|
||||||
@ -360,11 +364,14 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
|
|||||||
inline RegExp *
|
inline RegExp *
|
||||||
RegExp::create(JSContext *cx, JSString *source, uint32 flags)
|
RegExp::create(JSContext *cx, JSString *source, uint32 flags)
|
||||||
{
|
{
|
||||||
|
JSLinearString *flatSource = source->ensureLinear(cx);
|
||||||
|
if (!flatSource)
|
||||||
|
return NULL;
|
||||||
RegExp *self;
|
RegExp *self;
|
||||||
void *mem = cx->malloc(sizeof(*self));
|
void *mem = cx->malloc(sizeof(*self));
|
||||||
if (!mem)
|
if (!mem)
|
||||||
return NULL;
|
return NULL;
|
||||||
self = new (mem) RegExp(source, flags);
|
self = new (mem) RegExp(flatSource, flags);
|
||||||
if (!self->compile(cx)) {
|
if (!self->compile(cx)) {
|
||||||
cx->destroy<RegExp>(self);
|
cx->destroy<RegExp>(self);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -418,7 +425,7 @@ YarrJITIsBroken(JSContext *cx)
|
|||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
RegExp::compileHelper(JSContext *cx, UString &pattern)
|
RegExp::compileHelper(JSContext *cx, JSLinearString &pattern)
|
||||||
{
|
{
|
||||||
#if ENABLE_YARR_JIT
|
#if ENABLE_YARR_JIT
|
||||||
bool fellBack = false;
|
bool fellBack = false;
|
||||||
@ -452,8 +459,13 @@ RegExp::compileHelper(JSContext *cx, UString &pattern)
|
|||||||
inline bool
|
inline bool
|
||||||
RegExp::compile(JSContext *cx)
|
RegExp::compile(JSContext *cx)
|
||||||
{
|
{
|
||||||
|
/* Flatten source early for the rest of compilation. */
|
||||||
|
if (!source->ensureLinear(cx))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!sticky())
|
if (!sticky())
|
||||||
return compileHelper(cx, *source);
|
return compileHelper(cx, *source);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The sticky case we implement hackily by prepending a caret onto the front
|
* The sticky case we implement hackily by prepending a caret onto the front
|
||||||
* and relying on |::execute| to pseudo-slice the string when it sees a sticky regexp.
|
* and relying on |::execute| to pseudo-slice the string when it sees a sticky regexp.
|
||||||
@ -465,10 +477,10 @@ RegExp::compile(JSContext *cx)
|
|||||||
if (!cb.reserve(JS_ARRAY_LENGTH(prefix) + source->length() + JS_ARRAY_LENGTH(postfix)))
|
if (!cb.reserve(JS_ARRAY_LENGTH(prefix) + source->length() + JS_ARRAY_LENGTH(postfix)))
|
||||||
return false;
|
return false;
|
||||||
JS_ALWAYS_TRUE(cb.append(prefix, JS_ARRAY_LENGTH(prefix)));
|
JS_ALWAYS_TRUE(cb.append(prefix, JS_ARRAY_LENGTH(prefix)));
|
||||||
JS_ALWAYS_TRUE(cb.append(source->chars(), source->length()));
|
JS_ALWAYS_TRUE(cb.append(source->flatChars(), source->length()));
|
||||||
JS_ALWAYS_TRUE(cb.append(postfix, JS_ARRAY_LENGTH(postfix)));
|
JS_ALWAYS_TRUE(cb.append(postfix, JS_ARRAY_LENGTH(postfix)));
|
||||||
|
|
||||||
JSString *fakeySource = js_NewStringFromCharBuffer(cx, cb);
|
JSLinearString *fakeySource = js_NewStringFromCharBuffer(cx, cb);
|
||||||
if (!fakeySource)
|
if (!fakeySource)
|
||||||
return false;
|
return false;
|
||||||
return compileHelper(cx, *fakeySource);
|
return compileHelper(cx, *fakeySource);
|
||||||
|
@ -147,19 +147,17 @@ js_CheckKeyword(const jschar *str, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
js_IsIdentifier(JSString *str)
|
js_IsIdentifier(JSLinearString *str)
|
||||||
{
|
{
|
||||||
size_t length;
|
const jschar *chars = str->chars();
|
||||||
jschar c;
|
size_t length = str->length();
|
||||||
const jschar *chars, *end;
|
|
||||||
|
|
||||||
str->getCharsAndLength(chars, length);
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
c = *chars;
|
jschar c = *chars;
|
||||||
if (!JS_ISIDSTART(c))
|
if (!JS_ISIDSTART(c))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
end = chars + length;
|
const jschar *end = chars + length;
|
||||||
while (++chars != end) {
|
while (++chars != end) {
|
||||||
c = *chars;
|
c = *chars;
|
||||||
if (!JS_ISIDENT(c))
|
if (!JS_ISIDENT(c))
|
||||||
|
@ -537,7 +537,7 @@ typedef void (*JSMapKeywordFun)(const char *);
|
|||||||
* check if str is a JS keyword.
|
* check if str is a JS keyword.
|
||||||
*/
|
*/
|
||||||
extern JSBool
|
extern JSBool
|
||||||
js_IsIdentifier(JSString *str);
|
js_IsIdentifier(JSLinearString *str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error
|
* Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error
|
||||||
|
@ -1453,8 +1453,8 @@ PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
|
|||||||
name = trc->debugPrintIndex ? js_setter_str : js_getter_str;
|
name = trc->debugPrintIndex ? js_setter_str : js_getter_str;
|
||||||
|
|
||||||
if (JSID_IS_ATOM(id)) {
|
if (JSID_IS_ATOM(id)) {
|
||||||
n = PutEscapedString(buf, bufsize - 1, JSID_TO_STRING(id), 0);
|
n = PutEscapedString(buf, bufsize, JSID_TO_ATOM(id), 0);
|
||||||
if (n < bufsize - 1)
|
if (n < bufsize)
|
||||||
JS_snprintf(buf + n, bufsize - n, " %s", name);
|
JS_snprintf(buf + n, bufsize - n, " %s", name);
|
||||||
} else if (JSID_IS_INT(shape->id)) {
|
} else if (JSID_IS_INT(shape->id)) {
|
||||||
JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(id), name);
|
JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(id), name);
|
||||||
@ -1476,8 +1476,8 @@ PrintPropertyMethod(JSTracer *trc, char *buf, size_t bufsize)
|
|||||||
JS_ASSERT(!JSID_IS_VOID(id));
|
JS_ASSERT(!JSID_IS_VOID(id));
|
||||||
|
|
||||||
JS_ASSERT(JSID_IS_ATOM(id));
|
JS_ASSERT(JSID_IS_ATOM(id));
|
||||||
n = PutEscapedString(buf, bufsize - 1, JSID_TO_STRING(id), 0);
|
n = PutEscapedString(buf, bufsize, JSID_TO_ATOM(id), 0);
|
||||||
if (n < bufsize - 1)
|
if (n < bufsize)
|
||||||
JS_snprintf(buf + n, bufsize - n, " method");
|
JS_snprintf(buf + n, bufsize - n, " method");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
775
js/src/jsstr.cpp
775
js/src/jsstr.cpp
File diff suppressed because it is too large
Load Diff
170
js/src/jsstr.h
170
js/src/jsstr.h
@ -83,6 +83,8 @@ namespace js { namespace mjit {
|
|||||||
class Compiler;
|
class Compiler;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
struct JSLinearString;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The GC-thing "string" type.
|
* The GC-thing "string" type.
|
||||||
*
|
*
|
||||||
@ -110,6 +112,10 @@ namespace js { namespace mjit {
|
|||||||
*
|
*
|
||||||
* When a string is a ROPE, it represents the lazy concatenation of other
|
* When a string is a ROPE, it represents the lazy concatenation of other
|
||||||
* strings. In general, the nodes reachable from any rope form a dag.
|
* strings. In general, the nodes reachable from any rope form a dag.
|
||||||
|
*
|
||||||
|
* To allow static type-based checking that a given JSString* always points
|
||||||
|
* to a flat or non-rope string, the JSFlatString and JSLinearString types may
|
||||||
|
* be used. Instead of casting, callers should use ensureX() and assertIsX().
|
||||||
*/
|
*/
|
||||||
struct JSString
|
struct JSString
|
||||||
{
|
{
|
||||||
@ -124,7 +130,7 @@ struct JSString
|
|||||||
*/
|
*/
|
||||||
size_t lengthAndFlags; /* in all strings */
|
size_t lengthAndFlags; /* in all strings */
|
||||||
union {
|
union {
|
||||||
jschar *chars; /* in non-rope strings */
|
const jschar *chars; /* in non-rope strings */
|
||||||
JSString *left; /* in rope strings */
|
JSString *left; /* in rope strings */
|
||||||
} u;
|
} u;
|
||||||
union {
|
union {
|
||||||
@ -211,11 +217,6 @@ struct JSString
|
|||||||
return lengthAndFlags & ROPE_BIT;
|
return lengthAndFlags & ROPE_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE jschar *chars() {
|
|
||||||
ensureNotRope();
|
|
||||||
return u.chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_ALWAYS_INLINE size_t length() const {
|
JS_ALWAYS_INLINE size_t length() const {
|
||||||
return lengthAndFlags >> LENGTH_SHIFT;
|
return lengthAndFlags >> LENGTH_SHIFT;
|
||||||
}
|
}
|
||||||
@ -224,13 +225,18 @@ struct JSString
|
|||||||
return lengthAndFlags <= TYPE_FLAGS_MASK;
|
return lengthAndFlags <= TYPE_FLAGS_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE void getCharsAndLength(const jschar *&chars, size_t &length) {
|
/* This can fail by returning null and reporting an error on cx. */
|
||||||
chars = this->chars();
|
JS_ALWAYS_INLINE const jschar *getChars(JSContext *cx) {
|
||||||
length = this->length();
|
if (isRope())
|
||||||
|
return flatten(cx);
|
||||||
|
return nonRopeChars();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE void getCharsAndEnd(const jschar *&chars, const jschar *&end) {
|
/* This can fail by returning null and reporting an error on cx. */
|
||||||
end = length() + (chars = this->chars());
|
JS_ALWAYS_INLINE const jschar *getCharsZ(JSContext *cx) {
|
||||||
|
if (!isFlat())
|
||||||
|
return undepend(cx);
|
||||||
|
return flatChars();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE void initFlatNotTerminated(jschar *chars, size_t length) {
|
JS_ALWAYS_INLINE void initFlatNotTerminated(jschar *chars, size_t length) {
|
||||||
@ -246,7 +252,7 @@ struct JSString
|
|||||||
JS_ASSERT(chars[length] == jschar(0));
|
JS_ASSERT(chars[length] == jschar(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE void initShortString(jschar *chars, size_t length) {
|
JS_ALWAYS_INLINE void initShortString(const jschar *chars, size_t length) {
|
||||||
JS_ASSERT(length <= MAX_LENGTH);
|
JS_ASSERT(length <= MAX_LENGTH);
|
||||||
JS_ASSERT(chars >= inlineStorage && chars < (jschar *)(this + 2));
|
JS_ASSERT(chars >= inlineStorage && chars < (jschar *)(this + 2));
|
||||||
JS_ASSERT(!isStatic(this));
|
JS_ASSERT(!isStatic(this));
|
||||||
@ -263,7 +269,12 @@ struct JSString
|
|||||||
s.capacity = cap;
|
s.capacity = cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE jschar *flatChars() const {
|
JS_ALWAYS_INLINE JSFlatString *assertIsFlat() {
|
||||||
|
JS_ASSERT(isFlat());
|
||||||
|
return reinterpret_cast<JSFlatString *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ALWAYS_INLINE const jschar *flatChars() const {
|
||||||
JS_ASSERT(isFlat());
|
JS_ASSERT(isFlat());
|
||||||
return u.chars;
|
return u.chars;
|
||||||
}
|
}
|
||||||
@ -293,22 +304,22 @@ struct JSString
|
|||||||
* The chars pointer should point somewhere inside the buffer owned by base.
|
* The chars pointer should point somewhere inside the buffer owned by base.
|
||||||
* The caller still needs to pass base for GC purposes.
|
* The caller still needs to pass base for GC purposes.
|
||||||
*/
|
*/
|
||||||
inline void initDependent(JSString *base, jschar *chars, size_t length) {
|
inline void initDependent(JSString *base, const jschar *chars, size_t length) {
|
||||||
JS_ASSERT(!isStatic(this));
|
JS_ASSERT(!isStatic(this));
|
||||||
JS_ASSERT(base->isFlat());
|
JS_ASSERT(base->isFlat());
|
||||||
JS_ASSERT(chars >= base->chars() && chars < base->chars() + base->length());
|
JS_ASSERT(chars >= base->flatChars() && chars < base->flatChars() + base->length());
|
||||||
JS_ASSERT(length <= base->length() - (chars - base->chars()));
|
JS_ASSERT(length <= base->length() - (chars - base->flatChars()));
|
||||||
lengthAndFlags = buildLengthAndFlags(length, DEPENDENT);
|
lengthAndFlags = buildLengthAndFlags(length, DEPENDENT);
|
||||||
u.chars = chars;
|
u.chars = chars;
|
||||||
s.base = base;
|
s.base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSString *dependentBase() const {
|
inline JSLinearString *dependentBase() const {
|
||||||
JS_ASSERT(isDependent());
|
JS_ASSERT(isDependent());
|
||||||
return s.base;
|
return s.base->assertIsLinear();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ALWAYS_INLINE jschar *dependentChars() {
|
JS_ALWAYS_INLINE const jschar *dependentChars() {
|
||||||
JS_ASSERT(isDependent());
|
JS_ASSERT(isDependent());
|
||||||
return u.chars;
|
return u.chars;
|
||||||
}
|
}
|
||||||
@ -320,16 +331,6 @@ struct JSString
|
|||||||
|
|
||||||
const jschar *undepend(JSContext *cx);
|
const jschar *undepend(JSContext *cx);
|
||||||
|
|
||||||
const jschar *getCharsZ(JSContext *cx) {
|
|
||||||
if (!isFlat())
|
|
||||||
return undepend(cx);
|
|
||||||
return flatChars();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ensureNotDependent(JSContext *cx) {
|
|
||||||
return !isDependent() || undepend(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const jschar *nonRopeChars() const {
|
const jschar *nonRopeChars() const {
|
||||||
JS_ASSERT(!isRope());
|
JS_ASSERT(!isRope());
|
||||||
return u.chars;
|
return u.chars;
|
||||||
@ -353,17 +354,27 @@ struct JSString
|
|||||||
return s.right;
|
return s.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void finishTraversalConversion(JSString *base, jschar *baseBegin, jschar *end) {
|
inline void finishTraversalConversion(JSString *base, const jschar *baseBegin, const jschar *end) {
|
||||||
JS_ASSERT(baseBegin <= u.chars && u.chars <= end);
|
JS_ASSERT(baseBegin <= u.chars && u.chars <= end);
|
||||||
lengthAndFlags = buildLengthAndFlags(end - u.chars, DEPENDENT);
|
lengthAndFlags = buildLengthAndFlags(end - u.chars, DEPENDENT);
|
||||||
s.base = base;
|
s.base = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flatten();
|
const jschar *flatten(JSContext *maybecx);
|
||||||
|
|
||||||
void ensureNotRope() {
|
JSLinearString *ensureLinear(JSContext *cx) {
|
||||||
if (isRope())
|
if (isRope() && !flatten(cx))
|
||||||
flatten();
|
return NULL;
|
||||||
|
return reinterpret_cast<JSLinearString *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLinear() const {
|
||||||
|
return !isRope();
|
||||||
|
}
|
||||||
|
|
||||||
|
JSLinearString *assertIsLinear() {
|
||||||
|
JS_ASSERT(isLinear());
|
||||||
|
return reinterpret_cast<JSLinearString *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef uint8 SmallChar;
|
typedef uint8 SmallChar;
|
||||||
@ -426,13 +437,13 @@ struct JSString
|
|||||||
*/
|
*/
|
||||||
static const JSString *const intStringTable[];
|
static const JSString *const intStringTable[];
|
||||||
|
|
||||||
static JSString *unitString(jschar c);
|
static JSFlatString *unitString(jschar c);
|
||||||
static JSString *getUnitString(JSContext *cx, JSString *str, size_t index);
|
static JSLinearString *getUnitString(JSContext *cx, JSString *str, size_t index);
|
||||||
static JSString *length2String(jschar c1, jschar c2);
|
static JSFlatString *length2String(jschar c1, jschar c2);
|
||||||
static JSString *length2String(uint32 i);
|
static JSFlatString *length2String(uint32 i);
|
||||||
static JSString *intString(jsint i);
|
static JSFlatString *intString(jsint i);
|
||||||
|
|
||||||
static JSString *lookupStaticString(const jschar *chars, size_t length);
|
static JSFlatString *lookupStaticString(const jschar *chars, size_t length);
|
||||||
|
|
||||||
JS_ALWAYS_INLINE void finalize(JSContext *cx);
|
JS_ALWAYS_INLINE void finalize(JSContext *cx);
|
||||||
|
|
||||||
@ -450,12 +461,37 @@ struct JSString
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JSFlatString : JSString
|
/*
|
||||||
|
* A "linear" string may or may not be null-terminated, but it provides
|
||||||
|
* infallible access to a linear array of characters. Namely, this means the
|
||||||
|
* string is not a rope.
|
||||||
|
*/
|
||||||
|
struct JSLinearString : JSString
|
||||||
{
|
{
|
||||||
|
const jschar *chars() const { return JSString::nonRopeChars(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A linear string where, additionally, chars()[length()] == '\0'. Namely, this
|
||||||
|
* means the string is not a dependent string or rope.
|
||||||
|
*/
|
||||||
|
struct JSFlatString : JSLinearString
|
||||||
|
{
|
||||||
|
const jschar *charsZ() const { return chars(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_STATIC_ASSERT(sizeof(JSFlatString) == sizeof(JSString));
|
JS_STATIC_ASSERT(sizeof(JSFlatString) == sizeof(JSString));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A flat string which has been "atomized", i.e., that is a unique string among
|
||||||
|
* other atomized strings and therefore allows equality via pointer comparison.
|
||||||
|
*/
|
||||||
|
struct JSAtom : JSFlatString
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
struct JSExternalString : JSString
|
struct JSExternalString : JSString
|
||||||
{
|
{
|
||||||
static const uintN TYPE_LIMIT = 8;
|
static const uintN TYPE_LIMIT = 8;
|
||||||
@ -548,6 +584,7 @@ namespace js {
|
|||||||
* Implemented in jsstrinlines.h.
|
* Implemented in jsstrinlines.h.
|
||||||
*/
|
*/
|
||||||
class StringSegmentRange;
|
class StringSegmentRange;
|
||||||
|
class MutatingRopeSegmentRange;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utility for building a rope (lazy concatenation) of strings.
|
* Utility for building a rope (lazy concatenation) of strings.
|
||||||
@ -747,7 +784,7 @@ extern const char js_decodeURIComponent_str[];
|
|||||||
extern const char js_encodeURIComponent_str[];
|
extern const char js_encodeURIComponent_str[];
|
||||||
|
|
||||||
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewString(JSContext *cx, jschar *chars, size_t length);
|
js_NewString(JSContext *cx, jschar *chars, size_t length);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -755,25 +792,25 @@ js_NewString(JSContext *cx, jschar *chars, size_t length);
|
|||||||
* This function takes responsibility for adding the terminating '\0' required
|
* This function takes responsibility for adding the terminating '\0' required
|
||||||
* by js_NewString.
|
* by js_NewString.
|
||||||
*/
|
*/
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewStringFromCharBuffer(JSContext *cx, JSCharBuffer &cb);
|
js_NewStringFromCharBuffer(JSContext *cx, JSCharBuffer &cb);
|
||||||
|
|
||||||
extern JSString *
|
extern JSLinearString *
|
||||||
js_NewDependentString(JSContext *cx, JSString *base, size_t start,
|
js_NewDependentString(JSContext *cx, JSString *base, size_t start,
|
||||||
size_t length);
|
size_t length);
|
||||||
|
|
||||||
/* Copy a counted string and GC-allocate a descriptor for it. */
|
/* Copy a counted string and GC-allocate a descriptor for it. */
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
|
js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
|
||||||
|
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewStringCopyN(JSContext *cx, const char *s, size_t n);
|
js_NewStringCopyN(JSContext *cx, const char *s, size_t n);
|
||||||
|
|
||||||
/* Copy a C string and GC-allocate a descriptor for it. */
|
/* Copy a C string and GC-allocate a descriptor for it. */
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewStringCopyZ(JSContext *cx, const jschar *s);
|
js_NewStringCopyZ(JSContext *cx, const jschar *s);
|
||||||
|
|
||||||
extern JSString *
|
extern JSFlatString *
|
||||||
js_NewStringCopyZ(JSContext *cx, const char *s);
|
js_NewStringCopyZ(JSContext *cx, const char *s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -826,29 +863,42 @@ js_ValueToSource(JSContext *cx, const js::Value &v);
|
|||||||
* Compute a hash function from str. The caller can call this function even if
|
* Compute a hash function from str. The caller can call this function even if
|
||||||
* str is not a GC-allocated thing.
|
* str is not a GC-allocated thing.
|
||||||
*/
|
*/
|
||||||
extern uint32
|
inline uint32
|
||||||
js_HashString(JSString *str);
|
js_HashString(JSLinearString *str)
|
||||||
|
{
|
||||||
|
const jschar *s = str->chars();
|
||||||
|
size_t n = str->length();
|
||||||
|
uint32 h;
|
||||||
|
for (h = 0; n; s++, n--)
|
||||||
|
h = JS_ROTATE_LEFT32(h, 4) ^ *s;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace js {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test if strings are equal. The caller can call the function even if str1
|
* Test if strings are equal. The caller can call the function even if str1
|
||||||
* or str2 are not GC-allocated things.
|
* or str2 are not GC-allocated things.
|
||||||
*/
|
*/
|
||||||
extern JSBool JS_FASTCALL
|
extern bool
|
||||||
js_EqualStrings(JSString *str1, JSString *str2);
|
EqualStrings(JSContext *cx, JSString *str1, JSString *str2, JSBool *result);
|
||||||
|
|
||||||
|
/* EqualStrings is infallible on linear strings. */
|
||||||
|
extern bool
|
||||||
|
EqualStrings(JSLinearString *str1, JSLinearString *str2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return less than, equal to, or greater than zero depending on whether
|
* Return less than, equal to, or greater than zero depending on whether
|
||||||
* str1 is less than, equal to, or greater than str2.
|
* str1 is less than, equal to, or greater than str2.
|
||||||
*/
|
*/
|
||||||
extern int32 JS_FASTCALL
|
extern bool
|
||||||
js_CompareStrings(JSString *str1, JSString *str2);
|
CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32 *result);
|
||||||
|
|
||||||
namespace js {
|
|
||||||
/*
|
/*
|
||||||
* Return true if the string matches the given sequence of ASCII bytes.
|
* Return true if the string matches the given sequence of ASCII bytes.
|
||||||
*/
|
*/
|
||||||
extern JSBool
|
extern bool
|
||||||
MatchStringAndAscii(JSString *str, const char *asciiBytes);
|
StringEqualsAscii(JSLinearString *str, const char *asciiBytes);
|
||||||
|
|
||||||
} /* namespacejs */
|
} /* namespacejs */
|
||||||
|
|
||||||
@ -994,7 +1044,7 @@ js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char);
|
|||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
extern size_t
|
extern size_t
|
||||||
PutEscapedStringImpl(char *buffer, size_t size, FILE *fp, JSString *str, uint32 quote);
|
PutEscapedStringImpl(char *buffer, size_t size, FILE *fp, JSLinearString *str, uint32 quote);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write str into buffer escaping any non-printable or non-ASCII character
|
* Write str into buffer escaping any non-printable or non-ASCII character
|
||||||
@ -1006,7 +1056,7 @@ PutEscapedStringImpl(char *buffer, size_t size, FILE *fp, JSString *str, uint32
|
|||||||
* be a single or double quote character that will quote the output.
|
* be a single or double quote character that will quote the output.
|
||||||
*/
|
*/
|
||||||
inline size_t
|
inline size_t
|
||||||
PutEscapedString(char *buffer, size_t size, JSString *str, uint32 quote)
|
PutEscapedString(char *buffer, size_t size, JSLinearString *str, uint32 quote)
|
||||||
{
|
{
|
||||||
size_t n = PutEscapedStringImpl(buffer, size, NULL, str, quote);
|
size_t n = PutEscapedStringImpl(buffer, size, NULL, str, quote);
|
||||||
|
|
||||||
@ -1021,7 +1071,7 @@ PutEscapedString(char *buffer, size_t size, JSString *str, uint32 quote)
|
|||||||
* will quote the output.
|
* will quote the output.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
FileEscapedString(FILE *fp, JSString *str, uint32 quote)
|
FileEscapedString(FILE *fp, JSLinearString *str, uint32 quote)
|
||||||
{
|
{
|
||||||
return PutEscapedStringImpl(NULL, 0, fp, str, quote) != size_t(-1);
|
return PutEscapedStringImpl(NULL, 0, fp, str, quote) != size_t(-1);
|
||||||
}
|
}
|
||||||
|
@ -42,49 +42,53 @@
|
|||||||
|
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
|
||||||
inline JSString *
|
inline JSFlatString *
|
||||||
JSString::unitString(jschar c)
|
JSString::unitString(jschar c)
|
||||||
{
|
{
|
||||||
JS_ASSERT(c < UNIT_STRING_LIMIT);
|
JS_ASSERT(c < UNIT_STRING_LIMIT);
|
||||||
return const_cast<JSString *>(&unitStringTable[c]);
|
return const_cast<JSString *>(&unitStringTable[c])->assertIsFlat();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSString *
|
inline JSLinearString *
|
||||||
JSString::getUnitString(JSContext *cx, JSString *str, size_t index)
|
JSString::getUnitString(JSContext *cx, JSString *str, size_t index)
|
||||||
{
|
{
|
||||||
JS_ASSERT(index < str->length());
|
JS_ASSERT(index < str->length());
|
||||||
jschar c = str->chars()[index];
|
const jschar *chars = str->getChars(cx);
|
||||||
|
if (!chars)
|
||||||
|
return NULL;
|
||||||
|
jschar c = chars[index];
|
||||||
if (c < UNIT_STRING_LIMIT)
|
if (c < UNIT_STRING_LIMIT)
|
||||||
return unitString(c);
|
return unitString(c);
|
||||||
return js_NewDependentString(cx, str, index, 1);
|
return js_NewDependentString(cx, str, index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSString *
|
inline JSFlatString *
|
||||||
JSString::length2String(jschar c1, jschar c2)
|
JSString::length2String(jschar c1, jschar c2)
|
||||||
{
|
{
|
||||||
JS_ASSERT(fitsInSmallChar(c1));
|
JS_ASSERT(fitsInSmallChar(c1));
|
||||||
JS_ASSERT(fitsInSmallChar(c2));
|
JS_ASSERT(fitsInSmallChar(c2));
|
||||||
return const_cast<JSString *>
|
return const_cast<JSString *> (
|
||||||
(&length2StringTable[(((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2]]);
|
&length2StringTable[(((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2]]
|
||||||
|
)->assertIsFlat();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSString *
|
inline JSFlatString *
|
||||||
JSString::length2String(uint32 i)
|
JSString::length2String(uint32 i)
|
||||||
{
|
{
|
||||||
JS_ASSERT(i < 100);
|
JS_ASSERT(i < 100);
|
||||||
return length2String('0' + i / 10, '0' + i % 10);
|
return length2String('0' + i / 10, '0' + i % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSString *
|
inline JSFlatString *
|
||||||
JSString::intString(jsint i)
|
JSString::intString(jsint i)
|
||||||
{
|
{
|
||||||
jsuint u = jsuint(i);
|
jsuint u = jsuint(i);
|
||||||
JS_ASSERT(u < INT_STRING_LIMIT);
|
JS_ASSERT(u < INT_STRING_LIMIT);
|
||||||
return const_cast<JSString *>(JSString::intStringTable[u]);
|
return const_cast<JSString *>(JSString::intStringTable[u])->assertIsFlat();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a static atomized string for chars if possible. */
|
/* Get a static atomized string for chars if possible. */
|
||||||
inline JSString *
|
inline JSFlatString *
|
||||||
JSString::lookupStaticString(const jschar *chars, size_t length)
|
JSString::lookupStaticString(const jschar *chars, size_t length)
|
||||||
{
|
{
|
||||||
if (length == 1) {
|
if (length == 1) {
|
||||||
@ -125,14 +129,13 @@ JSString::finalize(JSContext *cx) {
|
|||||||
JS_ASSERT(!JSString::isStatic(this));
|
JS_ASSERT(!JSString::isStatic(this));
|
||||||
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
|
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
|
||||||
if (isDependent()) {
|
if (isDependent()) {
|
||||||
JS_ASSERT(dependentBase());
|
|
||||||
JS_RUNTIME_UNMETER(cx->runtime, liveDependentStrings);
|
JS_RUNTIME_UNMETER(cx->runtime, liveDependentStrings);
|
||||||
} else if (isFlat()) {
|
} else if (isFlat()) {
|
||||||
/*
|
/*
|
||||||
* flatChars for stillborn string is null, but cx->free checks
|
* flatChars for stillborn string is null, but cx->free checks
|
||||||
* for a null pointer on its own.
|
* for a null pointer on its own.
|
||||||
*/
|
*/
|
||||||
cx->free(flatChars());
|
cx->free(const_cast<jschar *>(flatChars()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +156,7 @@ JSExternalString::finalize(JSContext *cx)
|
|||||||
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
|
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
|
||||||
|
|
||||||
/* A stillborn string has null chars. */
|
/* A stillborn string has null chars. */
|
||||||
jschar *chars = flatChars();
|
jschar *chars = const_cast<jschar *>(flatChars());
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return;
|
return;
|
||||||
JSStringFinalizeOp finalizer = str_finalizers[externalStringType];
|
JSStringFinalizeOp finalizer = str_finalizers[externalStringType];
|
||||||
|
@ -437,14 +437,14 @@ jitstats_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
if (JSID_IS_STRING(id)) {
|
if (JSID_IS_STRING(id)) {
|
||||||
JSString* str = JSID_TO_STRING(id);
|
JSAtom* str = JSID_TO_ATOM(id);
|
||||||
if (MatchStringAndAscii(str, "HOTLOOP")) {
|
if (StringEqualsAscii(str, "HOTLOOP")) {
|
||||||
*vp = INT_TO_JSVAL(HOTLOOP);
|
*vp = INT_TO_JSVAL(HOTLOOP);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JS_METHODJIT
|
#ifdef JS_METHODJIT
|
||||||
if (MatchStringAndAscii(str, "profiler")) {
|
if (StringEqualsAscii(str, "profiler")) {
|
||||||
*vp = BOOLEAN_TO_JSVAL(cx->profilingEnabled);
|
*vp = BOOLEAN_TO_JSVAL(cx->profilingEnabled);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -910,7 +910,11 @@ PrintOnTrace(char* format, uint32 argc, double *argv)
|
|||||||
// protect against massive spew if u.s is a bad pointer.
|
// protect against massive spew if u.s is a bad pointer.
|
||||||
if (length > 1 << 16)
|
if (length > 1 << 16)
|
||||||
length = 1 << 16;
|
length = 1 << 16;
|
||||||
jschar *chars = u.s->chars();
|
if (u.s->isRope()) {
|
||||||
|
fprintf(out, "<rope>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const jschar *chars = u.s->nonRopeChars();
|
||||||
for (unsigned i = 0; i < length; ++i) {
|
for (unsigned i = 0; i < length; ++i) {
|
||||||
jschar co = chars[i];
|
jschar co = chars[i];
|
||||||
if (co < 128)
|
if (co < 128)
|
||||||
@ -8429,8 +8433,13 @@ TraceRecorder::d2i(LIns* d, bool resultCanBeImpreciseIfFractional)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (ci == &js_StringToNumber_ci) {
|
if (ci == &js_StringToNumber_ci) {
|
||||||
LIns* args[] = { d->callArgN(1), d->callArgN(0) };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
return w.call(&js_StringToInt32_ci, args);
|
LIns* args[] = { ok_ins, d->callArgN(1), d->callArgN(0) };
|
||||||
|
LIns* ret_ins = w.call(&js_StringToInt32_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
return ret_ins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resultCanBeImpreciseIfFractional
|
return resultCanBeImpreciseIfFractional
|
||||||
@ -8646,10 +8655,13 @@ TraceRecorder::switchop()
|
|||||||
w.name(w.eqd(v_ins, w.immd(d)), "guard(switch on numeric)"),
|
w.name(w.eqd(v_ins, w.immd(d)), "guard(switch on numeric)"),
|
||||||
BRANCH_EXIT);
|
BRANCH_EXIT);
|
||||||
} else if (v.isString()) {
|
} else if (v.isString()) {
|
||||||
LIns* args[] = { w.immpStrGC(v.toString()), v_ins };
|
LIns* args[] = { w.immpStrGC(v.toString()), v_ins, cx_ins };
|
||||||
guard(true,
|
LIns* equal_rval = w.call(&js_EqualStringsOnTrace_ci, args);
|
||||||
w.name(w.eqi0(w.eqi0(w.call(&js_EqualStrings_ci, args))),
|
guard(false,
|
||||||
"guard(switch on string)"),
|
w.name(w.eqiN(equal_rval, JS_NEITHER), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(equal_rval), "guard(switch on string)"),
|
||||||
BRANCH_EXIT);
|
BRANCH_EXIT);
|
||||||
} else if (v.isBoolean()) {
|
} else if (v.isBoolean()) {
|
||||||
guard(true,
|
guard(true,
|
||||||
@ -8711,8 +8723,12 @@ TraceRecorder::incHelper(const Value &v, LIns*& v_ins, LIns*& v_after, jsint inc
|
|||||||
if (v.isBoolean()) {
|
if (v.isBoolean()) {
|
||||||
v_ins = w.i2d(v_ins);
|
v_ins = w.i2d(v_ins);
|
||||||
} else if (v.isString()) {
|
} else if (v.isString()) {
|
||||||
LIns* args[] = { v_ins, cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, v_ins, cx_ins };
|
||||||
v_ins = w.call(&js_StringToNumber_ci, args);
|
v_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(v.isNumber());
|
JS_ASSERT(v.isNumber());
|
||||||
}
|
}
|
||||||
@ -8804,14 +8820,18 @@ EvalCmp(LOpcode op, double l, double r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EvalCmp(LOpcode op, JSString* l, JSString* r)
|
EvalCmp(JSContext *cx, LOpcode op, JSString* l, JSString* r, JSBool *ret)
|
||||||
{
|
{
|
||||||
if (op == LIR_eqd)
|
if (op == LIR_eqd)
|
||||||
return !!js_EqualStrings(l, r);
|
return EqualStrings(cx, l, r, ret);
|
||||||
return EvalCmp(op, js_CompareStrings(l, r), 0);
|
JSBool cmp;
|
||||||
|
if (!CompareStrings(cx, l, r, &cmp))
|
||||||
|
return false;
|
||||||
|
*ret = EvalCmp(op, cmp, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK void
|
JS_REQUIRES_STACK RecordingStatus
|
||||||
TraceRecorder::strictEquality(bool equal, bool cmpCase)
|
TraceRecorder::strictEquality(bool equal, bool cmpCase)
|
||||||
{
|
{
|
||||||
Value& r = stackval(-1);
|
Value& r = stackval(-1);
|
||||||
@ -8819,16 +8839,21 @@ TraceRecorder::strictEquality(bool equal, bool cmpCase)
|
|||||||
LIns* l_ins = get(&l);
|
LIns* l_ins = get(&l);
|
||||||
LIns* r_ins = get(&r);
|
LIns* r_ins = get(&r);
|
||||||
LIns* x;
|
LIns* x;
|
||||||
bool cond;
|
JSBool cond;
|
||||||
|
|
||||||
JSValueType ltag = getPromotedType(l);
|
JSValueType ltag = getPromotedType(l);
|
||||||
if (ltag != getPromotedType(r)) {
|
if (ltag != getPromotedType(r)) {
|
||||||
cond = !equal;
|
cond = !equal;
|
||||||
x = w.immi(cond);
|
x = w.immi(cond);
|
||||||
} else if (ltag == JSVAL_TYPE_STRING) {
|
} else if (ltag == JSVAL_TYPE_STRING) {
|
||||||
LIns* args[] = { r_ins, l_ins };
|
LIns* args[] = { r_ins, l_ins, cx_ins };
|
||||||
x = w.eqiN(w.call(&js_EqualStrings_ci, args), equal);
|
LIns* equal_ins = w.call(&js_EqualStringsOnTrace_ci, args);
|
||||||
cond = !!js_EqualStrings(l.toString(), r.toString());
|
guard(false,
|
||||||
|
w.name(w.eqiN(equal_ins, JS_NEITHER), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
x = w.eqiN(equal_ins, equal);
|
||||||
|
if (!EqualStrings(cx, l.toString(), r.toString(), &cond))
|
||||||
|
RETURN_ERROR("oom");
|
||||||
} else {
|
} else {
|
||||||
if (ltag == JSVAL_TYPE_DOUBLE)
|
if (ltag == JSVAL_TYPE_DOUBLE)
|
||||||
x = w.eqd(l_ins, r_ins);
|
x = w.eqd(l_ins, r_ins);
|
||||||
@ -8848,10 +8873,11 @@ TraceRecorder::strictEquality(bool equal, bool cmpCase)
|
|||||||
/* Only guard if the same path may not always be taken. */
|
/* Only guard if the same path may not always be taken. */
|
||||||
if (!x->isImmI())
|
if (!x->isImmI())
|
||||||
guard(cond, x, BRANCH_EXIT);
|
guard(cond, x, BRANCH_EXIT);
|
||||||
return;
|
return RECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
set(&l, x);
|
set(&l, x);
|
||||||
|
return RECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
@ -8871,8 +8897,8 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins,
|
|||||||
Value& rval)
|
Value& rval)
|
||||||
{
|
{
|
||||||
LOpcode op = LIR_eqi;
|
LOpcode op = LIR_eqi;
|
||||||
bool cond;
|
JSBool cond;
|
||||||
LIns* args[] = { NULL, NULL };
|
LIns* args[] = { NULL, NULL, NULL };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The if chain below closely mirrors that found in 11.9.3, in general
|
* The if chain below closely mirrors that found in 11.9.3, in general
|
||||||
@ -8913,11 +8939,16 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins,
|
|||||||
l_ins = w.getStringChar(l_ins, w.immpNonGC(0));
|
l_ins = w.getStringChar(l_ins, w.immpNonGC(0));
|
||||||
r_ins = w.getStringChar(r_ins, w.immpNonGC(0));
|
r_ins = w.getStringChar(r_ins, w.immpNonGC(0));
|
||||||
} else {
|
} else {
|
||||||
args[0] = r_ins, args[1] = l_ins;
|
args[0] = r_ins, args[1] = l_ins, args[2] = cx_ins;
|
||||||
l_ins = w.call(&js_EqualStrings_ci, args);
|
LIns *equal_ins = w.call(&js_EqualStringsOnTrace_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqiN(equal_ins, JS_NEITHER), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
l_ins = equal_ins;
|
||||||
r_ins = w.immi(1);
|
r_ins = w.immi(1);
|
||||||
}
|
}
|
||||||
cond = !!js_EqualStrings(l.toString(), r.toString());
|
if (!EqualStrings(cx, l.toString(), r.toString(), &cond))
|
||||||
|
RETURN_ERROR_A("oom");
|
||||||
} else {
|
} else {
|
||||||
JS_ASSERT(l.isNumber() && r.isNumber());
|
JS_ASSERT(l.isNumber() && r.isNumber());
|
||||||
cond = (l.toNumber() == r.toNumber());
|
cond = (l.toNumber() == r.toNumber());
|
||||||
@ -8930,14 +8961,30 @@ TraceRecorder::equalityHelper(Value& l, Value& r, LIns* l_ins, LIns* r_ins,
|
|||||||
r_ins = w.immiUndefined();
|
r_ins = w.immiUndefined();
|
||||||
cond = true;
|
cond = true;
|
||||||
} else if (l.isNumber() && r.isString()) {
|
} else if (l.isNumber() && r.isString()) {
|
||||||
args[0] = r_ins, args[1] = cx_ins;
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
args[0] = ok_ins, args[1] = r_ins, args[2] = cx_ins;
|
||||||
r_ins = w.call(&js_StringToNumber_ci, args);
|
r_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
cond = (l.toNumber() == js_StringToNumber(cx, r.toString()));
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
JSBool ok;
|
||||||
|
double d = js_StringToNumber(cx, r.toString(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
RETURN_ERROR_A("oom");
|
||||||
|
cond = (l.toNumber() == d);
|
||||||
op = LIR_eqd;
|
op = LIR_eqd;
|
||||||
} else if (l.isString() && r.isNumber()) {
|
} else if (l.isString() && r.isNumber()) {
|
||||||
args[0] = l_ins, args[1] = cx_ins;
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
args[0] = ok_ins, args[1] = l_ins, args[2] = cx_ins;
|
||||||
l_ins = w.call(&js_StringToNumber_ci, args);
|
l_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
cond = (js_StringToNumber(cx, l.toString()) == r.toNumber());
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
JSBool ok;
|
||||||
|
double d = js_StringToNumber(cx, l.toString(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
RETURN_ERROR_A("oom");
|
||||||
|
cond = (d == r.toNumber());
|
||||||
op = LIR_eqd;
|
op = LIR_eqd;
|
||||||
} else {
|
} else {
|
||||||
// Below we may assign to l or r, which modifies the interpreter state.
|
// Below we may assign to l or r, which modifies the interpreter state.
|
||||||
@ -9011,7 +9058,7 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond)
|
|||||||
Value& r = stackval(-1);
|
Value& r = stackval(-1);
|
||||||
Value& l = stackval(-2);
|
Value& l = stackval(-2);
|
||||||
LIns* x = NULL;
|
LIns* x = NULL;
|
||||||
bool cond;
|
JSBool cond;
|
||||||
LIns* l_ins = get(&l);
|
LIns* l_ins = get(&l);
|
||||||
LIns* r_ins = get(&r);
|
LIns* r_ins = get(&r);
|
||||||
bool fp = false;
|
bool fp = false;
|
||||||
@ -9037,22 +9084,31 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond)
|
|||||||
|
|
||||||
/* 11.8.5 steps 3, 16-21. */
|
/* 11.8.5 steps 3, 16-21. */
|
||||||
if (l.isString() && r.isString()) {
|
if (l.isString() && r.isString()) {
|
||||||
LIns* args[] = { r_ins, l_ins };
|
LIns* args[] = { r_ins, l_ins, cx_ins };
|
||||||
l_ins = w.call(&js_CompareStrings_ci, args);
|
LIns* result_ins = w.call(&js_CompareStringsOnTrace_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqiN(result_ins, INT32_MIN), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
l_ins = result_ins;
|
||||||
r_ins = w.immi(0);
|
r_ins = w.immi(0);
|
||||||
cond = EvalCmp(op, l.toString(), r.toString());
|
if (!EvalCmp(cx, op, l.toString(), r.toString(), &cond))
|
||||||
|
RETURN_ERROR_A("oom");
|
||||||
goto do_comparison;
|
goto do_comparison;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 11.8.5 steps 4-5. */
|
/* 11.8.5 steps 4-5. */
|
||||||
if (!l.isNumber()) {
|
if (!l.isNumber()) {
|
||||||
LIns* args[] = { l_ins, cx_ins };
|
|
||||||
if (l.isBoolean()) {
|
if (l.isBoolean()) {
|
||||||
l_ins = w.i2d(l_ins);
|
l_ins = w.i2d(l_ins);
|
||||||
} else if (l.isUndefined()) {
|
} else if (l.isUndefined()) {
|
||||||
l_ins = w.immd(js_NaN);
|
l_ins = w.immd(js_NaN);
|
||||||
} else if (l.isString()) {
|
} else if (l.isString()) {
|
||||||
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, l_ins, cx_ins };
|
||||||
l_ins = w.call(&js_StringToNumber_ci, args);
|
l_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
} else if (l.isNull()) {
|
} else if (l.isNull()) {
|
||||||
l_ins = w.immd(0.0);
|
l_ins = w.immd(0.0);
|
||||||
} else {
|
} else {
|
||||||
@ -9062,13 +9118,17 @@ TraceRecorder::relational(LOpcode op, bool tryBranchAfterCond)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!r.isNumber()) {
|
if (!r.isNumber()) {
|
||||||
LIns* args[] = { r_ins, cx_ins };
|
|
||||||
if (r.isBoolean()) {
|
if (r.isBoolean()) {
|
||||||
r_ins = w.i2d(r_ins);
|
r_ins = w.i2d(r_ins);
|
||||||
} else if (r.isUndefined()) {
|
} else if (r.isUndefined()) {
|
||||||
r_ins = w.immd(js_NaN);
|
r_ins = w.immd(js_NaN);
|
||||||
} else if (r.isString()) {
|
} else if (r.isString()) {
|
||||||
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, r_ins, cx_ins };
|
||||||
r_ins = w.call(&js_StringToNumber_ci, args);
|
r_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
} else if (r.isNull()) {
|
} else if (r.isNull()) {
|
||||||
r_ins = w.immd(0.0);
|
r_ins = w.immd(0.0);
|
||||||
} else {
|
} else {
|
||||||
@ -9176,16 +9236,30 @@ TraceRecorder::binary(LOpcode op)
|
|||||||
|
|
||||||
if (l.isString()) {
|
if (l.isString()) {
|
||||||
NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD()
|
NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD()
|
||||||
LIns* args[] = { a, cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, a, cx_ins };
|
||||||
a = w.call(&js_StringToNumber_ci, args);
|
a = w.call(&js_StringToNumber_ci, args);
|
||||||
lnum = js_StringToNumber(cx, l.toString());
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
JSBool ok;
|
||||||
|
lnum = js_StringToNumber(cx, l.toString(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
RETURN_ERROR("oom");
|
||||||
leftIsNumber = true;
|
leftIsNumber = true;
|
||||||
}
|
}
|
||||||
if (r.isString()) {
|
if (r.isString()) {
|
||||||
NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD()
|
NanoAssert(op != LIR_addd); // LIR_addd/IS_STRING case handled by record_JSOP_ADD()
|
||||||
LIns* args[] = { b, cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, b, cx_ins };
|
||||||
b = w.call(&js_StringToNumber_ci, args);
|
b = w.call(&js_StringToNumber_ci, args);
|
||||||
rnum = js_StringToNumber(cx, r.toString());
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
JSBool ok;
|
||||||
|
rnum = js_StringToNumber(cx, r.toString(), &ok);
|
||||||
|
if (!ok)
|
||||||
|
RETURN_ERROR("oom");
|
||||||
rightIsNumber = true;
|
rightIsNumber = true;
|
||||||
}
|
}
|
||||||
if (l.isBoolean()) {
|
if (l.isBoolean()) {
|
||||||
@ -10706,8 +10780,13 @@ TraceRecorder::record_JSOP_NEG()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v.isString()) {
|
if (v.isString()) {
|
||||||
LIns* args[] = { get(&v), cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
set(&v, w.negd(w.call(&js_StringToNumber_ci, args)));
|
LIns* args[] = { ok_ins, get(&v), cx_ins };
|
||||||
|
LIns* num_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
set(&v, w.negd(num_ins));
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10739,8 +10818,13 @@ TraceRecorder::record_JSOP_POS()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (v.isString()) {
|
if (v.isString()) {
|
||||||
LIns* args[] = { get(&v), cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
set(&v, w.call(&js_StringToNumber_ci, args));
|
LIns* args[] = { ok_ins, get(&v), cx_ins };
|
||||||
|
LIns* num_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
|
set(&v, num_ins);
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12425,7 +12509,9 @@ TraceRecorder::getCharCodeAt(JSString *str, LIns* str_ins, LIns* idx_ins, LIns**
|
|||||||
LIns *lengthAndFlags_ins = w.ldpStringLengthAndFlags(str_ins);
|
LIns *lengthAndFlags_ins = w.ldpStringLengthAndFlags(str_ins);
|
||||||
if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins, w.nameImmw(JSString::ROPE_BIT)))))
|
if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins, w.nameImmw(JSString::ROPE_BIT)))))
|
||||||
{
|
{
|
||||||
w.call(&js_Flatten_ci, &str_ins);
|
LIns *args[] = { str_ins, cx_ins };
|
||||||
|
LIns *ok_ins = w.call(&js_Flatten_ci, args);
|
||||||
|
guard(false, w.eqi0(ok_ins), OOM_EXIT);
|
||||||
w.label(mbr);
|
w.label(mbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12457,7 +12543,9 @@ TraceRecorder::getCharAt(JSString *str, LIns* str_ins, LIns* idx_ins, JSOp mode,
|
|||||||
if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins,
|
if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins,
|
||||||
w.nameImmw(JSString::ROPE_BIT)))))
|
w.nameImmw(JSString::ROPE_BIT)))))
|
||||||
{
|
{
|
||||||
w.call(&js_Flatten_ci, &str_ins);
|
LIns *args[] = { str_ins, cx_ins };
|
||||||
|
LIns *ok_ins = w.call(&js_Flatten_ci, args);
|
||||||
|
guard(false, w.eqi0(ok_ins), OOM_EXIT);
|
||||||
w.label(mbr);
|
w.label(mbr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12827,8 +12915,12 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
|
|||||||
} else if (v.isUndefined()) {
|
} else if (v.isUndefined()) {
|
||||||
typed_v_ins = w.immd(js_NaN);
|
typed_v_ins = w.immd(js_NaN);
|
||||||
} else if (v.isString()) {
|
} else if (v.isString()) {
|
||||||
LIns* args[] = { typed_v_ins, cx_ins };
|
LIns* ok_ins = w.allocp(sizeof(JSBool));
|
||||||
|
LIns* args[] = { ok_ins, typed_v_ins, cx_ins };
|
||||||
typed_v_ins = w.call(&js_StringToNumber_ci, args);
|
typed_v_ins = w.call(&js_StringToNumber_ci, args);
|
||||||
|
guard(false,
|
||||||
|
w.name(w.eqi0(w.ldiAlloc(ok_ins)), "guard(oom)"),
|
||||||
|
OOM_EXIT);
|
||||||
} else if (v.isBoolean()) {
|
} else if (v.isBoolean()) {
|
||||||
JS_ASSERT(v.isBoolean());
|
JS_ASSERT(v.isBoolean());
|
||||||
typed_v_ins = w.i2d(typed_v_ins);
|
typed_v_ins = w.i2d(typed_v_ins);
|
||||||
@ -14025,14 +14117,14 @@ TraceRecorder::record_JSOP_LOOKUPSWITCH()
|
|||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
TraceRecorder::record_JSOP_STRICTEQ()
|
TraceRecorder::record_JSOP_STRICTEQ()
|
||||||
{
|
{
|
||||||
strictEquality(true, false);
|
CHECK_STATUS_A(strictEquality(true, false));
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
TraceRecorder::record_JSOP_STRICTNE()
|
TraceRecorder::record_JSOP_STRICTNE()
|
||||||
{
|
{
|
||||||
strictEquality(false, false);
|
CHECK_STATUS_A(strictEquality(false, false));
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14937,7 +15029,7 @@ TraceRecorder::record_JSOP_CONDSWITCH()
|
|||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
TraceRecorder::record_JSOP_CASE()
|
TraceRecorder::record_JSOP_CASE()
|
||||||
{
|
{
|
||||||
strictEquality(true, true);
|
CHECK_STATUS_A(strictEquality(true, true));
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15315,7 +15407,7 @@ TraceRecorder::record_JSOP_GOSUBX()
|
|||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
TraceRecorder::record_JSOP_CASEX()
|
TraceRecorder::record_JSOP_CASEX()
|
||||||
{
|
{
|
||||||
strictEquality(true, true);
|
CHECK_STATUS_A(strictEquality(true, true));
|
||||||
return ARECORD_CONTINUE;
|
return ARECORD_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,7 +1300,7 @@ class TraceRecorder
|
|||||||
JS_REQUIRES_STACK RecordingStatus incElem(jsint incr, bool pre = true);
|
JS_REQUIRES_STACK RecordingStatus incElem(jsint incr, bool pre = true);
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus incName(jsint incr, bool pre = true);
|
JS_REQUIRES_STACK AbortableRecordingStatus incName(jsint incr, bool pre = true);
|
||||||
|
|
||||||
JS_REQUIRES_STACK void strictEquality(bool equal, bool cmpCase);
|
JS_REQUIRES_STACK RecordingStatus strictEquality(bool equal, bool cmpCase);
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus equality(bool negate, bool tryBranchAfterCond);
|
JS_REQUIRES_STACK AbortableRecordingStatus equality(bool negate, bool tryBranchAfterCond);
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus equalityHelper(Value& l, Value& r,
|
JS_REQUIRES_STACK AbortableRecordingStatus equalityHelper(Value& l, Value& r,
|
||||||
nanojit::LIns* l_ins, nanojit::LIns* r_ins,
|
nanojit::LIns* l_ins, nanojit::LIns* r_ins,
|
||||||
|
@ -357,10 +357,11 @@ PodArrayZero(T (&t)[N])
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
JS_ALWAYS_INLINE static void
|
JS_ALWAYS_INLINE static void
|
||||||
PodCopy(T *dst, T *src, size_t nelem)
|
PodCopy(T *dst, const T *src, size_t nelem)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(abs(dst - src) >= ptrdiff_t(nelem));
|
||||||
if (nelem < 128) {
|
if (nelem < 128) {
|
||||||
for (T *srcend = src + nelem; src != srcend; ++src, ++dst)
|
for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
} else {
|
} else {
|
||||||
memcpy(dst, src, nelem * sizeof(T));
|
memcpy(dst, src, nelem * sizeof(T));
|
||||||
|
@ -352,7 +352,7 @@ typedef union jsval_layout
|
|||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||||
{
|
{
|
||||||
return (uint32)l.s.tag < (uint32)JSVAL_TAG_CLEAR;
|
return (uint32)l.s.tag <= (uint32)JSVAL_TAG_CLEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE jsval_layout
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
@ -265,6 +265,10 @@ class Vector : AllocPolicy
|
|||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
|
|
||||||
|
const AllocPolicy &allocPolicy() const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
enum { InlineLength = N };
|
enum { InlineLength = N };
|
||||||
|
|
||||||
size_t length() const {
|
size_t length() const {
|
||||||
|
@ -456,13 +456,12 @@ JS_XDRString(JSXDRState *xdr, JSString **strp)
|
|||||||
if (!JS_XDRUint32(xdr, &nchars))
|
if (!JS_XDRUint32(xdr, &nchars))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
if (xdr->mode == JSXDR_DECODE) {
|
if (xdr->mode == JSXDR_DECODE)
|
||||||
chars = (jschar *) xdr->cx->malloc((nchars + 1) * sizeof(jschar));
|
chars = (jschar *) xdr->cx->malloc((nchars + 1) * sizeof(jschar));
|
||||||
if (!chars)
|
else
|
||||||
return JS_FALSE;
|
chars = const_cast<jschar *>((*strp)->getChars(xdr->cx));
|
||||||
} else {
|
if (!chars)
|
||||||
chars = (*strp)->chars();
|
return JS_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
if (!XDRChars(xdr, chars, nchars))
|
if (!XDRChars(xdr, chars, nchars))
|
||||||
goto bad;
|
goto bad;
|
||||||
|
595
js/src/jsxml.cpp
595
js/src/jsxml.cpp
File diff suppressed because it is too large
Load Diff
@ -312,7 +312,7 @@ js_IsXMLName(JSContext *cx, jsval v);
|
|||||||
extern JSBool
|
extern JSBool
|
||||||
js_ToAttributeName(JSContext *cx, js::Value *vp);
|
js_ToAttributeName(JSContext *cx, js::Value *vp);
|
||||||
|
|
||||||
extern JSString *
|
extern JSLinearString *
|
||||||
js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
|
js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
|
||||||
|
|
||||||
extern JSString *
|
extern JSString *
|
||||||
|
@ -2830,7 +2830,8 @@ mjit::Compiler::compareTwoValues(JSContext *cx, JSOp op, const Value &lhs, const
|
|||||||
JS_ASSERT(rhs.isPrimitive());
|
JS_ASSERT(rhs.isPrimitive());
|
||||||
|
|
||||||
if (lhs.isString() && rhs.isString()) {
|
if (lhs.isString() && rhs.isString()) {
|
||||||
int cmp = js_CompareStrings(lhs.toString(), rhs.toString());
|
int32 cmp;
|
||||||
|
CompareStrings(cx, lhs.toString(), rhs.toString(), &cmp);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case JSOP_LT:
|
case JSOP_LT:
|
||||||
return cmp < 0;
|
return cmp < 0;
|
||||||
|
@ -1562,7 +1562,8 @@ mjit::Compiler::jsop_stricteq(JSOp op)
|
|||||||
|
|
||||||
/* Constant-fold. */
|
/* Constant-fold. */
|
||||||
if (lhs->isConstant() && rhs->isConstant()) {
|
if (lhs->isConstant() && rhs->isConstant()) {
|
||||||
bool b = StrictlyEqual(cx, lhs->getValue(), rhs->getValue());
|
JSBool b;
|
||||||
|
StrictlyEqual(cx, lhs->getValue(), rhs->getValue(), &b);
|
||||||
frame.popn(2);
|
frame.popn(2);
|
||||||
frame.push(BooleanValue((op == JSOP_STRICTEQ) ? b : !b));
|
frame.push(BooleanValue((op == JSOP_STRICTEQ) ? b : !b));
|
||||||
return;
|
return;
|
||||||
|
@ -2136,7 +2136,7 @@ GetElementIC::attachGetProp(JSContext *cx, JSObject *obj, const Value &v, jsid i
|
|||||||
|
|
||||||
CodeLocationLabel cs = buffer.finalize();
|
CodeLocationLabel cs = buffer.finalize();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
char *chars = js_DeflateString(cx, v.toString()->chars(), v.toString()->length());
|
char *chars = js_DeflateString(cx, v.toString()->nonRopeChars(), v.toString()->length());
|
||||||
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n",
|
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom 0x%x (\"%s\") shape 0x%x (%s: %d)\n",
|
||||||
js_CodeName[op], cs.executableAddress(), id, chars, holder->shape(),
|
js_CodeName[op], cs.executableAddress(), id, chars, holder->shape(),
|
||||||
cx->fp()->script()->filename, js_FramePCToLineNumber(cx, cx->fp()));
|
cx->fp()->script()->filename, js_FramePCToLineNumber(cx, cx->fp()));
|
||||||
|
@ -940,7 +940,10 @@ template void JS_FASTCALL stubs::DefFun<false>(VMFrame &f, JSFunction *fun);
|
|||||||
DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
|
DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
|
||||||
if (lval.isString() && rval.isString()) { \
|
if (lval.isString() && rval.isString()) { \
|
||||||
JSString *l = lval.toString(), *r = rval.toString(); \
|
JSString *l = lval.toString(), *r = rval.toString(); \
|
||||||
cond = js_CompareStrings(l, r) OP 0; \
|
JSBool cmp; \
|
||||||
|
if (!CompareStrings(cx, l, r, &cmp)) \
|
||||||
|
THROWV(JS_FALSE); \
|
||||||
|
cond = cmp OP 0; \
|
||||||
} else { \
|
} else { \
|
||||||
double l, r; \
|
double l, r; \
|
||||||
if (!ValueToNumber(cx, lval, &l) || \
|
if (!ValueToNumber(cx, lval, &l) || \
|
||||||
@ -1006,7 +1009,10 @@ StubEqualityOp(VMFrame &f)
|
|||||||
if (lval.isString() && rval.isString()) {
|
if (lval.isString() && rval.isString()) {
|
||||||
JSString *l = lval.toString();
|
JSString *l = lval.toString();
|
||||||
JSString *r = rval.toString();
|
JSString *r = rval.toString();
|
||||||
cond = js_EqualStrings(l, r) == EQ;
|
JSBool equal;
|
||||||
|
if (!EqualStrings(cx, l, r, &equal))
|
||||||
|
return false;
|
||||||
|
cond = equal == EQ;
|
||||||
} else
|
} else
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
if ((lval.isObject() && lval.toObject().isXML()) ||
|
if ((lval.isObject() && lval.toObject().isXML()) ||
|
||||||
@ -1066,7 +1072,10 @@ StubEqualityOp(VMFrame &f)
|
|||||||
if (lval.isString() && rval.isString()) {
|
if (lval.isString() && rval.isString()) {
|
||||||
JSString *l = lval.toString();
|
JSString *l = lval.toString();
|
||||||
JSString *r = rval.toString();
|
JSString *r = rval.toString();
|
||||||
cond = js_EqualStrings(l, r) == EQ;
|
JSBool equal;
|
||||||
|
if (!EqualStrings(cx, l, r, &equal))
|
||||||
|
return false;
|
||||||
|
cond = equal == EQ;
|
||||||
} else {
|
} else {
|
||||||
double l, r;
|
double l, r;
|
||||||
if (!ValueToNumber(cx, lval, &l) ||
|
if (!ValueToNumber(cx, lval, &l) ||
|
||||||
@ -2302,9 +2311,11 @@ stubs::StrictEq(VMFrame &f)
|
|||||||
{
|
{
|
||||||
const Value &rhs = f.regs.sp[-1];
|
const Value &rhs = f.regs.sp[-1];
|
||||||
const Value &lhs = f.regs.sp[-2];
|
const Value &lhs = f.regs.sp[-2];
|
||||||
const bool b = StrictlyEqual(f.cx, lhs, rhs) == true;
|
JSBool equal;
|
||||||
|
if (!StrictlyEqual(f.cx, lhs, rhs, &equal))
|
||||||
|
THROW();
|
||||||
f.regs.sp--;
|
f.regs.sp--;
|
||||||
f.regs.sp[-1].setBoolean(b);
|
f.regs.sp[-1].setBoolean(equal == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JS_FASTCALL
|
void JS_FASTCALL
|
||||||
@ -2312,9 +2323,11 @@ stubs::StrictNe(VMFrame &f)
|
|||||||
{
|
{
|
||||||
const Value &rhs = f.regs.sp[-1];
|
const Value &rhs = f.regs.sp[-1];
|
||||||
const Value &lhs = f.regs.sp[-2];
|
const Value &lhs = f.regs.sp[-2];
|
||||||
const bool b = StrictlyEqual(f.cx, lhs, rhs) != true;
|
JSBool equal;
|
||||||
|
if (!StrictlyEqual(f.cx, lhs, rhs, &equal))
|
||||||
|
THROW();
|
||||||
f.regs.sp--;
|
f.regs.sp--;
|
||||||
f.regs.sp[-1].setBoolean(b);
|
f.regs.sp[-1].setBoolean(equal != true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JS_FASTCALL
|
void JS_FASTCALL
|
||||||
@ -2487,13 +2500,15 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
|
|||||||
JS_ASSERT(npairs);
|
JS_ASSERT(npairs);
|
||||||
|
|
||||||
if (lval.isString()) {
|
if (lval.isString()) {
|
||||||
JSString *str = lval.toString();
|
JSLinearString *str = lval.toString()->ensureLinear(f.cx);
|
||||||
|
if (!str)
|
||||||
|
THROWV(NULL);
|
||||||
for (uint32 i = 1; i <= npairs; i++) {
|
for (uint32 i = 1; i <= npairs; i++) {
|
||||||
Value rval = script->getConst(GET_INDEX(pc));
|
Value rval = script->getConst(GET_INDEX(pc));
|
||||||
pc += INDEX_LEN;
|
pc += INDEX_LEN;
|
||||||
if (rval.isString()) {
|
if (rval.isString()) {
|
||||||
JSString *rhs = rval.toString();
|
JSLinearString *rhs = rval.toString()->assertIsLinear();
|
||||||
if (rhs == str || js_EqualStrings(str, rhs)) {
|
if (rhs == str || EqualStrings(str, rhs)) {
|
||||||
void* native = script->nativeCodeForPC(ctor,
|
void* native = script->nativeCodeForPC(ctor,
|
||||||
jpc + GET_JUMP_OFFSET(pc));
|
jpc + GET_JUMP_OFFSET(pc));
|
||||||
JS_ASSERT(native);
|
JS_ASSERT(native);
|
||||||
|
@ -3402,7 +3402,12 @@ EvalInFrame(JSContext *cx, uintN argc, jsval *vp)
|
|||||||
if (saveCurrent)
|
if (saveCurrent)
|
||||||
oldfp = JS_SaveFrameChain(cx);
|
oldfp = JS_SaveFrameChain(cx);
|
||||||
|
|
||||||
JSBool ok = JS_EvaluateUCInStackFrame(cx, fp, str->chars(), str->length(),
|
size_t length;
|
||||||
|
const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
|
||||||
|
if (!chars)
|
||||||
|
return JS_FALSE;
|
||||||
|
|
||||||
|
JSBool ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length,
|
||||||
fp->script()->filename,
|
fp->script()->filename,
|
||||||
JS_PCToLineNumber(cx, fp->script(),
|
JS_PCToLineNumber(cx, fp->script(),
|
||||||
fi.pc()),
|
fi.pc()),
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
#include "jstl.h"
|
#include "jstl.h"
|
||||||
|
|
||||||
typedef jschar UChar;
|
typedef jschar UChar;
|
||||||
typedef JSString UString;
|
typedef JSLinearString UString;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ValueDeleter
|
class ValueDeleter
|
||||||
|
Loading…
Reference in New Issue
Block a user