1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/public/StructuredClone.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef js_StructuredClone_h 1.11 +#define js_StructuredClone_h 1.12 + 1.13 +#include "mozilla/NullPtr.h" 1.14 + 1.15 +#include <stdint.h> 1.16 + 1.17 +#include "jstypes.h" 1.18 + 1.19 +#include "js/RootingAPI.h" 1.20 +#include "js/TypeDecls.h" 1.21 +#include "js/Value.h" 1.22 + 1.23 +struct JSRuntime; 1.24 +struct JSStructuredCloneReader; 1.25 +struct JSStructuredCloneWriter; 1.26 + 1.27 +// API for the HTML5 internal structured cloning algorithm. 1.28 + 1.29 +namespace JS { 1.30 +enum TransferableOwnership { 1.31 + // Transferable data has not been filled in yet 1.32 + SCTAG_TMO_UNFILLED = 0, 1.33 + 1.34 + // Structured clone buffer does not yet own the data 1.35 + SCTAG_TMO_UNOWNED = 1, 1.36 + 1.37 + // All values at least this large are owned by the clone buffer 1.38 + SCTAG_TMO_FIRST_OWNED = 2, 1.39 + 1.40 + // Data is a pointer that can be freed 1.41 + SCTAG_TMO_ALLOC_DATA = 2, 1.42 + 1.43 + // Data is a SharedArrayBufferObject's buffer 1.44 + SCTAG_TMO_SHARED_BUFFER = 3, 1.45 + 1.46 + // Data is a memory mapped pointer 1.47 + SCTAG_TMO_MAPPED_DATA = 4, 1.48 + 1.49 + // Data is embedding-specific. The engine can free it by calling the 1.50 + // freeTransfer op. The embedding can also use SCTAG_TMO_USER_MIN and 1.51 + // greater, up to 32 bits, to distinguish specific ownership variants. 1.52 + SCTAG_TMO_CUSTOM = 5, 1.53 + 1.54 + SCTAG_TMO_USER_MIN 1.55 +}; 1.56 +} /* namespace JS */ 1.57 + 1.58 +// Read structured data from the reader r. This hook is used to read a value 1.59 +// previously serialized by a call to the WriteStructuredCloneOp hook. 1.60 +// 1.61 +// tag and data are the pair of uint32_t values from the header. The callback 1.62 +// may use the JS_Read* APIs to read any other relevant parts of the object 1.63 +// from the reader r. closure is any value passed to the JS_ReadStructuredClone 1.64 +// function. Return the new object on success, nullptr on error/exception. 1.65 +typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r, 1.66 + uint32_t tag, uint32_t data, void *closure); 1.67 + 1.68 +// Structured data serialization hook. The engine can write primitive values, 1.69 +// Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other 1.70 +// type of object requires application support. This callback must first use 1.71 +// the JS_WriteUint32Pair API to write an object header, passing a value 1.72 +// greater than JS_SCTAG_USER to the tag parameter. Then it can use the 1.73 +// JS_Write* APIs to write any other relevant parts of the value v to the 1.74 +// writer w. closure is any value passed to the JS_WriteStructuredCLone function. 1.75 +// 1.76 +// Return true on success, false on error/exception. 1.77 +typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w, 1.78 + JS::HandleObject obj, void *closure); 1.79 + 1.80 +// This is called when JS_WriteStructuredClone is given an invalid transferable. 1.81 +// To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException 1.82 +// with error set to one of the JS_SCERR_* values. 1.83 +typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid); 1.84 + 1.85 +// This is called when JS_ReadStructuredClone receives a transferable object 1.86 +// not known to the engine. If this hook does not exist or returns false, the 1.87 +// JS engine calls the reportError op if set, otherwise it throws a 1.88 +// DATA_CLONE_ERR DOM Exception. This method is called before any other 1.89 +// callback and must return a non-null object in returnObject on success. 1.90 +typedef bool (*ReadTransferStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r, 1.91 + uint32_t tag, void *content, uint64_t extraData, 1.92 + void *closure, 1.93 + JS::MutableHandleObject returnObject); 1.94 + 1.95 +// Called when JS_WriteStructuredClone receives a transferable object not 1.96 +// handled by the engine. If this hook does not exist or returns false, the JS 1.97 +// engine will call the reportError hook or fall back to throwing a 1.98 +// DATA_CLONE_ERR DOM Exception. This method is called before any other 1.99 +// callback. 1.100 +// 1.101 +// tag: indicates what type of transferable this is. Must be greater than 1.102 +// 0xFFFF0201 (value of the internal SCTAG_TRANSFER_MAP_PENDING_ENTRY) 1.103 +// 1.104 +// ownership: see TransferableOwnership, above. Used to communicate any needed 1.105 +// ownership info to the FreeTransferStructuredCloneOp. 1.106 +// 1.107 +// content, extraData: what the ReadTransferStructuredCloneOp will receive 1.108 +// 1.109 +typedef bool (*TransferStructuredCloneOp)(JSContext *cx, 1.110 + JS::Handle<JSObject*> obj, 1.111 + void *closure, 1.112 + // Output: 1.113 + uint32_t *tag, 1.114 + JS::TransferableOwnership *ownership, 1.115 + void **content, 1.116 + uint64_t *extraData); 1.117 + 1.118 +// Called when JS_ClearStructuredClone has to free an unknown transferable 1.119 +// object. Note that it should never trigger a garbage collection (and will 1.120 +// assert in a debug build if it does.) 1.121 +typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership, 1.122 + void *content, uint64_t extraData, void *closure); 1.123 + 1.124 +// The maximum supported structured-clone serialization format version. Note 1.125 +// that this does not need to be bumped for Transferable-only changes, since 1.126 +// they are never saved to persistent storage. 1.127 +#define JS_STRUCTURED_CLONE_VERSION 2 1.128 + 1.129 +struct JSStructuredCloneCallbacks { 1.130 + ReadStructuredCloneOp read; 1.131 + WriteStructuredCloneOp write; 1.132 + StructuredCloneErrorOp reportError; 1.133 + ReadTransferStructuredCloneOp readTransfer; 1.134 + TransferStructuredCloneOp writeTransfer; 1.135 + FreeTransferStructuredCloneOp freeTransfer; 1.136 +}; 1.137 + 1.138 +// Note: if the *data contains transferable objects, it can be read only once. 1.139 +JS_PUBLIC_API(bool) 1.140 +JS_ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, uint32_t version, 1.141 + JS::MutableHandleValue vp, 1.142 + const JSStructuredCloneCallbacks *optionalCallbacks, void *closure); 1.143 + 1.144 +// Note: On success, the caller is responsible for calling 1.145 +// JS_ClearStructuredClone(*datap, nbytes, optionalCallbacks, closure). 1.146 +JS_PUBLIC_API(bool) 1.147 +JS_WriteStructuredClone(JSContext *cx, JS::HandleValue v, uint64_t **datap, size_t *nbytesp, 1.148 + const JSStructuredCloneCallbacks *optionalCallbacks, 1.149 + void *closure, JS::HandleValue transferable); 1.150 + 1.151 +JS_PUBLIC_API(bool) 1.152 +JS_ClearStructuredClone(uint64_t *data, size_t nbytes, 1.153 + const JSStructuredCloneCallbacks *optionalCallbacks, 1.154 + void *closure); 1.155 + 1.156 +JS_PUBLIC_API(bool) 1.157 +JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes, bool *hasTransferable); 1.158 + 1.159 +JS_PUBLIC_API(bool) 1.160 +JS_StructuredClone(JSContext *cx, JS::HandleValue v, JS::MutableHandleValue vp, 1.161 + const JSStructuredCloneCallbacks *optionalCallbacks, void *closure); 1.162 + 1.163 +// RAII sugar for JS_WriteStructuredClone. 1.164 +class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) { 1.165 + uint64_t *data_; 1.166 + size_t nbytes_; 1.167 + uint32_t version_; 1.168 + const JSStructuredCloneCallbacks *callbacks_; 1.169 + void *closure_; 1.170 + 1.171 + public: 1.172 + JSAutoStructuredCloneBuffer() 1.173 + : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION), 1.174 + callbacks_(nullptr), closure_(nullptr) 1.175 + {} 1.176 + 1.177 + JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks *callbacks, void *closure) 1.178 + : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION), 1.179 + callbacks_(callbacks), closure_(closure) 1.180 + {} 1.181 + 1.182 + JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer &&other); 1.183 + JSAutoStructuredCloneBuffer &operator=(JSAutoStructuredCloneBuffer &&other); 1.184 + 1.185 + ~JSAutoStructuredCloneBuffer() { clear(); } 1.186 + 1.187 + uint64_t *data() const { return data_; } 1.188 + size_t nbytes() const { return nbytes_; } 1.189 + 1.190 + void clear(); 1.191 + 1.192 + // Copy some memory. It will be automatically freed by the destructor. 1.193 + bool copy(const uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION); 1.194 + 1.195 + // Adopt some memory. It will be automatically freed by the destructor. 1.196 + // data must have been allocated by the JS engine (e.g., extracted via 1.197 + // JSAutoStructuredCloneBuffer::steal). 1.198 + void adopt(uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION); 1.199 + 1.200 + // Remove the buffer so that it will not be automatically freed. 1.201 + // After this, the caller is responsible for feeding the memory back to 1.202 + // JSAutoStructuredCloneBuffer::adopt. 1.203 + void steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp=nullptr); 1.204 + 1.205 + bool read(JSContext *cx, JS::MutableHandleValue vp, 1.206 + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); 1.207 + 1.208 + bool write(JSContext *cx, JS::HandleValue v, 1.209 + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); 1.210 + 1.211 + bool write(JSContext *cx, JS::HandleValue v, JS::HandleValue transferable, 1.212 + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); 1.213 + 1.214 + private: 1.215 + // Copy and assignment are not supported. 1.216 + JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE; 1.217 + JSAutoStructuredCloneBuffer &operator=(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE; 1.218 +}; 1.219 + 1.220 +// The range of tag values the application may use for its own custom object types. 1.221 +#define JS_SCTAG_USER_MIN ((uint32_t) 0xFFFF8000) 1.222 +#define JS_SCTAG_USER_MAX ((uint32_t) 0xFFFFFFFF) 1.223 + 1.224 +#define JS_SCERR_RECURSION 0 1.225 +#define JS_SCERR_TRANSFERABLE 1 1.226 + 1.227 +JS_PUBLIC_API(void) 1.228 +JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks); 1.229 + 1.230 +JS_PUBLIC_API(bool) 1.231 +JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2); 1.232 + 1.233 +JS_PUBLIC_API(bool) 1.234 +JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len); 1.235 + 1.236 +JS_PUBLIC_API(bool) 1.237 +JS_ReadTypedArray(JSStructuredCloneReader *r, JS::MutableHandleValue vp); 1.238 + 1.239 +JS_PUBLIC_API(bool) 1.240 +JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data); 1.241 + 1.242 +JS_PUBLIC_API(bool) 1.243 +JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len); 1.244 + 1.245 +JS_PUBLIC_API(bool) 1.246 +JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::HandleValue v); 1.247 + 1.248 +#endif /* js_StructuredClone_h */