From 1f8e75388da1d5dd84d424115e4a8563f483a630 Mon Sep 17 00:00:00 2001 From: David Richardson Date: Thu, 27 Aug 2026 21:57:37 -0600 Subject: [PATCH] Fix undefined function call in CPArray range/argument exceptions Foundation/CPException.j: _CPRaiseRangeException and _CPRaiseInvalidArgumentException called METHOD_CALL_STRING(), undefined anywhere. Every out-of-bounds CPArray access threw an uncatchable JS ReferenceError instead of CPRangeException/ CPInvalidArgumentException. Fixed to call the existing _CPMethodCallString(anObject, aSelector). Tests/Foundation/CPArrayTest.j, CPMutableArrayTest.j: the defect was invisible because test_objectAtIndex_ and test_objectsAtIndexes_ checked only that something was thrown, not what. Added exception-identity checks, and fixed ConcreteArray/ConcreteMutableArray's objectAtIndex: overrides, which threw a plain string and would have failed the new checks. --- Foundation/CPException.j | 4 +-- Tests/Foundation/CPArrayTest.j | 39 +++++++++++++++++++-------- Tests/Foundation/CPMutableArrayTest.j | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) mode change 100755 => 100644 Foundation/CPException.j diff --git a/Foundation/CPException.j b/Foundation/CPException.j old mode 100755 new mode 100644 index 7ff6db223..1c3d4f08a --- a/Foundation/CPException.j +++ b/Foundation/CPException.j @@ -264,13 +264,13 @@ function _CPRaiseInvalidAbstractInvocation(anObject, aSelector) function _CPRaiseInvalidArgumentException(anObject, aSelector, aMessage) { [CPException raise:CPInvalidArgumentException - reason:METHOD_CALL_STRING() + aMessage]; + reason:_CPMethodCallString(anObject, aSelector) + aMessage]; } function _CPRaiseRangeException(anObject, aSelector, anIndex, aCount) { [CPException raise:CPRangeException - reason:METHOD_CALL_STRING() + "index (" + anIndex + ") beyond bounds (" + aCount + ")"]; + reason:_CPMethodCallString(anObject, aSelector) + "index (" + anIndex + ") beyond bounds (" + aCount + ")"]; } function _CPReportLenientDeprecation(/*Class*/ aClass, /*SEL*/ oldSelector, /*SEL*/ newSelector) diff --git a/Tests/Foundation/CPArrayTest.j b/Tests/Foundation/CPArrayTest.j index 850af1cbd..f783739db 100644 --- a/Tests/Foundation/CPArrayTest.j +++ b/Tests/Foundation/CPArrayTest.j @@ -82,18 +82,26 @@ - (void)test_objectAtIndex_ { var arrayClass = [[self class] arrayClass], - array = [arrayClass array]; + array = [arrayClass array], + e; - [self assertThrows:function () { [array objectAtIndex:-1] }]; - [self assertThrows:function () { [array objectAtIndex:0] }]; + e = [self assertThrows:function () { [array objectAtIndex:-1] }]; + [self assert:CPRangeException equals:[e name]]; + + e = [self assertThrows:function () { [array objectAtIndex:0] }]; + [self assert:CPRangeException equals:[e name]]; var array = [arrayClass arrayWithObjects:0, 1, 2]; - [self assertThrows:function () { [array objectAtIndex:-1] }]; + e = [self assertThrows:function () { [array objectAtIndex:-1] }]; + [self assert:CPRangeException equals:[e name]]; + [self assert:[array objectAtIndex:0] same:0]; [self assert:[array objectAtIndex:1] same:1]; [self assert:[array objectAtIndex:2] same:2]; - [self assertThrows:function () { [array objectAtIndex:3] }]; + + e = [self assertThrows:function () { [array objectAtIndex:3] }]; + [self assert:CPRangeException equals:[e name]]; } - (void)test_objectsAtIndexes_ @@ -104,20 +112,29 @@ } var arrayClass = [[self class] arrayClass], - array = [arrayClass array]; + array = [arrayClass array], + e; - [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(0, 1)] }]; + e = [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(0, 1)] }]; + [self assert:CPRangeException equals:[e name]]; var array = [arrayClass arrayWithObjects:0, 1, 2]; [self assert:[array objectsAtIndexes:rangeIndexes(0, 1)] equals:[0]]; [self assert:[array objectsAtIndexes:rangeIndexes(0, 2)] equals:[0, 1]]; [self assert:[array objectsAtIndexes:rangeIndexes(0, 3)] equals:[0, 1, 2]]; - [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(0, 4)] }]; + + e = [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(0, 4)] }]; + [self assert:CPRangeException equals:[e name]]; + [self assert:[array objectsAtIndexes:rangeIndexes(1, 1)] equals:[1]]; [self assert:[array objectsAtIndexes:rangeIndexes(1, 2)] equals:[1, 2]]; - [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(1, 3)] }]; - [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(3, 1)] }]; + + e = [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(1, 3)] }]; + [self assert:CPRangeException equals:[e name]]; + + e = [self assertThrows:function () { [array objectsAtIndexes:rangeIndexes(3, 1)] }]; + [self assert:CPRangeException equals:[e name]]; } - (void)test_indexOfObject_ @@ -829,7 +846,7 @@ - (id)objectAtIndex:(CPUInteger)anIndex { if (anIndex < 0 || anIndex >= [self count]) - throw "range error"; + [CPException raise:CPRangeException reason:"index (" + anIndex + ") beyond bounds (" + [self count] + ")"]; return array[anIndex]; } diff --git a/Tests/Foundation/CPMutableArrayTest.j b/Tests/Foundation/CPMutableArrayTest.j index 03d8129b3..9a495f191 100644 --- a/Tests/Foundation/CPMutableArrayTest.j +++ b/Tests/Foundation/CPMutableArrayTest.j @@ -578,7 +578,7 @@ - (id)objectAtIndex:(CPUInteger)anIndex { if (anIndex < 0 || anIndex >= [self count]) - throw "range error"; + [CPException raise:CPRangeException reason:"index (" + anIndex + ") beyond bounds (" + [self count] + ")"]; return array[anIndex]; }