jscript: Implement DataView getters.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
Gabriel Ivăncescu 2024-02-12 17:47:11 +02:00 committed by Alexandre Julliard
parent 556e3349ab
commit aa2bd097d6
2 changed files with 219 additions and 5 deletions

View file

@ -236,6 +236,45 @@ static inline void copy_type_data(void *dst, const void *src, unsigned type_size
out[i] = in[type_size - i - 1];
}
static HRESULT get_data(script_ctx_t *ctx, jsval_t vthis, unsigned argc, jsval_t *argv, unsigned type_size, void *ret)
{
BOOL little_endian = FALSE;
DataViewInstance *view;
HRESULT hres;
DWORD offset;
BYTE *data;
double n;
if(!(view = dataview_this(vthis)))
return JS_E_NOT_DATAVIEW;
if(!argc || is_undefined(argv[0]))
return JS_E_DATAVIEW_NO_ARGUMENT;
hres = to_integer(ctx, argv[0], &n);
if(FAILED(hres))
return hres;
if(n < 0.0 || n + type_size > view->size)
return JS_E_DATAVIEW_INVALID_ACCESS;
offset = n;
data = &view->buffer->buf[view->offset + offset];
if(type_size == 1) {
*(BYTE*)ret = data[0];
return S_OK;
}
if(argc > 1) {
hres = to_boolean(argv[1], &little_endian);
if(FAILED(hres))
return hres;
}
copy_type_data(ret, data, type_size, little_endian);
return S_OK;
}
static HRESULT set_data(script_ctx_t *ctx, jsval_t vthis, unsigned argc, jsval_t *argv, unsigned type_size, const void *val)
{
BOOL little_endian = FALSE;
@ -275,6 +314,118 @@ static HRESULT set_data(script_ctx_t *ctx, jsval_t vthis, unsigned argc, jsval_t
return S_OK;
}
static HRESULT DataView_getFloat32(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
float v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getFloat64(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
double v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getInt8(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
INT8 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getInt16(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
INT16 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getInt32(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
INT32 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getUint8(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
UINT8 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getUint16(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
UINT16 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_getUint32(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
UINT32 v;
TRACE("\n");
hres = get_data(ctx, vthis, argc, argv, sizeof(v), &v);
if(FAILED(hres))
return hres;
if(r) *r = jsval_number(v);
return S_OK;
}
static HRESULT DataView_setFloat32(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
HRESULT hres;
@ -382,6 +533,14 @@ static HRESULT DataView_setInt32(script_ctx_t *ctx, jsval_t vthis, WORD flags, u
}
static const builtin_prop_t DataView_props[] = {
{L"getFloat32", DataView_getFloat32, PROPF_METHOD|1},
{L"getFloat64", DataView_getFloat64, PROPF_METHOD|1},
{L"getInt16", DataView_getInt16, PROPF_METHOD|1},
{L"getInt32", DataView_getInt32, PROPF_METHOD|1},
{L"getInt8", DataView_getInt8, PROPF_METHOD|1},
{L"getUint16", DataView_getUint16, PROPF_METHOD|1},
{L"getUint32", DataView_getUint32, PROPF_METHOD|1},
{L"getUint8", DataView_getUint8, PROPF_METHOD|1},
{L"setFloat32", DataView_setFloat32, PROPF_METHOD|1},
{L"setFloat64", DataView_setFloat64, PROPF_METHOD|1},
{L"setInt16", DataView_setInt16, PROPF_METHOD|1},

View file

@ -1751,10 +1751,10 @@ sync_test("ArrayBuffers & Views", function() {
test_own_props("DataView.prototype", [
"buffer", "byteLength", "byteOffset",
"setInt8", "setUint8",
"setInt16", "setUint16",
"setInt32", "setUint32",
"setFloat32", "setFloat64"
"getInt8", "setInt8", "getUint8", "setUint8",
"getInt16", "setInt16", "getUint16", "setUint16",
"getInt32", "setInt32", "getUint32", "setUint32",
"getFloat32", "setFloat32", "getFloat64", "setFloat64"
]);
r = Object.prototype.toString.call(new DataView(buf));
@ -1869,8 +1869,51 @@ sync_test("ArrayBuffers & Views", function() {
ok(view.byteLength === 10, "DataView(buf).byteLength = " + view.byteLength);
ok(view.byteOffset === 0, "DataView(buf).byteOffset = " + view.byteOffset);
for(i = 0; i < 10; i++) {
r = view.getInt8(i);
ok(r === 0, "view byte " + i + " = " + r);
}
for(i = 0; i < types.length; i++) {
var method = "set" + types[i][0], offs = 11 - types[i][1];
var method = "get" + types[i][0], offs = 11 - types[i][1];
r = DataView.prototype[method].length;
ok(r === 1, "DataView.prototype." + method + ".length = " + r);
try {
view[method]();
ok(false, "view." + method + "() did not throw exception");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_DATAVIEW_NO_ARGUMENT, "view." + method + "() threw " + n);
}
try {
view[method](-1);
ok(false, "view." + method + "(-1) did not throw exception");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_DATAVIEW_INVALID_ACCESS, "view." + method + "(-1) threw " + n);
}
try {
view[method](offs);
ok(false, "view." + method + "(" + offs + ") did not throw exception");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_DATAVIEW_INVALID_ACCESS, "view." + method + "(" + offs + ") threw " + n);
}
try {
view[method].call(null, 0);
ok(false, "view." + method + "(0) with null context did not throw exception");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_NOT_DATAVIEW, "view." + method + "(0) with null context threw " + n);
}
try {
view[method].call({}, 0);
ok(false, "view." + method + "(0) with an object context did not throw exception");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_NOT_DATAVIEW, "view." + method + "(0) with an object context threw " + n);
}
method = "set" + types[i][0];
r = DataView.prototype[method].length;
ok(r === 1, "DataView.prototype." + method + ".length = " + r);
try {
@ -1919,14 +1962,26 @@ sync_test("ArrayBuffers & Views", function() {
r = view.setInt8(1, -257);
ok(r === undefined, "view.setInt8(1, -1) returned " + r);
r = view.getUint16(0);
ok(r === 255, "view.getUint16(0) returned " + r);
r = view.getUint16(0, true);
ok(r === 65280, "view.getUint16(0, true) returned " + r);
r = view.setUint32(2, "12345678", true);
ok(r === undefined, "view.setUint32(2, '12345678', true) returned " + r);
r = view.getInt32(1);
ok(r === -11640388, "view.getInt32(1) returned " + r);
r = view.setInt16(3, 65535, true);
ok(r === undefined, "view.setInt16(3, 65535) returned " + r);
r = view.getUint16(3);
ok(r === 65535, "view.getUint16(3) returned " + r);
r = view.setUint32(0, -2, true);
ok(r === undefined, "view.setUint32(0, -2) returned " + r);
r = view.getInt32(0, true);
ok(r === -2, "view.getInt32(0) returned " + r);
r = view.setFloat32(6, 1234.5, true);
ok(r === undefined, "view.setFloat32(6, 1234.5) returned " + r);
r = view2.getFloat32(0, true);
ok(r === 1234.5, "view2.getFloat32(0) returned " + r);
/* setters differing only in signedness have identical behavior, but they're not the same methods */
ok(view.setInt8 !== view.setUint8, "setInt8 and setUint8 are the same method");