Skip to content

Commit 7a2ffd0

Browse files
Merge pull request #397 from Distributive-Network/philippe/396-fix
Objects now use prototype defaults
2 parents 8f1ac3c + 3b02465 commit 7a2ffd0

6 files changed

+38
-66
lines changed

include/PyIterableProxyHandler.hh

-6
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ public:
2828
JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
2929
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc
3030
) const override;
31-
32-
/**
33-
* @brief An array of method definitions for Iterable prototype methods
34-
*
35-
*/
36-
static JSMethodDef iterable_methods[];
3731
};
3832

3933
#endif

include/PyObjectProxyHandler.hh

-6
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,6 @@ public:
190190
JS::ObjectOpResult &result) const override;
191191

192192
bool getBuiltinClass(JSContext *cx, JS::HandleObject proxy, js::ESClass *cls) const override;
193-
194-
/**
195-
* @brief An array of method definitions for Object prototype methods
196-
*
197-
*/
198-
static JSMethodDef object_methods[];
199193
};
200194

201195
#endif

src/PyIterableProxyHandler.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static bool iterable_valueOf(JSContext *cx, unsigned argc, JS::Value *vp) {
105105
return toPrimitive(cx, argc, vp);
106106
}
107107

108-
JSMethodDef PyIterableProxyHandler::iterable_methods[] = {
108+
static JSMethodDef iterable_methods[] = {
109109
{"next", iterable_next, 0},
110110
{"valueOf", iterable_valueOf, 0},
111111
{NULL, NULL, 0}
@@ -238,8 +238,6 @@ bool PyIterableProxyHandler::getOwnPropertyDescriptor(
238238
// "constructor" property
239239
bool isConstructorProperty;
240240
if (id.isString() && JS_StringEqualsLiteral(cx, id.toString(), "constructor", &isConstructorProperty) && isConstructorProperty) {
241-
JS::RootedObject global(cx, JS::GetNonCCWObjectGlobal(proxy));
242-
243241
JS::RootedObject rootedObjectPrototype(cx);
244242
if (!JS_GetClassPrototype(cx, JSProto_Object, &rootedObjectPrototype)) {
245243
return false;

src/PyListProxyHandler.cc

-2
Original file line numberDiff line numberDiff line change
@@ -2040,8 +2040,6 @@ bool PyListProxyHandler::getOwnPropertyDescriptor(
20402040
// "constructor" property
20412041
bool isConstructorProperty;
20422042
if (id.isString() && JS_StringEqualsLiteral(cx, id.toString(), "constructor", &isConstructorProperty) && isConstructorProperty) {
2043-
JS::RootedObject global(cx, JS::GetNonCCWObjectGlobal(proxy));
2044-
20452043
JS::RootedObject rootedArrayPrototype(cx);
20462044
if (!JS_GetClassPrototype(cx, JSProto_Array, &rootedArrayPrototype)) {
20472045
return false;

src/PyObjectProxyHandler.cc

+21-48
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,6 @@
2424

2525
const char PyObjectProxyHandler::family = 0;
2626

27-
bool PyObjectProxyHandler::object_toString(JSContext *cx, unsigned argc, JS::Value *vp) {
28-
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
29-
30-
args.rval().setString(JS_NewStringCopyZ(cx, "[object Object]"));
31-
return true;
32-
}
33-
34-
bool PyObjectProxyHandler::object_toLocaleString(JSContext *cx, unsigned argc, JS::Value *vp) {
35-
return object_toString(cx, argc, vp);
36-
}
37-
38-
bool PyObjectProxyHandler::object_valueOf(JSContext *cx, unsigned argc, JS::Value *vp) {
39-
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
40-
41-
JS::RootedObject proxy(cx, JS::ToObject(cx, args.thisv()));
42-
if (!proxy) {
43-
return false;
44-
}
45-
PyObject *self = JS::GetMaybePtrFromReservedSlot<PyObject>(proxy, PyObjectSlot);
46-
47-
// return ref to self
48-
args.rval().set(jsTypeFactory(cx, self));
49-
return true;
50-
}
51-
52-
JSMethodDef PyObjectProxyHandler::object_methods[] = {
53-
{"toString", PyObjectProxyHandler::object_toString, 0},
54-
{"toLocaleString", PyObjectProxyHandler::object_toLocaleString, 0},
55-
{"valueOf", PyObjectProxyHandler::object_valueOf, 0},
56-
{NULL, NULL, 0}
57-
};
58-
5927
bool PyObjectProxyHandler::handleOwnPropertyKeys(JSContext *cx, PyObject *keys, size_t length, JS::MutableHandleIdVector props) {
6028
if (!props.reserve(length)) {
6129
return false; // out of memory
@@ -76,24 +44,29 @@ bool PyObjectProxyHandler::handleGetOwnPropertyDescriptor(JSContext *cx, JS::Han
7644
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc, PyObject *item) {
7745
// see if we're calling a function
7846
if (id.isString()) {
79-
for (size_t index = 0;; index++) {
80-
bool isThatFunction;
81-
const char *methodName = object_methods[index].name;
82-
if (methodName == NULL) {
83-
break;
47+
JS::RootedString idString(cx, id.toString());
48+
const char *methodName = JS_EncodeStringToUTF8(cx, idString).get();
49+
if (!strcmp(methodName, "toString") || !strcmp(methodName, "toLocaleString") || !strcmp(methodName, "valueOf")) {
50+
JS::RootedObject objectPrototype(cx);
51+
if (!JS_GetClassPrototype(cx, JSProto_Object, &objectPrototype)) {
52+
return false;
8453
}
85-
else if (JS_StringEqualsAscii(cx, id.toString(), methodName, &isThatFunction) && isThatFunction) {
86-
JSFunction *newFunction = JS_NewFunction(cx, object_methods[index].call, object_methods[index].nargs, 0, NULL);
87-
if (!newFunction) return false;
88-
JS::RootedObject funObj(cx, JS_GetFunctionObject(newFunction));
89-
desc.set(mozilla::Some(
90-
JS::PropertyDescriptor::Data(
91-
JS::ObjectValue(*funObj),
92-
{JS::PropertyAttribute::Enumerable}
93-
)
94-
));
95-
return true;
54+
55+
JS::RootedValue Object_Prototype_Method(cx);
56+
if (!JS_GetProperty(cx, objectPrototype, methodName, &Object_Prototype_Method)) {
57+
return false;
9658
}
59+
60+
JS::RootedObject rootedObjectPrototypeConstructor(cx, Object_Prototype_Method.toObjectOrNull());
61+
62+
desc.set(mozilla::Some(
63+
JS::PropertyDescriptor::Data(
64+
JS::ObjectValue(*rootedObjectPrototypeConstructor),
65+
{JS::PropertyAttribute::Enumerable}
66+
)
67+
));
68+
69+
return true;
9770
}
9871
}
9972

tests/python/test_objects.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,19 @@ def test_toPrimitive_stdin():
170170

171171
def test_constructor_stdin():
172172
constructor = pm.eval("(obj) => { return obj.constructor; }")(sys.stdin)
173-
assert repr(constructor).__contains__("<pythonmonkey.JSFunctionProxy object at")
173+
assert repr(constructor).__contains__("<pythonmonkey.JSFunctionProxy object at")
174+
175+
176+
def test_toString_is_prototype_toString():
177+
is_to_string_correct = pm.eval("x => x.toString === Object.prototype.toString")
178+
assert is_to_string_correct({})
179+
180+
181+
def test_toString_is_prototype_toLocaleString():
182+
is_to_locale_string_correct = pm.eval("x => x.toLocaleString === Object.prototype.toLocaleString")
183+
assert is_to_locale_string_correct({})
184+
185+
186+
def test_valueof_is_prototype_valueof():
187+
is_valueof_correct = pm.eval("x => x.valueOf === Object.prototype.valueOf")
188+
assert is_valueof_correct({})

0 commit comments

Comments
 (0)