js/public/StructuredClone.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef js_StructuredClone_h
michael@0 8 #define js_StructuredClone_h
michael@0 9
michael@0 10 #include "mozilla/NullPtr.h"
michael@0 11
michael@0 12 #include <stdint.h>
michael@0 13
michael@0 14 #include "jstypes.h"
michael@0 15
michael@0 16 #include "js/RootingAPI.h"
michael@0 17 #include "js/TypeDecls.h"
michael@0 18 #include "js/Value.h"
michael@0 19
michael@0 20 struct JSRuntime;
michael@0 21 struct JSStructuredCloneReader;
michael@0 22 struct JSStructuredCloneWriter;
michael@0 23
michael@0 24 // API for the HTML5 internal structured cloning algorithm.
michael@0 25
michael@0 26 namespace JS {
michael@0 27 enum TransferableOwnership {
michael@0 28 // Transferable data has not been filled in yet
michael@0 29 SCTAG_TMO_UNFILLED = 0,
michael@0 30
michael@0 31 // Structured clone buffer does not yet own the data
michael@0 32 SCTAG_TMO_UNOWNED = 1,
michael@0 33
michael@0 34 // All values at least this large are owned by the clone buffer
michael@0 35 SCTAG_TMO_FIRST_OWNED = 2,
michael@0 36
michael@0 37 // Data is a pointer that can be freed
michael@0 38 SCTAG_TMO_ALLOC_DATA = 2,
michael@0 39
michael@0 40 // Data is a SharedArrayBufferObject's buffer
michael@0 41 SCTAG_TMO_SHARED_BUFFER = 3,
michael@0 42
michael@0 43 // Data is a memory mapped pointer
michael@0 44 SCTAG_TMO_MAPPED_DATA = 4,
michael@0 45
michael@0 46 // Data is embedding-specific. The engine can free it by calling the
michael@0 47 // freeTransfer op. The embedding can also use SCTAG_TMO_USER_MIN and
michael@0 48 // greater, up to 32 bits, to distinguish specific ownership variants.
michael@0 49 SCTAG_TMO_CUSTOM = 5,
michael@0 50
michael@0 51 SCTAG_TMO_USER_MIN
michael@0 52 };
michael@0 53 } /* namespace JS */
michael@0 54
michael@0 55 // Read structured data from the reader r. This hook is used to read a value
michael@0 56 // previously serialized by a call to the WriteStructuredCloneOp hook.
michael@0 57 //
michael@0 58 // tag and data are the pair of uint32_t values from the header. The callback
michael@0 59 // may use the JS_Read* APIs to read any other relevant parts of the object
michael@0 60 // from the reader r. closure is any value passed to the JS_ReadStructuredClone
michael@0 61 // function. Return the new object on success, nullptr on error/exception.
michael@0 62 typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
michael@0 63 uint32_t tag, uint32_t data, void *closure);
michael@0 64
michael@0 65 // Structured data serialization hook. The engine can write primitive values,
michael@0 66 // Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other
michael@0 67 // type of object requires application support. This callback must first use
michael@0 68 // the JS_WriteUint32Pair API to write an object header, passing a value
michael@0 69 // greater than JS_SCTAG_USER to the tag parameter. Then it can use the
michael@0 70 // JS_Write* APIs to write any other relevant parts of the value v to the
michael@0 71 // writer w. closure is any value passed to the JS_WriteStructuredCLone function.
michael@0 72 //
michael@0 73 // Return true on success, false on error/exception.
michael@0 74 typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
michael@0 75 JS::HandleObject obj, void *closure);
michael@0 76
michael@0 77 // This is called when JS_WriteStructuredClone is given an invalid transferable.
michael@0 78 // To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException
michael@0 79 // with error set to one of the JS_SCERR_* values.
michael@0 80 typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid);
michael@0 81
michael@0 82 // This is called when JS_ReadStructuredClone receives a transferable object
michael@0 83 // not known to the engine. If this hook does not exist or returns false, the
michael@0 84 // JS engine calls the reportError op if set, otherwise it throws a
michael@0 85 // DATA_CLONE_ERR DOM Exception. This method is called before any other
michael@0 86 // callback and must return a non-null object in returnObject on success.
michael@0 87 typedef bool (*ReadTransferStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
michael@0 88 uint32_t tag, void *content, uint64_t extraData,
michael@0 89 void *closure,
michael@0 90 JS::MutableHandleObject returnObject);
michael@0 91
michael@0 92 // Called when JS_WriteStructuredClone receives a transferable object not
michael@0 93 // handled by the engine. If this hook does not exist or returns false, the JS
michael@0 94 // engine will call the reportError hook or fall back to throwing a
michael@0 95 // DATA_CLONE_ERR DOM Exception. This method is called before any other
michael@0 96 // callback.
michael@0 97 //
michael@0 98 // tag: indicates what type of transferable this is. Must be greater than
michael@0 99 // 0xFFFF0201 (value of the internal SCTAG_TRANSFER_MAP_PENDING_ENTRY)
michael@0 100 //
michael@0 101 // ownership: see TransferableOwnership, above. Used to communicate any needed
michael@0 102 // ownership info to the FreeTransferStructuredCloneOp.
michael@0 103 //
michael@0 104 // content, extraData: what the ReadTransferStructuredCloneOp will receive
michael@0 105 //
michael@0 106 typedef bool (*TransferStructuredCloneOp)(JSContext *cx,
michael@0 107 JS::Handle<JSObject*> obj,
michael@0 108 void *closure,
michael@0 109 // Output:
michael@0 110 uint32_t *tag,
michael@0 111 JS::TransferableOwnership *ownership,
michael@0 112 void **content,
michael@0 113 uint64_t *extraData);
michael@0 114
michael@0 115 // Called when JS_ClearStructuredClone has to free an unknown transferable
michael@0 116 // object. Note that it should never trigger a garbage collection (and will
michael@0 117 // assert in a debug build if it does.)
michael@0 118 typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership,
michael@0 119 void *content, uint64_t extraData, void *closure);
michael@0 120
michael@0 121 // The maximum supported structured-clone serialization format version. Note
michael@0 122 // that this does not need to be bumped for Transferable-only changes, since
michael@0 123 // they are never saved to persistent storage.
michael@0 124 #define JS_STRUCTURED_CLONE_VERSION 2
michael@0 125
michael@0 126 struct JSStructuredCloneCallbacks {
michael@0 127 ReadStructuredCloneOp read;
michael@0 128 WriteStructuredCloneOp write;
michael@0 129 StructuredCloneErrorOp reportError;
michael@0 130 ReadTransferStructuredCloneOp readTransfer;
michael@0 131 TransferStructuredCloneOp writeTransfer;
michael@0 132 FreeTransferStructuredCloneOp freeTransfer;
michael@0 133 };
michael@0 134
michael@0 135 // Note: if the *data contains transferable objects, it can be read only once.
michael@0 136 JS_PUBLIC_API(bool)
michael@0 137 JS_ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, uint32_t version,
michael@0 138 JS::MutableHandleValue vp,
michael@0 139 const JSStructuredCloneCallbacks *optionalCallbacks, void *closure);
michael@0 140
michael@0 141 // Note: On success, the caller is responsible for calling
michael@0 142 // JS_ClearStructuredClone(*datap, nbytes, optionalCallbacks, closure).
michael@0 143 JS_PUBLIC_API(bool)
michael@0 144 JS_WriteStructuredClone(JSContext *cx, JS::HandleValue v, uint64_t **datap, size_t *nbytesp,
michael@0 145 const JSStructuredCloneCallbacks *optionalCallbacks,
michael@0 146 void *closure, JS::HandleValue transferable);
michael@0 147
michael@0 148 JS_PUBLIC_API(bool)
michael@0 149 JS_ClearStructuredClone(uint64_t *data, size_t nbytes,
michael@0 150 const JSStructuredCloneCallbacks *optionalCallbacks,
michael@0 151 void *closure);
michael@0 152
michael@0 153 JS_PUBLIC_API(bool)
michael@0 154 JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes, bool *hasTransferable);
michael@0 155
michael@0 156 JS_PUBLIC_API(bool)
michael@0 157 JS_StructuredClone(JSContext *cx, JS::HandleValue v, JS::MutableHandleValue vp,
michael@0 158 const JSStructuredCloneCallbacks *optionalCallbacks, void *closure);
michael@0 159
michael@0 160 // RAII sugar for JS_WriteStructuredClone.
michael@0 161 class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
michael@0 162 uint64_t *data_;
michael@0 163 size_t nbytes_;
michael@0 164 uint32_t version_;
michael@0 165 const JSStructuredCloneCallbacks *callbacks_;
michael@0 166 void *closure_;
michael@0 167
michael@0 168 public:
michael@0 169 JSAutoStructuredCloneBuffer()
michael@0 170 : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
michael@0 171 callbacks_(nullptr), closure_(nullptr)
michael@0 172 {}
michael@0 173
michael@0 174 JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks *callbacks, void *closure)
michael@0 175 : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION),
michael@0 176 callbacks_(callbacks), closure_(closure)
michael@0 177 {}
michael@0 178
michael@0 179 JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer &&other);
michael@0 180 JSAutoStructuredCloneBuffer &operator=(JSAutoStructuredCloneBuffer &&other);
michael@0 181
michael@0 182 ~JSAutoStructuredCloneBuffer() { clear(); }
michael@0 183
michael@0 184 uint64_t *data() const { return data_; }
michael@0 185 size_t nbytes() const { return nbytes_; }
michael@0 186
michael@0 187 void clear();
michael@0 188
michael@0 189 // Copy some memory. It will be automatically freed by the destructor.
michael@0 190 bool copy(const uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
michael@0 191
michael@0 192 // Adopt some memory. It will be automatically freed by the destructor.
michael@0 193 // data must have been allocated by the JS engine (e.g., extracted via
michael@0 194 // JSAutoStructuredCloneBuffer::steal).
michael@0 195 void adopt(uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
michael@0 196
michael@0 197 // Remove the buffer so that it will not be automatically freed.
michael@0 198 // After this, the caller is responsible for feeding the memory back to
michael@0 199 // JSAutoStructuredCloneBuffer::adopt.
michael@0 200 void steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp=nullptr);
michael@0 201
michael@0 202 bool read(JSContext *cx, JS::MutableHandleValue vp,
michael@0 203 const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr);
michael@0 204
michael@0 205 bool write(JSContext *cx, JS::HandleValue v,
michael@0 206 const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr);
michael@0 207
michael@0 208 bool write(JSContext *cx, JS::HandleValue v, JS::HandleValue transferable,
michael@0 209 const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr);
michael@0 210
michael@0 211 private:
michael@0 212 // Copy and assignment are not supported.
michael@0 213 JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE;
michael@0 214 JSAutoStructuredCloneBuffer &operator=(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE;
michael@0 215 };
michael@0 216
michael@0 217 // The range of tag values the application may use for its own custom object types.
michael@0 218 #define JS_SCTAG_USER_MIN ((uint32_t) 0xFFFF8000)
michael@0 219 #define JS_SCTAG_USER_MAX ((uint32_t) 0xFFFFFFFF)
michael@0 220
michael@0 221 #define JS_SCERR_RECURSION 0
michael@0 222 #define JS_SCERR_TRANSFERABLE 1
michael@0 223
michael@0 224 JS_PUBLIC_API(void)
michael@0 225 JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks);
michael@0 226
michael@0 227 JS_PUBLIC_API(bool)
michael@0 228 JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2);
michael@0 229
michael@0 230 JS_PUBLIC_API(bool)
michael@0 231 JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len);
michael@0 232
michael@0 233 JS_PUBLIC_API(bool)
michael@0 234 JS_ReadTypedArray(JSStructuredCloneReader *r, JS::MutableHandleValue vp);
michael@0 235
michael@0 236 JS_PUBLIC_API(bool)
michael@0 237 JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data);
michael@0 238
michael@0 239 JS_PUBLIC_API(bool)
michael@0 240 JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len);
michael@0 241
michael@0 242 JS_PUBLIC_API(bool)
michael@0 243 JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::HandleValue v);
michael@0 244
michael@0 245 #endif /* js_StructuredClone_h */

mercurial