diff options
author | Jason Carey <jcarey@argv.me> | 2015-10-06 20:42:23 -0400 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2015-10-06 20:42:23 -0400 |
commit | cad0c421371e55fdf65c0be4badd23120bec72c1 (patch) | |
tree | 104284cbb97a1810f34269ae11738b1c39c6e767 /src/mongo/scripting | |
parent | b0c83fe82db91e239b706c21636e9aae318e640f (diff) | |
download | mongo-cad0c421371e55fdf65c0be4badd23120bec72c1.tar.gz |
SERVER-19977 Re-work JS ObjectID
Rather than storing a string with the encoded oid, just store a pointer
to the oid and convert it to a string on demand for "str" access.
Diffstat (limited to 'src/mongo/scripting')
-rw-r--r-- | src/mongo/scripting/mozjs/oid.cpp | 72 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/oid.h | 10 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/valuereader.cpp | 6 |
3 files changed, 67 insertions, 21 deletions
diff --git a/src/mongo/scripting/mozjs/oid.cpp b/src/mongo/scripting/mozjs/oid.cpp index 8c0debaccc1..e24dd3f0aca 100644 --- a/src/mongo/scripting/mozjs/oid.cpp +++ b/src/mongo/scripting/mozjs/oid.cpp @@ -42,46 +42,86 @@ namespace mongo { namespace mozjs { const JSFunctionSpec OIDInfo::methods[2] = { - MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, OIDInfo), JS_FS_END, + MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(toString, OIDInfo), JS_FS_END, }; const char* const OIDInfo::className = "ObjectId"; -void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) { - ObjectWrapper o(cx, args.thisv()); +void OIDInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto oid = static_cast<OID*>(JS_GetPrivate(obj)); - if (!o.hasField("str")) - uasserted(ErrorCodes::BadValue, "Must have \"str\" field"); + if (oid) { + delete oid; + } +} - JS::RootedValue value(cx); - o.getValue("str", &value); +void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) { + auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull())); - std::string str = str::stream() << "ObjectId(\"" << ValueWriter(cx, value).toString() << "\")"; + std::string str = str::stream() << "ObjectId(\"" << oid->toString() << "\")"; ValueReader(cx, args.rval()).fromStringData(str); } -void OIDInfo::construct(JSContext* cx, JS::CallArgs args) { - auto scope = getScope(cx); +void OIDInfo::Functions::getter::call(JSContext* cx, JS::CallArgs args) { + auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull())); - auto oid = stdx::make_unique<OID>(); + ValueReader(cx, args.rval()).fromStringData(oid->toString()); +} +void OIDInfo::construct(JSContext* cx, JS::CallArgs args) { + OID oid; if (args.length() == 0) { - oid->init(); + oid.init(); } else { auto str = ValueWriter(cx, args.get(0)).toString(); Scope::validateObjectIdString(str); - oid->init(str); + oid.init(str); } + make(cx, oid, args.rval()); +} + +void OIDInfo::make(JSContext* cx, const OID& oid, JS::MutableHandleValue out) { + auto scope = getScope(cx); + + auto oidHolder = stdx::make_unique<OID>(oid); JS::RootedObject thisv(cx); scope->getProto<OIDInfo>().newObject(&thisv); - ObjectWrapper o(cx, thisv); + JS_SetPrivate(thisv, oidHolder.release()); + + out.setObjectOrNull(thisv); +} + +OID OIDInfo::getOID(JSContext* cx, JS::HandleValue value) { + JS::RootedObject obj(cx, value.toObjectOrNull()); + return getOID(cx, obj); +} - o.setString("str", oid->toString()); +OID OIDInfo::getOID(JSContext* cx, JS::HandleObject object) { + auto oid = static_cast<OID*>(JS_GetPrivate(object)); - args.rval().setObjectOrNull(thisv); + if (oid) { + return *oid; + } + + uasserted(ErrorCodes::BadValue, "Can't call getOID on OID prototype"); +} + +void OIDInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::HandleObject proto) { + JS::RootedValue undef(cx); + undef.setUndefined(); + + if (!JS_DefinePropertyById(cx, + proto, + getScope(cx)->getInternedStringId(InternedString::str), + undef, + JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_SHARED, + smUtils::wrapConstrainedMethod<Functions::getter, true, OIDInfo>, + nullptr)) { + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); + } } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/oid.h b/src/mongo/scripting/mozjs/oid.h index 8171d2d2aac..3d723b97003 100644 --- a/src/mongo/scripting/mozjs/oid.h +++ b/src/mongo/scripting/mozjs/oid.h @@ -40,14 +40,24 @@ namespace mozjs { */ struct OIDInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { + MONGO_DECLARE_JS_FUNCTION(getter); MONGO_DECLARE_JS_FUNCTION(toString); }; static const JSFunctionSpec methods[2]; + static const unsigned classFlags = JSCLASS_HAS_PRIVATE; + static const char* const className; + + static void postInstall(JSContext* cx, JS::HandleObject global, JS::HandleObject proto); + + static void make(JSContext* cx, const OID& oid, JS::MutableHandleValue out); + static OID getOID(JSContext* cx, JS::HandleValue value); + static OID getOID(JSContext* cx, JS::HandleObject object); }; } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/valuereader.cpp b/src/mongo/scripting/mozjs/valuereader.cpp index 71be53c6ff2..b78ed461297 100644 --- a/src/mongo/scripting/mozjs/valuereader.cpp +++ b/src/mongo/scripting/mozjs/valuereader.cpp @@ -66,11 +66,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent fromStringData(elem.valueStringData()); return; case mongo::jstOID: { - JS::AutoValueArray<1> args(_context); - - ValueReader(_context, args[0]).fromStringData(elem.OID().toString()); - - scope->getProto<OIDInfo>().newInstance(args, _value); + OIDInfo::make(_context, elem.OID(), _value); return; } case mongo::NumberDouble: |