From 6e1ceff4b78bd992d4a35831e263c95f80e9d40f Mon Sep 17 00:00:00 2001 From: Gary Li Date: Tue, 9 Jul 2024 17:34:38 -0400 Subject: [PATCH] prettyPrint: do not call legacy toString for Uint8Arrays Certain Uint8Arrays returned from introspected functions fail to print with the pretty printer and log deprecated warnings. This is because for those Uint8Arrays we override its toString as a compatibility shim to warn users of legacy behaviour. However, this makes its toString own property nonstandard. Detect TypedArrays explicitly when pretty printing so it can be printed in an array-like format. Fixes https://gitlab.gnome.org/GNOME/gjs/-/issues/434 --- installed-tests/js/testPrint.js | 35 ++++++++++++++++++++++++++++ modules/script/_bootstrap/default.js | 11 ++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/installed-tests/js/testPrint.js b/installed-tests/js/testPrint.js index 083ddb9a8..558de6640 100644 --- a/installed-tests/js/testPrint.js +++ b/installed-tests/js/testPrint.js @@ -4,6 +4,7 @@ imports.gi.versions.Gdk = '3.0'; const Gdk = imports.gi.Gdk; +const ByteArray = imports.byteArray; const {getPrettyPrintFunction} = imports._print; let prettyPrint = getPrettyPrintFunction(globalThis); @@ -211,4 +212,38 @@ describe('prettyPrint', function () { expect(prettyPrint({'foo': imports})) .toEqual('{ foo: [GjsFileImporter root] }'); }); + + describe('TypedArrays', () => { + [ + Int8Array, + Uint8Array, + Uint16Array, + Uint8ClampedArray, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + ].forEach(constructor => { + it(constructor.name, function () { + const arr = new constructor([1, 2, 3]); + expect(prettyPrint(arr)) + .toEqual('[1, 2, 3]'); + }); + }); + + [BigInt64Array, BigUint64Array].forEach(constructor => { + it(constructor.name, function () { + const arr = new constructor([1n, 2n, 3n]); + expect(prettyPrint(arr)) + .toEqual('[1, 2, 3]'); + }); + }); + }); + + it('Uint8Array returned from introspected function', function () { + let a = ByteArray.fromString('⅜'); + expect(prettyPrint(a)).toEqual('[226, 133, 156]'); + }); }); diff --git a/modules/script/_bootstrap/default.js b/modules/script/_bootstrap/default.js index 91282f9ba..871d2bf74 100644 --- a/modules/script/_bootstrap/default.js +++ b/modules/script/_bootstrap/default.js @@ -23,9 +23,18 @@ return nativeLogError(e, args.map(arg => typeof arg === 'string' ? arg : prettyPrint(arg)).join(' ')); } + // compare against the %TypedArray% intrinsic object all typed array constructors inherit from + function _isTypedArray(value) { + return value instanceof Object.getPrototypeOf(Uint8Array); + } + function _hasStandardToString(value) { return value.toString === Object.prototype.toString || value.toString === Array.prototype.toString || + // although TypedArrays have a standard Array.prototype.toString, we currently enforce an override to warn + // for legacy behaviour, making the toString non-standard for + // "any Uint8Array instances created in situations where previously a ByteArray would have been created" + _isTypedArray(value) || value.toString === Date.prototype.toString; } @@ -64,7 +73,7 @@ function formatObject(obj, printedObjects) { printedObjects.add(obj); - if (Array.isArray(obj)) + if (Array.isArray(obj) || _isTypedArray(obj)) return formatArray(obj, printedObjects).toString(); if (obj instanceof Date) -- GitLab