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: /* 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: /* michael@0: * Infrastructure for sharing DOMString data with JSStrings. michael@0: * michael@0: * Importing an nsAString into JS: michael@0: * If possible (GetSharedBufferHandle works) use the external string support in michael@0: * JS to create a JSString that points to the readable's buffer. We keep a michael@0: * reference to the buffer handle until the JSString is finalized. michael@0: * michael@0: * Exporting a JSString as an nsAReadable: michael@0: * Wrap the JSString with a root-holding XPCJSReadableStringWrapper, which roots michael@0: * the string and exposes its buffer via the nsAString interface, as michael@0: * well as providing refcounting support. michael@0: */ michael@0: michael@0: #include "nscore.h" michael@0: #include "nsString.h" michael@0: #include "nsStringBuffer.h" michael@0: #include "jsapi.h" michael@0: #include "xpcpublic.h" michael@0: michael@0: using namespace JS; michael@0: michael@0: // static michael@0: void michael@0: XPCStringConvert::FreeZoneCache(JS::Zone *zone) michael@0: { michael@0: // Put the zone user data into an AutoPtr (which will do the cleanup for us), michael@0: // and null out the user data (which may already be null). michael@0: nsAutoPtr cache(static_cast(JS_GetZoneUserData(zone))); michael@0: JS_SetZoneUserData(zone, nullptr); michael@0: } michael@0: michael@0: // static michael@0: void michael@0: XPCStringConvert::ClearZoneCache(JS::Zone *zone) michael@0: { michael@0: ZoneStringCache *cache = static_cast(JS_GetZoneUserData(zone)); michael@0: if (cache) { michael@0: cache->mBuffer = nullptr; michael@0: cache->mString = nullptr; michael@0: } michael@0: } michael@0: michael@0: // static michael@0: void michael@0: XPCStringConvert::FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars) michael@0: { michael@0: } michael@0: michael@0: const JSStringFinalizer XPCStringConvert::sLiteralFinalizer = michael@0: { XPCStringConvert::FinalizeLiteral }; michael@0: michael@0: // static michael@0: void michael@0: XPCStringConvert::FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars) michael@0: { michael@0: nsStringBuffer* buf = nsStringBuffer::FromData(chars); michael@0: buf->Release(); michael@0: } michael@0: michael@0: const JSStringFinalizer XPCStringConvert::sDOMStringFinalizer = michael@0: { XPCStringConvert::FinalizeDOMString }; michael@0: michael@0: // convert a readable to a JSString, copying string data michael@0: // static michael@0: bool michael@0: XPCStringConvert::ReadableToJSVal(JSContext *cx, michael@0: const nsAString &readable, michael@0: nsStringBuffer** sharedBuffer, michael@0: MutableHandleValue vp) michael@0: { michael@0: *sharedBuffer = nullptr; michael@0: michael@0: uint32_t length = readable.Length(); michael@0: michael@0: if (readable.IsLiteral()) { michael@0: JSString *str = JS_NewExternalString(cx, michael@0: static_cast(readable.BeginReading()), michael@0: length, &sLiteralFinalizer); michael@0: if (!str) michael@0: return false; michael@0: vp.setString(str); michael@0: return true; michael@0: } michael@0: michael@0: nsStringBuffer *buf = nsStringBuffer::FromString(readable); michael@0: if (buf) { michael@0: bool shared; michael@0: if (!StringBufferToJSVal(cx, buf, length, vp, &shared)) michael@0: return false; michael@0: if (shared) michael@0: *sharedBuffer = buf; michael@0: return true; michael@0: } michael@0: michael@0: // blech, have to copy. michael@0: JSString *str = JS_NewUCStringCopyN(cx, readable.BeginReading(), length); michael@0: if (!str) michael@0: return false; michael@0: vp.setString(str); michael@0: return true; michael@0: }