void ObjectWrapper::Key::del(JSContext* cx, JS::HandleObject o) { switch (_type) { case Type::Field: if (JS_DeleteProperty(cx, o, _field)) return; break; case Type::Index: if (JS_DeleteElement(cx, o, _idx)) return; break; case Type::Id: { JS::RootedId id(cx, _id); // For some reason JS_DeletePropertyById doesn't link if (JS_DeleteProperty(cx, o, IdWrapper(cx, id).toString().c_str())) return; break; } case Type::InternedString: { InternedStringId id(cx, _internedString); if (JS_DeleteProperty(cx, o, IdWrapper(cx, id).toString().c_str())) break; } } throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to delete value on a JSObject"); }
void BSONInfo::delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* succeeded) { auto holder = getHolder(obj); if (holder) { if (holder->_readOnly) { uasserted(ErrorCodes::BadValue, "Read only object"); } holder->_altered = true; holder->_removed.insert(IdWrapper(cx, id).toString()); } *succeeded = true; }
void BSONInfo::setProperty( JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp) { auto holder = getHolder(obj); if (holder) { if (holder->_readOnly) { uasserted(ErrorCodes::BadValue, "Read only object"); } auto iter = holder->_removed.find(IdWrapper(cx, id).toString()); if (iter != holder->_removed.end()) { holder->_removed.erase(iter); } holder->_altered = true; } ObjectWrapper(cx, obj).defineProperty(id, vp, JSPROP_ENUMERATE); }
void BSONInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { auto holder = getHolder(obj); *resolvedp = false; if (!holder) { return; } IdWrapper idw(cx, id); if (!holder->_readOnly && holder->_removed.count(idw.toString())) { return; } ObjectWrapper o(cx, obj); std::string sname = IdWrapper(cx, id).toString(); if (holder->_obj.hasField(sname)) { auto elem = holder->_obj[sname]; JS::RootedValue vp(cx); ValueReader(cx, &vp).fromBSONElement(elem, holder->_readOnly); o.defineProperty(id, vp, JSPROP_ENUMERATE); if (!holder->_readOnly && (elem.type() == mongo::Object || elem.type() == mongo::Array)) { // if accessing a subobject, we have no way to know if // modifications are being made on writable objects holder->_altered = true; } *resolvedp = true; } }