Skip to content

Commit c822eaa

Browse files
committed
feat: 优化 toMap 的循环引用处理逻辑
1 parent 60f75fb commit c822eaa

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

wrapper-android/src/androidTest/java/com/whl/quickjs/wrapper/QuickJSTest.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,11 +1193,11 @@ public void testAsyncErrorInByteCode() {
11931193
public void testObjectToMap() {
11941194
try (QuickJSContext context = createContext()) {
11951195
JSObject ret = (JSObject) context.evaluate("var a = {'a': '123', 'b': [1, 2]};a.c = a;a;");
1196-
assertEquals("{a=123, b=[1, 2]}", ret.toMap().toString());
1196+
assertEquals("{a=123, b=[1, 2], c=(this Map)}", ret.toMap().toString());
11971197
ret.release();
11981198

11991199
JSArray array = (JSArray) context.evaluate("var b = [{a: { c : 'xxx'}}, 2, 'qqq', 1.22]; b.push(b); b;");
1200-
assertEquals("[{a={c=xxx}}, 2, qqq, 1.22]", array.toArray().toString());
1200+
assertEquals("[{a={c=xxx}}, 2, qqq, 1.22, (this Collection)]", array.toArray().toString());
12011201
array.release();
12021202

12031203
JSObject emptyObj = (JSObject) context.evaluate("var a = { emptyArray: [] };a;");
@@ -1211,7 +1211,7 @@ public void testObjectToMap() {
12111211
public void testObjectToMapFilter() {
12121212
try (QuickJSContext context = createContext()) {
12131213
HashMap<String, Object> map = context.getGlobalObject().toMap((key, pointer, extra) -> key.equals("Math") || key.equals("Infinity"));
1214-
assertEquals("{console={}, Reflect={}, NaN=NaN, JSON={}, Atomics={}, undefined=null}", map.toString());
1214+
assertEquals("{globalThis=(this Map), console={}, Reflect={}, NaN=NaN, JSON={}, Atomics={}, undefined=null}", map.toString());
12151215
}
12161216
}
12171217

@@ -1309,4 +1309,26 @@ public void testDynamicImport() {
13091309
}
13101310
}
13111311

1312+
@Test
1313+
public void testArraySameRefToMap() {
1314+
try (QuickJSContext context = createContext()){
1315+
JSObject ret = (JSObject) context.evaluate("const a = [7]\n" +
1316+
"\n" +
1317+
"const b = {\n" +
1318+
"\tc: {\n" +
1319+
"\t\td: a\n" +
1320+
"\t},\n" +
1321+
"\te: a,\n" +
1322+
"\tg: null,\n" +
1323+
"\tk: undefined\n" +
1324+
"}\n" +
1325+
"\n" +
1326+
"b.f = b\n" +
1327+
"\n" +
1328+
"console.log(b)\n" +
1329+
"b;");
1330+
assertEquals("{c={d=[7]}, e=[7], f=(this Map), g=null, k=null}", ret.toMap().toString());
1331+
}
1332+
}
1333+
13121334
}

wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSArray.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public ArrayList<Object> toArray(MapFilter filter) {
5555
@Override
5656
public ArrayList<Object> toArray(MapFilter filter, Object extra, MapCreator creator) {
5757
ArrayList<Object> arrayList = new ArrayList<>(length());
58-
HashSet<Long> circulars = new HashSet<>();
58+
HashMap<Long, Object> circulars = new HashMap<>();
5959
convertToMap(this, arrayList, circulars, filter, extra, creator);
6060
circulars.clear();
6161
return arrayList;

wrapper-java/src/main/java/com/whl/quickjs/wrapper/QuickJSObject.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public HashMap<String, Object> toMap(MapFilter filter) {
272272
@Override
273273
public Map<String, Object> toMap(MapFilter filter, Object extra, MapCreator mapCreator) {
274274
Map<String, Object> objectMap = mapCreator.get();
275-
HashSet<Long> circulars = new HashSet<>();
275+
HashMap<Long, Object> circulars = new HashMap<>();
276276
convertToMap(this, objectMap, circulars, filter, extra, mapCreator);
277277
circulars.clear();
278278
return objectMap;
@@ -290,10 +290,12 @@ public ArrayList<Object> toArray(MapFilter filter) {
290290
}
291291

292292
/**
293-
* 注意点:循环引用的对象会被过滤掉
293+
* 注意点:
294+
* 1. 循环引用的对象会被过滤掉
295+
* 2. 当 value 值为 undefined ,和 null 的处理逻辑一样,未做区分
294296
*/
295-
protected void convertToMap(Object target, Object map, HashSet<Long> circulars, MapFilter filter, Object extra, MapCreator mapCreator) {
296-
circulars.add(((JSObject) target).getPointer());
297+
protected void convertToMap(Object target, Object map, HashMap<Long, Object> circulars, MapFilter filter, Object extra, MapCreator mapCreator) {
298+
circulars.put(((JSObject) target).getPointer(), map);
297299

298300
boolean isArray = target instanceof JSArray;
299301
JSArray array = isArray ? (JSArray) target : ((JSObject) target).getNames();
@@ -313,8 +315,14 @@ protected void convertToMap(Object target, Object map, HashSet<Long> circulars,
313315

314316
if (value instanceof JSObject) {
315317
long pointer = ((JSObject) value).getPointer();
316-
if (circulars.contains(pointer)) {
317-
// Circular reference objects, no processing needed.
318+
if (circulars.containsKey(pointer)) {
319+
// Circular reference objects.
320+
Object refValue = circulars.get(pointer);
321+
if (map instanceof Map) {
322+
((Map<String, Object>) map).put(key, refValue);
323+
} else if (map instanceof ArrayList){
324+
((ArrayList<Object>) map).add(refValue);
325+
}
318326
continue;
319327
}
320328
}

0 commit comments

Comments
 (0)