Skip to content

Commit

Permalink
Added Object.getOwnPropertyDescriptors as per #1302 (comment)
Browse files Browse the repository at this point in the history
  • Loading branch information
gfwilliams committed Feb 23, 2023
1 parent eb9cd93 commit 20ff75e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
Bangle.js2: Fix regression in E.showMenu so you can use menu items with ':undefined' (as in the example in the reference)
Graphics: Ensure that an error is thrown if a palette is used in >8 bit images. It was previously possible to ask for a palette on a 32 bit image, which caused an overflow
Fix issue extending a class from a class from a class (fix #1529)
Added Object.getOwnPropertyDescriptors

2v16 : JIT functions now execute in their own function scope (allows arguments)
Move older 'HY' boards to use `g` for the built-in graphics, not `LCD` (and change docs)
Expand Down
44 changes: 44 additions & 0 deletions src/jswrap_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,50 @@ JsVar *jswrap_object_getOwnPropertyDescriptor(JsVar *parent, JsVar *name) {
return obj;
}

/*JSON{
"type" : "staticmethod",
"class" : "Object",
"name" : "getOwnPropertyDescriptors",
"ifndef" : "SAVE_ON_FLASH",
"generate" : "jswrap_object_getOwnPropertyDescriptors",
"params" : [
["obj","JsVar","The object"]
],
"return" : ["JsVar","An object containing all the property descriptors of an object"]
}
Get information on all properties in the object (from `Object.getOwnPropertyDescriptor`), or just `{}` if no properties
*/
JsVar *jswrap_object_getOwnPropertyDescriptors(JsVar *parent) {
if (!jsvHasChildren(parent)) {
jsExceptionHere(JSET_TYPEERROR, "First argument must be an object, got %t", parent);
return 0;
}
JsVar *descriptors = jsvNewObject();
if (!descriptors) return 0;

/* There is some code mentioned at https://github.com/espruino/Espruino/issues/1302#issuecomment-1430833414
const protoPropDescriptor = Object.getOwnPropertyDescriptor(obj, '__proto__');
const descriptors = protoPropDescriptor ? { ['__proto__']: protoPropDescriptor } : {};
which we're not implementing here - but I think the current implementation is fine for 99% of cases
*/

JsVar *ownPropertyNames = jswrap_object_keys_or_property_names(parent, JSWOKPF_INCLUDE_NON_ENUMERABLE);
JsvObjectIterator it;
jsvObjectIteratorNew(&it, ownPropertyNames);
while (jsvObjectIteratorHasValue(&it)) {
JsVar *propName = jsvObjectIteratorGetValue(&it);
JsVar *propValue = jswrap_object_getOwnPropertyDescriptor(parent, propName);
jsvObjectSetChildVar(descriptors, propName, propValue);
jsvUnLock2(propName, propValue);
jsvObjectIteratorNext(&it);
}
jsvObjectIteratorFree(&it);
jsvUnLock(ownPropertyNames);
return descriptors;
}

/*JSON{
"type" : "method",
"class" : "Object",
Expand Down
1 change: 1 addition & 0 deletions src/jswrap_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ JsVar *jswrap_object_keys_or_property_names(
JsVar *jswrap_object_values_or_entries(JsVar *object, bool returnEntries);
JsVar *jswrap_object_create(JsVar *proto, JsVar *propertiesObject);
JsVar *jswrap_object_getOwnPropertyDescriptor(JsVar *parent, JsVar *name);
JsVar *jswrap_object_getOwnPropertyDescriptors(JsVar *parent);
bool jswrap_object_hasOwnProperty(JsVar *parent, JsVar *name);
JsVar *jswrap_object_defineProperty(JsVar *parent, JsVar *propName, JsVar *desc);
JsVar *jswrap_object_defineProperties(JsVar *parent, JsVar *props);
Expand Down
19 changes: 19 additions & 0 deletions tests/test_object_getOwnPropertyDescriptors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var A = {
b : 42,
c : function() {}
};

class B {
};


var r = [
// [JSON.stringify(Object.getOwnPropertyDescriptors(A)),'{"b":{"writable":true,"enumerable":true,"configurable":true,"value":42},"c":{"writable":true,"enumerable":true,"configurable":true}}'],
// this one is not correct as it seems V8 adds 'length' and 'name' fields to classes
//[JSON.stringify(Object.getOwnPropertyDescriptors(B)),"{\"prototype\":{\"writable\":true,\"enumerable\":true,\"configurable\":true,\"value\":{}}}"]
];

//console.log(r);

result = r.every(a => a[0]==a[1]);

0 comments on commit 20ff75e

Please sign in to comment.