bool PropertyTree::insertChild(ExclusiveContext *cx, Shape *parent, Shape *child) { JS_ASSERT(!parent->inDictionary()); JS_ASSERT(!child->parent); JS_ASSERT(!child->inDictionary()); JS_ASSERT(child->compartment() == parent->compartment()); JS_ASSERT(cx->isInsideCurrentCompartment(this)); KidsPointer *kidp = &parent->kids; if (kidp->isNull()) { child->setParent(parent); kidp->setShape(child); return true; } if (kidp->isShape()) { Shape *shape = kidp->toShape(); JS_ASSERT(shape != child); JS_ASSERT(!shape->matches(child)); KidsHash *hash = HashChildren(shape, child); if (!hash) { js_ReportOutOfMemory(cx); return false; } kidp->setHash(hash); child->setParent(parent); return true; } if (!kidp->toHash()->putNew(child, child)) { js_ReportOutOfMemory(cx); return false; } child->setParent(parent); return true; }
bool PropertyTree::insertChild(JSContext *cx, UnrootedShape parent, UnrootedShape child) { JS_ASSERT(!parent->inDictionary()); JS_ASSERT(!child->parent); JS_ASSERT(!child->inDictionary()); JS_ASSERT(cx->compartment == compartment); JS_ASSERT(child->compartment() == parent->compartment()); KidsPointer *kidp = &parent->kids; if (kidp->isNull()) { child->setParent(parent); kidp->setShape(child); return true; } if (kidp->isShape()) { UnrootedShape shape = kidp->toShape(); JS_ASSERT(shape != child); JS_ASSERT(!shape->matches(child)); KidsHash *hash = HashChildren(shape, child); if (!hash) { JS_ReportOutOfMemory(cx); return false; } kidp->setHash(hash); child->setParent(parent); return true; } if (!kidp->toHash()->putNew(child, child)) { JS_ReportOutOfMemory(cx); return false; } child->setParent(parent); return true; }
void Shape::removeChild(Shape *child) { MOZ_ASSERT(!child->inDictionary()); MOZ_ASSERT(child->parent == this); KidsPointer *kidp = &kids; if (kidp->isShape()) { MOZ_ASSERT(kidp->toShape() == child); kidp->setNull(); child->parent = nullptr; return; } KidsHash *hash = kidp->toHash(); MOZ_ASSERT(hash->count() >= 2); /* otherwise kidp->isShape() should be true */ #ifdef DEBUG size_t oldCount = hash->count(); #endif hash->remove(StackShape(child)); child->parent = nullptr; MOZ_ASSERT(hash->count() == oldCount - 1); if (hash->count() == 1) { /* Convert from HASH form back to SHAPE form. */ KidsHash::Range r = hash->all(); Shape *otherChild = r.front(); MOZ_ASSERT((r.popFront(), r.empty())); /* No more elements! */ kidp->setShape(otherChild); js_delete(hash); } }