michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "jscompartment.h" michael@0: #include "jsgc.h" michael@0: michael@0: #include "jsapi-tests/tests.h" michael@0: #include "vm/Shape.h" michael@0: michael@0: BEGIN_TEST(testRegExpInstanceProperties) michael@0: { michael@0: jsval regexpProtoVal; michael@0: EVAL("RegExp.prototype", ®expProtoVal); michael@0: michael@0: JSObject *regexpProto = JSVAL_TO_OBJECT(regexpProtoVal); michael@0: michael@0: if (!helper(regexpProto)) michael@0: return false; michael@0: michael@0: JS_GC(cx); michael@0: michael@0: CHECK_EQUAL(regexpProto->compartment()->initialRegExpShape, nullptr); michael@0: michael@0: jsval regexp; michael@0: EVAL("/foopy/", ®exp); michael@0: JSObject *robj = JSVAL_TO_OBJECT(regexp); michael@0: michael@0: CHECK(robj->lastProperty()); michael@0: CHECK_EQUAL(robj->compartment()->initialRegExpShape, robj->lastProperty()); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: /* michael@0: * Do this all in a nested function evaluation so as (hopefully) not to get michael@0: * screwed up by the conservative stack scanner when GCing. michael@0: */ michael@0: MOZ_NEVER_INLINE bool helper(JSObject *regexpProto) michael@0: { michael@0: CHECK(!regexpProto->inDictionaryMode()); michael@0: michael@0: // Verify the compartment's cached shape is being used by RegExp.prototype. michael@0: const js::Shape *shape = regexpProto->lastProperty(); michael@0: js::AutoShapeRooter root(cx, shape); michael@0: for (js::Shape::Range r = shape; michael@0: &r.front() != regexpProto->compartment()->initialRegExpShape; michael@0: r.popFront()) michael@0: { michael@0: CHECK(!r.empty()); michael@0: } michael@0: michael@0: JS::RootedValue v(cx, INT_TO_JSVAL(17)); michael@0: CHECK(JS_SetProperty(cx, regexpProto, "foopy", v)); michael@0: v = INT_TO_JSVAL(42); michael@0: CHECK(JS_SetProperty(cx, regexpProto, "bunky", v)); michael@0: CHECK(JS_DeleteProperty(cx, regexpProto, "foopy")); michael@0: CHECK(regexpProto->inDictionaryMode()); michael@0: michael@0: const js::Shape *shape2 = regexpProto->lastProperty(); michael@0: js::AutoShapeRooter root2(cx, shape2); michael@0: js::Shape::Range r2 = shape2; michael@0: while (!r2.empty()) { michael@0: CHECK(&r2.front() != regexpProto->compartment()->initialRegExpShape); michael@0: r2.popFront(); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: END_TEST(testRegExpInstanceProperties)