Skip to content

Commit 6184a08

Browse files
authored
Don't fetch range if the object has no length (#1453)
1 parent 8033d67 commit 6184a08

File tree

3 files changed

+189
-76
lines changed

3 files changed

+189
-76
lines changed

dwds/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
- Fix chrome detection in iPhone emulation mode in chrome or edge browsers.
1515
- Reliably find unused port for extension backend http service.
16+
- Ignore offset / count parameters in getObject if the object has no length
1617

1718
## 11.4.0
1819

dwds/lib/src/debugging/debugger.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ class Debugger extends Domain {
362362
/// List/Map and [offset] and [count] should indicate the desired range.
363363
Future<RemoteObject> _subrange(
364364
String id, int offset, int count, int length) async {
365+
assert(offset != null);
366+
assert(length != null);
365367
// TODO(#809): Sometimes we already know the type of the object, and
366368
// we could take advantage of that to short-circuit.
367369
var receiver = remoteObjectFor(id);
@@ -395,12 +397,11 @@ class Debugger extends Domain {
395397
/// Note that the property names are JS names, e.g.
396398
/// Symbol(DartClass.actualName) and will need to be converted. For a system
397399
/// List or Map, [offset] and/or [count] can be provided to indicate a desired
398-
/// range of entries. If those are provided, then [length] should also be
399-
/// provided to indicate the total length of the List/Map.
400+
/// range of entries. They will be ignored if there is no [length].
400401
Future<List<Property>> getProperties(String objectId,
401402
{int offset, int count, int length}) async {
402403
var rangeId = objectId;
403-
if (offset != null || count != null) {
404+
if (length != null && (offset != null || count != null)) {
404405
var range = await _subrange(objectId, offset ?? 0, count, length);
405406
rangeId = range.objectId;
406407
}

dwds/test/chrome_proxy_service_test.dart

Lines changed: 184 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -492,28 +492,6 @@ void main() {
492492
expect(world.valueAsString, 'world');
493493
});
494494

495-
test('Strings with offset', () async {
496-
var worldRef = await service.evaluate(
497-
isolate.id, bootstrap.id, "helloString('world')") as InstanceRef;
498-
var world = await service.getObject(isolate.id, worldRef.id,
499-
count: 2, offset: 1) as Instance;
500-
expect(world.valueAsString, 'or');
501-
expect(world.count, 2);
502-
expect(world.length, 5);
503-
expect(world.offset, 1);
504-
});
505-
506-
test('Strings with offset off the end', () async {
507-
var worldRef = await service.evaluate(
508-
isolate.id, bootstrap.id, "helloString('world')") as InstanceRef;
509-
var world = await service.getObject(isolate.id, worldRef.id,
510-
count: 5, offset: 3) as Instance;
511-
expect(world.valueAsString, 'ld');
512-
expect(world.count, 2);
513-
expect(world.length, 5);
514-
expect(world.offset, 3);
515-
});
516-
517495
test('Large strings not truncated', () async {
518496
var largeString = await service.evaluate(
519497
isolate.id, bootstrap.id, "helloString('${'abcde' * 250}')")
@@ -564,30 +542,6 @@ void main() {
564542
expect(sixth.valueAsString, '5');
565543
});
566544

567-
test('Lists with count/offset', () async {
568-
var list = await createList();
569-
var inst = await service.getObject(isolate.id, list.objectId,
570-
count: 7, offset: 4) as Instance;
571-
expect(inst.length, 1001);
572-
expect(inst.offset, 4);
573-
expect(inst.count, 7);
574-
var fifth = inst.elements[0] as InstanceRef;
575-
expect(fifth.valueAsString, '100');
576-
var sixth = inst.elements[1] as InstanceRef;
577-
expect(sixth.valueAsString, '5');
578-
});
579-
580-
test('Lists running off the end', () async {
581-
var list = await createList();
582-
var inst = await service.getObject(isolate.id, list.objectId,
583-
count: 5, offset: 1000) as Instance;
584-
expect(inst.length, 1001);
585-
expect(inst.offset, 1000);
586-
expect(inst.count, 1);
587-
var only = inst.elements[0] as InstanceRef;
588-
expect(only.valueAsString, '5');
589-
});
590-
591545
test('Maps', () async {
592546
var map = await createMap();
593547
var inst =
@@ -603,33 +557,6 @@ void main() {
603557
expect(sixth.value.valueAsString, '995');
604558
});
605559

606-
test('Maps with count/offset', () async {
607-
var map = await createMap();
608-
var inst = await service.getObject(isolate.id, map.objectId,
609-
count: 7, offset: 4) as Instance;
610-
expect(inst.length, 1001);
611-
expect(inst.offset, 4);
612-
expect(inst.count, 7);
613-
var fifth = inst.associations[0];
614-
expect(fifth.key.valueAsString, '4');
615-
expect(fifth.value.valueAsString, '996');
616-
var sixth = inst.associations[1];
617-
expect(sixth.key.valueAsString, '5');
618-
expect(sixth.value.valueAsString, '995');
619-
});
620-
621-
test('Maps running off the end', () async {
622-
var map = await createMap();
623-
var inst = await service.getObject(isolate.id, map.objectId,
624-
count: 5, offset: 1000) as Instance;
625-
expect(inst.length, 1001);
626-
expect(inst.offset, 1000);
627-
expect(inst.count, 1);
628-
var only = inst.associations[0];
629-
expect(only.key.valueAsString, '1000');
630-
expect(only.value.valueAsString, '0');
631-
});
632-
633560
test('bool', () async {
634561
var ref = await service.evaluate(
635562
isolate.id, bootstrap.id, 'helloBool(true)') as InstanceRef;
@@ -671,6 +598,190 @@ void main() {
671598
expect(script.tokenPosTable, isNotEmpty);
672599
}
673600
});
601+
602+
group('getObject called with offset/count parameters', () {
603+
test('Lists with offset/count are truncated', () async {
604+
var list = await createList();
605+
var inst = await service.getObject(
606+
isolate.id,
607+
list.objectId,
608+
count: 7,
609+
offset: 4,
610+
) as Instance;
611+
expect(inst.length, 1001);
612+
expect(inst.offset, 4);
613+
expect(inst.count, 7);
614+
var fifth = inst.elements[0] as InstanceRef;
615+
expect(fifth.valueAsString, '100');
616+
var sixth = inst.elements[1] as InstanceRef;
617+
expect(sixth.valueAsString, '5');
618+
});
619+
620+
test('Lists are truncated to the end if offset/count runs off the end',
621+
() async {
622+
var list = await createList();
623+
var inst = await service.getObject(
624+
isolate.id,
625+
list.objectId,
626+
count: 5,
627+
offset: 1000,
628+
) as Instance;
629+
expect(inst.length, 1001);
630+
expect(inst.offset, 1000);
631+
expect(inst.count, 1);
632+
var only = inst.elements[0] as InstanceRef;
633+
expect(only.valueAsString, '5');
634+
});
635+
636+
test('Maps with offset/count are truncated', () async {
637+
var map = await createMap();
638+
var inst = await service.getObject(
639+
isolate.id,
640+
map.objectId,
641+
count: 7,
642+
offset: 4,
643+
) as Instance;
644+
expect(inst.length, 1001);
645+
expect(inst.offset, 4);
646+
expect(inst.count, 7);
647+
var fifth = inst.associations[0];
648+
expect(fifth.key.valueAsString, '4');
649+
expect(fifth.value.valueAsString, '996');
650+
var sixth = inst.associations[1];
651+
expect(sixth.key.valueAsString, '5');
652+
expect(sixth.value.valueAsString, '995');
653+
});
654+
655+
test('Maps are truncated to the end if offset/count runs off the end',
656+
() async {
657+
var map = await createMap();
658+
var inst = await service.getObject(
659+
isolate.id,
660+
map.objectId,
661+
count: 5,
662+
offset: 1000,
663+
) as Instance;
664+
expect(inst.length, 1001);
665+
expect(inst.offset, 1000);
666+
expect(inst.count, 1);
667+
var only = inst.associations[0];
668+
expect(only.key.valueAsString, '1000');
669+
expect(only.value.valueAsString, '0');
670+
});
671+
672+
test('Strings with offset/count are truncated', () async {
673+
var worldRef = await service.evaluate(
674+
isolate.id, bootstrap.id, "helloString('world')") as InstanceRef;
675+
var world = await service.getObject(
676+
isolate.id,
677+
worldRef.id,
678+
count: 2,
679+
offset: 1,
680+
) as Instance;
681+
expect(world.valueAsString, 'or');
682+
expect(world.count, 2);
683+
expect(world.length, 5);
684+
expect(world.offset, 1);
685+
});
686+
687+
test(
688+
'Strings are truncated to the end if offset/count runs off the end',
689+
() async {
690+
var worldRef = await service.evaluate(
691+
isolate.id, bootstrap.id, "helloString('world')") as InstanceRef;
692+
var world = await service.getObject(
693+
isolate.id,
694+
worldRef.id,
695+
count: 5,
696+
offset: 3,
697+
) as Instance;
698+
expect(world.valueAsString, 'ld');
699+
expect(world.count, 2);
700+
expect(world.length, 5);
701+
expect(world.offset, 3);
702+
});
703+
704+
test('offset/count parameters are ignored for Classes', () async {
705+
var testClass = await service.getObject(
706+
isolate.id,
707+
rootLibrary.classes.first.id,
708+
offset: 100,
709+
count: 100,
710+
) as Class;
711+
expect(
712+
testClass.functions,
713+
unorderedEquals([
714+
predicate((FuncRef f) => f.name == 'message' && !f.isStatic),
715+
predicate((FuncRef f) => f.name == 'notFinal' && !f.isStatic),
716+
predicate((FuncRef f) => f.name == 'hello' && !f.isStatic),
717+
predicate((FuncRef f) => f.name == '_equals' && !f.isStatic),
718+
predicate((FuncRef f) => f.name == 'hashCode' && !f.isStatic),
719+
predicate((FuncRef f) => f.name == 'toString' && !f.isStatic),
720+
predicate(
721+
(FuncRef f) => f.name == 'noSuchMethod' && !f.isStatic),
722+
predicate(
723+
(FuncRef f) => f.name == 'runtimeType' && !f.isStatic),
724+
]));
725+
expect(
726+
testClass.fields,
727+
unorderedEquals([
728+
predicate((FieldRef f) =>
729+
f.name == 'message' &&
730+
f.declaredType != null &&
731+
!f.isStatic &&
732+
!f.isConst &&
733+
f.isFinal),
734+
predicate((FieldRef f) =>
735+
f.name == 'notFinal' &&
736+
f.declaredType != null &&
737+
!f.isStatic &&
738+
!f.isConst &&
739+
!f.isFinal),
740+
]));
741+
});
742+
743+
test('offset/count parameters are ignored for bools', () async {
744+
var ref = await service.evaluate(
745+
isolate.id, bootstrap.id, 'helloBool(true)') as InstanceRef;
746+
var obj = await service.getObject(
747+
isolate.id,
748+
ref.id,
749+
offset: 100,
750+
count: 100,
751+
) as Instance;
752+
expect(obj.kind, InstanceKind.kBool);
753+
expect(obj.classRef.name, 'Bool');
754+
expect(obj.valueAsString, 'true');
755+
});
756+
757+
test('offset/count parameters are ignored for nums', () async {
758+
var ref = await service.evaluate(
759+
isolate.id, bootstrap.id, 'helloNum(42)') as InstanceRef;
760+
var obj = await service.getObject(
761+
isolate.id,
762+
ref.id,
763+
offset: 100,
764+
count: 100,
765+
) as Instance;
766+
expect(obj.kind, InstanceKind.kDouble);
767+
expect(obj.classRef.name, 'Double');
768+
expect(obj.valueAsString, '42');
769+
});
770+
771+
test('offset/count parameters are ignored for null', () async {
772+
var ref = await service.evaluate(
773+
isolate.id, bootstrap.id, 'helloNum(null)') as InstanceRef;
774+
var obj = await service.getObject(
775+
isolate.id,
776+
ref.id,
777+
offset: 100,
778+
count: 100,
779+
) as Instance;
780+
expect(obj.kind, InstanceKind.kNull);
781+
expect(obj.classRef.name, 'Null');
782+
expect(obj.valueAsString, 'null');
783+
});
784+
});
674785
});
675786

676787
test('getScripts', () async {

0 commit comments

Comments
 (0)