Skip to content

Value::to_json destroy the order of items in an Array #690

@sele9

Description

@sele9

Describe the bug
The order of array items is sometimes mixed after the conversion from boa::Value to serde_json::Value.

To Reproduce
I've added a few lines of code here:

for k in obj.borrow().keys() {

let mut keys: Vec<u32> = Vec::new();
    for k in obj.borrow().keys() {
        match k {
            PropertyKey::Index(i) => {
                keys.push(i);
            },
            _ => {},
       }
}

The debugger shows me the following keys:
Bildschirmfoto vom 2020-09-07 18-42-42

This JavaScript code reproduces the issue:
where $t is a globally registered function implemented in rust and self the equivalent of globalThis

function tableItems(items) {
    return items.map((item, i) => {
        if (i === 0) {
            item.isFirst = true;
        }
        if (i === items.length - 1) {
            item.isLast = true;
        }
        return item;
    });
}

self.context = {
    bevollmaechtigterItems() {
        const geschlechtF = (self.vollmacht_geschlecht === 'm' || self.vollmacht_geschlecht === 'w' || self.vollmacht_geschlecht === 'd') ? self.$t('geschlecht.' + self.vollmacht_geschlecht) : '';
        return tableItems([
            { label: self.$t('pdf.labels.vorname'), value: self.vollmacht_vorname },
            { label: self.$t('pdf.labels.nachname'), value: self.vollmacht_nachname },
            { label: self.$t('pdf.labels.geschlecht'), value: geschlechtF },
            { label: self.$t('pdf.labels.strasse'), value: self.vollmacht_strasse },
            { label: self.$t('pdf.labels.hausnummer'), value: self.vollmacht_hausnummer },
            { label: self.$t('pdf.labels.postleitzahl'), value: self.vollmacht_postleitzahl },
            { label: self.$t('pdf.labels.ort'), value: self.vollmacht_ort },
            { label: self.$t('pdf.labels.email'), value: self.vollmacht_email },
            { label: self.$t('pdf.labels.telefonnummer'), value: self.vollmacht_telefonnummer },
        ]);
    }
};

Expected behavior
It should return in the same Order as defined in javascript.

Build environment (please complete the following information):

  • OS: Ubuntu Linux
  • Version: 20.04.2 LTS
  • Target triple: x86_64-unknown-linux-gnu
  • Rustc version: 1.48.0-nightly

Additional context
I replaced these lines:

boa/boa/src/value/mod.rs

Lines 240 to 253 in edfafc4

if obj.borrow().is_array() {
let mut arr: Vec<JSONValue> = Vec::new();
for k in obj.borrow().keys() {
if k != "length" {
let value = self.get_field(k.to_string());
if value.is_undefined() || value.is_function() || value.is_symbol() {
arr.push(JSONValue::Null);
} else {
arr.push(self.get_field(k.to_string()).to_json(interpreter)?);
}
}
}
Ok(JSONValue::Array(arr))
} else {

with:

                if obj.borrow().is_array() {
                    let mut arr: Vec<JSONValue> = Vec::new();
                    let mut keys: Vec<u32> = Vec::new();
                    for k in obj.borrow().keys() {
                        match k {
                            PropertyKey::Index(i) => {
                                keys.push(i);
                            },
                            _ => {},
                        }
                    }
                    keys.sort();
                    for key in keys {
                        let k = PropertyKey::Index(key);
                        let value = self.get_field(k.to_string());
                        if value.is_undefined() || value.is_function() || value.is_symbol() {
                            arr.push(JSONValue::Null);
                        } else {
                            arr.push(self.get_field(k.to_string()).to_json(interpreter)?);
                        }
                    }
                    Ok(JSONValue::Array(arr))
                }

it works as expected but maybe there is a more performant way?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingbuiltinsPRs and Issues related to builtins/intrinsics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions