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.

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

mercurial