From 627b54768293ec277f1adb997c888ec524f4174d Mon Sep 17 00:00:00 2001 From: Jb Aviat Date: Fri, 22 May 2020 14:19:14 +0200 Subject: [PATCH] Fix array conversion when size changes dynamically --- .../extension/mini_racer_extension.cc | 9 ++- tests/test_array_growth.py | 80 +++++++++++++++++++ 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 tests/test_array_growth.py diff --git a/py_mini_racer/extension/mini_racer_extension.cc b/py_mini_racer/extension/mini_racer_extension.cc index da4a6049..52b064b4 100644 --- a/py_mini_racer/extension/mini_racer_extension.cc +++ b/py_mini_racer/extension/mini_racer_extension.cc @@ -447,20 +447,23 @@ static BinaryValue *convert_v8_to_binary(Isolate * isolate, else if (value->IsArray()) { Local arr = Local::Cast(value); - size_t len = arr->Length(); + uint32_t len = arr->Length(); + BinaryValue **ary = xalloc(ary, sizeof(*ary) * len); res->type = type_array; res->array_val = ary; + res->len = (size_t) len; - for(uint32_t i = 0; i < arr->Length(); i++) { + for(uint32_t i = 0; i < len; i++) { Local element = arr->Get(context, i).ToLocalChecked(); BinaryValue *bin_value = convert_v8_to_binary(isolate, context, element); if (bin_value == NULL) { + // adjust final array length + res->len = (size_t) i; goto err; } ary[i] = bin_value; - res->len++; } } diff --git a/tests/test_array_growth.py b/tests/test_array_growth.py new file mode 100644 index 00000000..8605e0ae --- /dev/null +++ b/tests/test_array_growth.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" Growing and reducing arrays """ + +import unittest +import json +import time + +from datetime import datetime + +from py_mini_racer import py_mini_racer + + +class Test(unittest.TestCase): + """ Test basic types """ + + + def setUp(self): + + self.mr = py_mini_racer.MiniRacer() + + def test_growing_array(self): + + js = """ + var global_array = [ + { + get first() { + for(var i=0; i<100; i++) { + global_array.push(0x41); + } + } + } + ]; + + // when accessed, the first element will make the array grow by 100 items. + global_array; + """ + + res = self.mr.eval(js) + # Initial array size was 100 + self.assertEqual(res, [{'first': None}]) + + + def test_shrinking_array(self): + js = """ + var global_array = [ + { + get first() { + for(var i=0; i<100; i++) { + global_array.pop(); + } + } + } + ]; + + // build a 200 elements array + for(var i=0; i < 200; i++) + global_array.push(0x41); + + // when the first item will be accessed, it should remove 100 items. + + global_array; + """ + + # The final array should have: + # The initial item + # The next 100 items (value 0x41) + # The last 100 items which have been removed when the initial key was accessed + array = [{'first': None}] + \ + [0x41] * 100 + \ + [None] * 100 + + res = self.mr.eval(js) + self.assertEqual(res, array) + + +if __name__ == '__main__': + import sys + sys.exit(unittest.main())