Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * Infrastructure for sharing DOMString data with JSStrings.
9 : *
10 : * Importing an nsAString into JS:
11 : * If possible (GetSharedBufferHandle works) use the external string support in
12 : * JS to create a JSString that points to the readable's buffer. We keep a
13 : * reference to the buffer handle until the JSString is finalized.
14 : *
15 : * Exporting a JSString as an nsAReadable:
16 : * Wrap the JSString with a root-holding XPCJSReadableStringWrapper, which roots
17 : * the string and exposes its buffer via the nsAString interface, as
18 : * well as providing refcounting support.
19 : */
20 :
21 : #include "nsAutoPtr.h"
22 : #include "nscore.h"
23 : #include "nsString.h"
24 : #include "nsStringBuffer.h"
25 : #include "jsapi.h"
26 : #include "xpcpublic.h"
27 :
28 : using namespace JS;
29 :
30 : // static
31 : void
32 0 : XPCStringConvert::FinalizeLiteral(const JSStringFinalizer* fin, char16_t* chars)
33 : {
34 0 : }
35 :
36 : const JSStringFinalizer XPCStringConvert::sLiteralFinalizer =
37 : { XPCStringConvert::FinalizeLiteral };
38 :
39 : // static
40 : void
41 15 : XPCStringConvert::FinalizeDOMString(const JSStringFinalizer* fin, char16_t* chars)
42 : {
43 15 : nsStringBuffer* buf = nsStringBuffer::FromData(chars);
44 15 : buf->Release();
45 15 : }
46 :
47 : const JSStringFinalizer XPCStringConvert::sDOMStringFinalizer =
48 : { XPCStringConvert::FinalizeDOMString };
49 :
50 : // convert a readable to a JSString, copying string data
51 : // static
52 : bool
53 380 : XPCStringConvert::ReadableToJSVal(JSContext* cx,
54 : const nsAString& readable,
55 : nsStringBuffer** sharedBuffer,
56 : MutableHandleValue vp)
57 : {
58 380 : *sharedBuffer = nullptr;
59 :
60 380 : uint32_t length = readable.Length();
61 :
62 380 : if (readable.IsLiteral()) {
63 : bool ignored;
64 24 : JSString* str = JS_NewMaybeExternalString(cx,
65 24 : static_cast<const char16_t*>(readable.BeginReading()),
66 24 : length, &sLiteralFinalizer, &ignored);
67 24 : if (!str)
68 0 : return false;
69 24 : vp.setString(str);
70 24 : return true;
71 : }
72 :
73 356 : nsStringBuffer* buf = nsStringBuffer::FromString(readable);
74 356 : if (buf) {
75 : bool shared;
76 216 : if (!StringBufferToJSVal(cx, buf, length, vp, &shared))
77 0 : return false;
78 216 : if (shared)
79 194 : *sharedBuffer = buf;
80 216 : return true;
81 : }
82 :
83 : // blech, have to copy.
84 140 : JSString* str = JS_NewUCStringCopyN(cx, readable.BeginReading(), length);
85 140 : if (!str)
86 0 : return false;
87 140 : vp.setString(str);
88 140 : return true;
89 : }
90 :
91 : namespace xpc {
92 :
93 : bool
94 126 : NonVoidStringToJsval(JSContext* cx, nsAString& str, MutableHandleValue rval)
95 : {
96 : nsStringBuffer* sharedBuffer;
97 126 : if (!XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer, rval))
98 0 : return false;
99 :
100 126 : if (sharedBuffer) {
101 : // The string was shared but ReadableToJSVal didn't addref it.
102 : // Move the ownership from str to jsstr.
103 12 : str.ForgetSharedBuffer();
104 : }
105 126 : return true;
106 : }
107 :
108 : } // namespace xpc
|