JSON.parse seems to create object whose attributes cannot be modified (but can be deleted).
Steps To Reproduce
Checkout current master (87aea64c)
start cli: ./target/debug/boa
Enter
var a = JSON.parse('{"x":0}');
a.x=2;
a.x
The value a.x is still 0 instead of expected 2.
Build environment (please complete the following information):
The bug is here.
when we inset the fields of the object, we don't set it as writable, configurable and enumerable:
Property::default().value(Value::from(json.clone())).writable(true).configurable(true).enumerable(true),
Doing this should fix it :)
I can take this.
Looks like this was partially addressed in #410 . I'm trying to figure out a good way to test the enumerable portion.
Assuming propertyIsEnumerable is implemented, I will go ahead with that unless I hear or think of a better idea.
I can take this.
Go ahead! :)
@HalidOdat -- I'm trying to test that the properties are enumerable by using the propertyIsEnumerable function which I have rough implementation written here. However, it doesn't seem like the Object.prototype methods are getting added to the new objects created in Value::from_json based on https://github.com/boa-dev/boa/blob/bb2b6f638cba59269694d44424d16c9a5ede6a81/boa/src/builtins/value/mod.rs#L702
and
https://github.com/boa-dev/boa/blob/bb2b6f638cba59269694d44424d16c9a5ede6a81/boa/src/builtins/object/mod.rs#L339-L351
What would be the best way to grab the Object.prototype so that it can be added to those objects?
What would be the best way to grab the
Object.prototypeso that it can be added to those objects?
Hmmm. For this we need to take in an Interpreter (context) in Value::from_json, and get the prototype of Object and construct the object, it seems Value::from_json does not do that. I'll create an issue for this.
This issue can be easily tested with:
var a = JSON.parse('{"x":0}');
a.x=2;
a.x
and asserting that a.x == 2
@HalidOdat doesn鈥檛 asserting that the value changes only assert that it is writeable? As the bug was written, it is technically no longer a bug. However, the properties are not enumerated so I figured I鈥檇 just use this issue for that problem.
@HalidOdat doesn鈥檛 asserting that the value changes only assert that it is writeable? As the bug was written, it is technically no longer a bug. However, the properties are not enumerated so I figured I鈥檇 just use this issue for that problem.
I see. Even if we implement propertyIsEnumerable we can't use it if the object does not have a prototype instance so we first need to fix #452
I see. Even if we implement propertyIsEnumerable we can't use it if the object does not have a prototype instance so we first need to fix #452
Agreed.
@HalidOdat @Razican -- As was mentioned earlier in this thread, I'm using propertyIsEnumerable to try to test enumerability on the properties for objects and arrays in Value::from_json. In the Array::create function, I'm trying to create the array prototype using the object prototype based on the fourth bullet here: https://tc39.es/ecma262/#sec-properties-of-the-array-prototype-object. I do this by calling Value::new_object with the global object; however, it seems that the object prototype data is being lost. I've pasted the contents of the function below with a few print statements (and the output below that) that show what leads me to believe that the prototype data is being lost:
/// Returns a new empty object
pub fn new_object(global: Option<&Value>) -> Self {
let _timer = BoaProfiler::global().start_event("new_object", "value");
if let Some(global) = global {
let object_prototype = global.get_field("Object").get_field(PROTOTYPE);
println!("object prototype: {:?}", object_prototype);
let object = Object::create(object_prototype);
println!("new object: {:?}", object);
Self::object(object)
} else {
Self::object(Object::default())
}
}
object prototype: Value(Object(GcCell { value: {
kind: Ordinary
state: None
func: None
properties: {
constructor
hasOwnProperty
propertyIsEnumerable
toString
}
} }))
new object: {
kind: Ordinary
state: None
func: None
properties: {
}
}
Are my expectations on what should be happening off here? I've pushed my branch up if that would be easier than interpreting what I've stated above. You can find it here
I do this by calling
Value::new_objectwith the global object; however, it seems that the object prototype data is being lost. I've pasted the contents of the function below with a few print statements (and the output below that) that show what leads me to believe that the prototype data is being lost
Were not losing the object prototype but were not displaying it, the debug printer Debug trait was implemented by hand (no idea why, we should almost always let the compiler generate it for us) https://github.com/boa-dev/boa/blob/master/boa/src/builtins/object/mod.rs#L66-L79 we should delete it and add a Debug in Object derive here https://github.com/boa-dev/boa/blob/master/boa/src/builtins/object/mod.rs#L50
The prototype property prototype is stored in properties (as any property, like 'x', 'foo'), but prototype instance __proto__ is stored in internal_slots (this are properties which can not be accessed through javascript) v8 and spidermonkey allows accessing it
Hope this helps :)
It helps explain why I'm not seeing it in the print statements :smile:; however, I'm still not seeing the propertyIsEnumerable function on an array.
I'm still not seeing the
propertyIsEnumerablefunction on an array.
Hmmm. I think I know why this is happening because the order of the builtins initialization is not right! here Object should be declared before Array.
here Object should be declared before Array.
This doesn't quite seem to do the trick. Everything is added to that global object all at once after everything has been initialized. Thus, when Array::init(global) is called, the object has not been put on the global since all of that happens here. I tried to initialize each thing and then immediately add it to the global object, but I was then met with
thread 'main' panicked at 'GcCell<T> already mutably borrowed', <::std::macros::panic macros>:5:6