Bug 891107 - Part 11: Show information about type in cast error messages in js-ctypes. r=jorendorff

This commit is contained in:
Tooru Fujisawa 2015-08-07 06:58:58 +09:00
Родитель f7870cdfc9
Коммит 0dd2a12852
4 изменённых файлов: 75 добавлений и 9 удалений

Просмотреть файл

@ -1827,6 +1827,55 @@ TypeOverflow(JSContext* cx, const char* expected, HandleValue actual)
return false;
}
static bool
UndefinedSizeCastError(JSContext* cx, HandleObject targetTypeObj)
{
AutoString targetTypeSource;
JSAutoByteString targetTypeBytes;
BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
const char* targetTypeStr = EncodeLatin1(cx, targetTypeSource,
targetTypeBytes);
if (!targetTypeStr)
return false;
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
CTYPESMSG_UNDEFINED_SIZE_CAST, targetTypeStr);
return false;
}
static bool
SizeMismatchCastError(JSContext* cx,
HandleObject sourceTypeObj, HandleObject targetTypeObj,
size_t sourceSize, size_t targetSize)
{
AutoString sourceTypeSource;
JSAutoByteString sourceTypeBytes;
BuildTypeSource(cx, sourceTypeObj, true, sourceTypeSource);
const char* sourceTypeStr = EncodeLatin1(cx, sourceTypeSource,
sourceTypeBytes);
if (!sourceTypeStr)
return false;
AutoString targetTypeSource;
JSAutoByteString targetTypeBytes;
BuildTypeSource(cx, targetTypeObj, true, targetTypeSource);
const char* targetTypeStr = EncodeLatin1(cx, targetTypeSource,
targetTypeBytes);
if (!targetTypeStr)
return false;
char sourceSizeStr[16];
char targetSizeStr[16];
JS_snprintf(sourceSizeStr, 16, "%u", sourceSize);
JS_snprintf(targetSizeStr, 16, "%u", targetSize);
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
CTYPESMSG_SIZE_MISMATCH_CAST,
targetTypeStr, sourceTypeStr,
targetSizeStr, sourceSizeStr);
return false;
}
static bool
UndefinedSizePointerError(JSContext* cx, const char* action, HandleObject obj)
{
@ -7667,7 +7716,7 @@ CData::Cast(JSContext* cx, unsigned argc, Value* vp)
return ArgumentTypeMismatch(cx, "first ", "ctypes.cast", "a CData");
}
RootedObject sourceData(cx, &args[0].toObject());
JSObject* sourceType = CData::GetCType(sourceData);
RootedObject sourceType(cx, CData::GetCType(sourceData));
if (args[1].isPrimitive() || !CType::IsCType(&args[1].toObject())) {
return ArgumentTypeMismatch(cx, "second ", "ctypes.cast", "a CType");
@ -7675,11 +7724,12 @@ CData::Cast(JSContext* cx, unsigned argc, Value* vp)
RootedObject targetType(cx, &args[1].toObject());
size_t targetSize;
if (!CType::GetSafeSize(targetType, &targetSize) ||
targetSize > CType::GetSize(sourceType)) {
JS_ReportError(cx,
"target CType has undefined or larger size than source CType");
return false;
if (!CType::GetSafeSize(targetType, &targetSize)) {
return UndefinedSizeCastError(cx, targetType);
}
if (targetSize > CType::GetSize(sourceType)) {
return SizeMismatchCastError(cx, sourceType, targetType,
CType::GetSize(sourceType), targetSize);
}
// Construct a new CData object with a type of 'targetType' and a referent

Просмотреть файл

@ -70,3 +70,7 @@ MSG_DEF(CTYPESMSG_CANNOT_CONSTRUCT,1, JSEXN_TYPEERR, "cannot construct from {0}"
MSG_DEF(CTYPESMSG_UNDEFINED_SIZE,2, JSEXN_TYPEERR, "cannot {0} pointer of undefined size {1}")
MSG_DEF(CTYPESMSG_NULL_POINTER, 2, JSEXN_TYPEERR, "cannot {0} null pointer {1}")
MSG_DEF(CTYPESMSG_NON_STRING_BASE,1, JSEXN_TYPEERR, "base type {0} is not an 8-bit or 16-bit integer or character type")
/* cast */
MSG_DEF(CTYPESMSG_UNDEFINED_SIZE_CAST,1, JSEXN_TYPEERR, "target type {0} has undefined size")
MSG_DEF(CTYPESMSG_SIZE_MISMATCH_CAST,4, JSEXN_TYPEERR, "target type {0} has larger size than source type {1} ({2} > {3})")

Просмотреть файл

@ -0,0 +1,12 @@
load(libdir + 'asserts.js');
function test() {
assertTypeErrorMessage(() => { ctypes.cast(ctypes.int32_t(0), ctypes.StructType("foo")); },
"target type foo has undefined size");
assertTypeErrorMessage(() => { ctypes.cast(ctypes.int32_t(0), ctypes.StructType("foo", [ { x: ctypes.int32_t }, { y: ctypes.int32_t } ])); },
"target type foo has larger size than source type ctypes.int32_t (8 > 4)");
}
if (typeof ctypes === "object")
test();

Просмотреть файл

@ -2204,9 +2204,9 @@ function run_cast_tests() {
do_check_eq(i.value, k.value);
// Test casting to a type of undefined or larger size.
do_check_throws(function() { ctypes.cast(i, ctypes.void_t); }, Error);
do_check_throws(function() { ctypes.cast(i, ctypes.int32_t.array()); }, Error);
do_check_throws(function() { ctypes.cast(i, ctypes.int64_t); }, Error);
do_check_throws(function() { ctypes.cast(i, ctypes.void_t); }, TypeError);
do_check_throws(function() { ctypes.cast(i, ctypes.int32_t.array()); }, TypeError);
do_check_throws(function() { ctypes.cast(i, ctypes.int64_t); }, TypeError);
// Test casting between special types.
let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]);