diff -r 000000000000 -r 6474c204b198 js/xpconnect/src/XPCString.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/xpconnect/src/XPCString.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=99: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Infrastructure for sharing DOMString data with JSStrings. + * + * Importing an nsAString into JS: + * If possible (GetSharedBufferHandle works) use the external string support in + * JS to create a JSString that points to the readable's buffer. We keep a + * reference to the buffer handle until the JSString is finalized. + * + * Exporting a JSString as an nsAReadable: + * Wrap the JSString with a root-holding XPCJSReadableStringWrapper, which roots + * the string and exposes its buffer via the nsAString interface, as + * well as providing refcounting support. + */ + +#include "nscore.h" +#include "nsString.h" +#include "nsStringBuffer.h" +#include "jsapi.h" +#include "xpcpublic.h" + +using namespace JS; + +// static +void +XPCStringConvert::FreeZoneCache(JS::Zone *zone) +{ + // Put the zone user data into an AutoPtr (which will do the cleanup for us), + // and null out the user data (which may already be null). + nsAutoPtr cache(static_cast(JS_GetZoneUserData(zone))); + JS_SetZoneUserData(zone, nullptr); +} + +// static +void +XPCStringConvert::ClearZoneCache(JS::Zone *zone) +{ + ZoneStringCache *cache = static_cast(JS_GetZoneUserData(zone)); + if (cache) { + cache->mBuffer = nullptr; + cache->mString = nullptr; + } +} + +// static +void +XPCStringConvert::FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars) +{ +} + +const JSStringFinalizer XPCStringConvert::sLiteralFinalizer = + { XPCStringConvert::FinalizeLiteral }; + +// static +void +XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars) +{ + nsStringBuffer* buf = nsStringBuffer::FromData(chars); + buf->Release(); +} + +const JSStringFinalizer XPCStringConvert::sDOMStringFinalizer = + { XPCStringConvert::FinalizeDOMString }; + +// convert a readable to a JSString, copying string data +// static +bool +XPCStringConvert::ReadableToJSVal(JSContext *cx, + const nsAString &readable, + nsStringBuffer** sharedBuffer, + MutableHandleValue vp) +{ + *sharedBuffer = nullptr; + + uint32_t length = readable.Length(); + + if (readable.IsLiteral()) { + JSString *str = JS_NewExternalString(cx, + static_cast(readable.BeginReading()), + length, &sLiteralFinalizer); + if (!str) + return false; + vp.setString(str); + return true; + } + + nsStringBuffer *buf = nsStringBuffer::FromString(readable); + if (buf) { + bool shared; + if (!StringBufferToJSVal(cx, buf, length, vp, &shared)) + return false; + if (shared) + *sharedBuffer = buf; + return true; + } + + // blech, have to copy. + JSString *str = JS_NewUCStringCopyN(cx, readable.BeginReading(), length); + if (!str) + return false; + vp.setString(str); + return true; +}