js/src/jsapi-tests/testResolveRecursion.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:56e96a1beb88
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include "jsapi-tests/tests.h"
9
10 /*
11 * Test that resolve hook recursion for the same object and property is
12 * prevented.
13 */
14
15 BEGIN_TEST(testResolveRecursion)
16 {
17 static const JSClass my_resolve_class = {
18 "MyResolve",
19 JSCLASS_NEW_RESOLVE | JSCLASS_HAS_PRIVATE,
20
21 JS_PropertyStub, // add
22 JS_DeletePropertyStub, // delete
23 JS_PropertyStub, // get
24 JS_StrictPropertyStub, // set
25 JS_EnumerateStub,
26 (JSResolveOp) my_resolve,
27 JS_ConvertStub
28 };
29
30 obj1 = obj2 = nullptr;
31 JS::AddObjectRoot(cx, &obj1);
32 JS::AddObjectRoot(cx, &obj2);
33
34 obj1 = JS_NewObject(cx, &my_resolve_class, JS::NullPtr(), JS::NullPtr());
35 CHECK(obj1);
36 obj2 = JS_NewObject(cx, &my_resolve_class, JS::NullPtr(), JS::NullPtr());
37 CHECK(obj2);
38 JS_SetPrivate(obj1, this);
39 JS_SetPrivate(obj2, this);
40
41 JS::RootedValue obj1Val(cx, ObjectValue(*obj1));
42 JS::RootedValue obj2Val(cx, ObjectValue(*obj2));
43 CHECK(JS_DefineProperty(cx, global, "obj1", obj1Val, 0));
44 CHECK(JS_DefineProperty(cx, global, "obj2", obj2Val, 0));
45
46 resolveEntryCount = 0;
47 resolveExitCount = 0;
48
49 /* Start the essence of the test via invoking the first resolve hook. */
50 JS::RootedValue v(cx);
51 EVAL("obj1.x", &v);
52 CHECK_SAME(v, JSVAL_FALSE);
53 CHECK_EQUAL(resolveEntryCount, 4);
54 CHECK_EQUAL(resolveExitCount, 4);
55
56 obj1 = nullptr;
57 obj2 = nullptr;
58 JS::RemoveObjectRoot(cx, &obj1);
59 JS::RemoveObjectRoot(cx, &obj2);
60 return true;
61 }
62
63 JS::Heap<JSObject *> obj1;
64 JS::Heap<JSObject *> obj2;
65 unsigned resolveEntryCount;
66 unsigned resolveExitCount;
67
68 struct AutoIncrCounters {
69
70 AutoIncrCounters(cls_testResolveRecursion *t) : t(t) {
71 t->resolveEntryCount++;
72 }
73
74 ~AutoIncrCounters() {
75 t->resolveExitCount++;
76 }
77
78 cls_testResolveRecursion *t;
79 };
80
81 bool
82 doResolve(JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp)
83 {
84 CHECK_EQUAL(resolveExitCount, 0);
85 AutoIncrCounters incr(this);
86 CHECK_EQUAL(obj, obj1 || obj == obj2);
87
88 CHECK(JSID_IS_STRING(id));
89
90 JSFlatString *str = JS_FlattenString(cx, JSID_TO_STRING(id));
91 CHECK(str);
92 JS::RootedValue v(cx);
93 if (JS_FlatStringEqualsAscii(str, "x")) {
94 if (obj == obj1) {
95 /* First resolve hook invocation. */
96 CHECK_EQUAL(resolveEntryCount, 1);
97 EVAL("obj2.y = true", &v);
98 CHECK_SAME(v, JSVAL_TRUE);
99 CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_FALSE, nullptr, nullptr, 0));
100 objp.set(obj);
101 return true;
102 }
103 if (obj == obj2) {
104 CHECK_EQUAL(resolveEntryCount, 4);
105 objp.set(nullptr);
106 return true;
107 }
108 } else if (JS_FlatStringEqualsAscii(str, "y")) {
109 if (obj == obj2) {
110 CHECK_EQUAL(resolveEntryCount, 2);
111 CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_NULL, nullptr, nullptr, 0));
112 EVAL("obj1.x", &v);
113 CHECK(JSVAL_IS_VOID(v));
114 EVAL("obj1.y", &v);
115 CHECK_SAME(v, JSVAL_ZERO);
116 objp.set(obj);
117 return true;
118 }
119 if (obj == obj1) {
120 CHECK_EQUAL(resolveEntryCount, 3);
121 EVAL("obj1.x", &v);
122 CHECK(JSVAL_IS_VOID(v));
123 EVAL("obj1.y", &v);
124 CHECK(JSVAL_IS_VOID(v));
125 EVAL("obj2.y", &v);
126 CHECK(JSVAL_IS_NULL(v));
127 EVAL("obj2.x", &v);
128 CHECK(JSVAL_IS_VOID(v));
129 EVAL("obj1.y = 0", &v);
130 CHECK_SAME(v, JSVAL_ZERO);
131 objp.set(obj);
132 return true;
133 }
134 }
135 CHECK(false);
136 return false;
137 }
138
139 static bool
140 my_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp)
141 {
142 return static_cast<cls_testResolveRecursion *>(JS_GetPrivate(obj))->
143 doResolve(obj, id, objp);
144 }
145
146 END_TEST(testResolveRecursion)

mercurial