diff -r 000000000000 -r 6474c204b198 js/public/StructuredClone.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/public/StructuredClone.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_StructuredClone_h +#define js_StructuredClone_h + +#include "mozilla/NullPtr.h" + +#include + +#include "jstypes.h" + +#include "js/RootingAPI.h" +#include "js/TypeDecls.h" +#include "js/Value.h" + +struct JSRuntime; +struct JSStructuredCloneReader; +struct JSStructuredCloneWriter; + +// API for the HTML5 internal structured cloning algorithm. + +namespace JS { +enum TransferableOwnership { + // Transferable data has not been filled in yet + SCTAG_TMO_UNFILLED = 0, + + // Structured clone buffer does not yet own the data + SCTAG_TMO_UNOWNED = 1, + + // All values at least this large are owned by the clone buffer + SCTAG_TMO_FIRST_OWNED = 2, + + // Data is a pointer that can be freed + SCTAG_TMO_ALLOC_DATA = 2, + + // Data is a SharedArrayBufferObject's buffer + SCTAG_TMO_SHARED_BUFFER = 3, + + // Data is a memory mapped pointer + SCTAG_TMO_MAPPED_DATA = 4, + + // Data is embedding-specific. The engine can free it by calling the + // freeTransfer op. The embedding can also use SCTAG_TMO_USER_MIN and + // greater, up to 32 bits, to distinguish specific ownership variants. + SCTAG_TMO_CUSTOM = 5, + + SCTAG_TMO_USER_MIN +}; +} /* namespace JS */ + +// Read structured data from the reader r. This hook is used to read a value +// previously serialized by a call to the WriteStructuredCloneOp hook. +// +// tag and data are the pair of uint32_t values from the header. The callback +// may use the JS_Read* APIs to read any other relevant parts of the object +// from the reader r. closure is any value passed to the JS_ReadStructuredClone +// function. Return the new object on success, nullptr on error/exception. +typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r, + uint32_t tag, uint32_t data, void *closure); + +// Structured data serialization hook. The engine can write primitive values, +// Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other +// type of object requires application support. This callback must first use +// the JS_WriteUint32Pair API to write an object header, passing a value +// greater than JS_SCTAG_USER to the tag parameter. Then it can use the +// JS_Write* APIs to write any other relevant parts of the value v to the +// writer w. closure is any value passed to the JS_WriteStructuredCLone function. +// +// Return true on success, false on error/exception. +typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w, + JS::HandleObject obj, void *closure); + +// This is called when JS_WriteStructuredClone is given an invalid transferable. +// To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException +// with error set to one of the JS_SCERR_* values. +typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid); + +// This is called when JS_ReadStructuredClone receives a transferable object +// not known to the engine. If this hook does not exist or returns false, the +// JS engine calls the reportError op if set, otherwise it throws a +// DATA_CLONE_ERR DOM Exception. This method is called before any other +// callback and must return a non-null object in returnObject on success. +typedef bool (*ReadTransferStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r, + uint32_t tag, void *content, uint64_t extraData, + void *closure, + JS::MutableHandleObject returnObject); + +// Called when JS_WriteStructuredClone receives a transferable object not +// handled by the engine. If this hook does not exist or returns false, the JS +// engine will call the reportError hook or fall back to throwing a +// DATA_CLONE_ERR DOM Exception. This method is called before any other +// callback. +// +// tag: indicates what type of transferable this is. Must be greater than +// 0xFFFF0201 (value of the internal SCTAG_TRANSFER_MAP_PENDING_ENTRY) +// +// ownership: see TransferableOwnership, above. Used to communicate any needed +// ownership info to the FreeTransferStructuredCloneOp. +// +// content, extraData: what the ReadTransferStructuredCloneOp will receive +// +typedef bool (*TransferStructuredCloneOp)(JSContext *cx, + JS::Handle obj, + void *closure, + // Output: + uint32_t *tag, + JS::TransferableOwnership *ownership, + void **content, + uint64_t *extraData); + +// Called when JS_ClearStructuredClone has to free an unknown transferable +// object. Note that it should never trigger a garbage collection (and will +// assert in a debug build if it does.) +typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership, + void *content, uint64_t extraData, void *closure); + +// The maximum supported structured-clone serialization format version. Note +// that this does not need to be bumped for Transferable-only changes, since +// they are never saved to persistent storage. +#define JS_STRUCTURED_CLONE_VERSION 2 + +struct JSStructuredCloneCallbacks { + ReadStructuredCloneOp read; + WriteStructuredCloneOp write; + StructuredCloneErrorOp reportError; + ReadTransferStructuredCloneOp readTransfer; + TransferStructuredCloneOp writeTransfer; + FreeTransferStructuredCloneOp freeTransfer; +}; + +// Note: if the *data contains transferable objects, it can be read only once. +JS_PUBLIC_API(bool) +JS_ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, uint32_t version, + JS::MutableHandleValue vp, + const JSStructuredCloneCallbacks *optionalCallbacks, void *closure); + +// Note: On success, the caller is responsible for calling +// JS_ClearStructuredClone(*datap, nbytes, optionalCallbacks, closure). +JS_PUBLIC_API(bool) +JS_WriteStructuredClone(JSContext *cx, JS::HandleValue v, uint64_t **datap, size_t *nbytesp, + const JSStructuredCloneCallbacks *optionalCallbacks, + void *closure, JS::HandleValue transferable); + +JS_PUBLIC_API(bool) +JS_ClearStructuredClone(uint64_t *data, size_t nbytes, + const JSStructuredCloneCallbacks *optionalCallbacks, + void *closure); + +JS_PUBLIC_API(bool) +JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes, bool *hasTransferable); + +JS_PUBLIC_API(bool) +JS_StructuredClone(JSContext *cx, JS::HandleValue v, JS::MutableHandleValue vp, + const JSStructuredCloneCallbacks *optionalCallbacks, void *closure); + +// RAII sugar for JS_WriteStructuredClone. +class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) { + uint64_t *data_; + size_t nbytes_; + uint32_t version_; + const JSStructuredCloneCallbacks *callbacks_; + void *closure_; + + public: + JSAutoStructuredCloneBuffer() + : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION), + callbacks_(nullptr), closure_(nullptr) + {} + + JSAutoStructuredCloneBuffer(const JSStructuredCloneCallbacks *callbacks, void *closure) + : data_(nullptr), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION), + callbacks_(callbacks), closure_(closure) + {} + + JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer &&other); + JSAutoStructuredCloneBuffer &operator=(JSAutoStructuredCloneBuffer &&other); + + ~JSAutoStructuredCloneBuffer() { clear(); } + + uint64_t *data() const { return data_; } + size_t nbytes() const { return nbytes_; } + + void clear(); + + // Copy some memory. It will be automatically freed by the destructor. + bool copy(const uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION); + + // Adopt some memory. It will be automatically freed by the destructor. + // data must have been allocated by the JS engine (e.g., extracted via + // JSAutoStructuredCloneBuffer::steal). + void adopt(uint64_t *data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION); + + // Remove the buffer so that it will not be automatically freed. + // After this, the caller is responsible for feeding the memory back to + // JSAutoStructuredCloneBuffer::adopt. + void steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp=nullptr); + + bool read(JSContext *cx, JS::MutableHandleValue vp, + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); + + bool write(JSContext *cx, JS::HandleValue v, + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); + + bool write(JSContext *cx, JS::HandleValue v, JS::HandleValue transferable, + const JSStructuredCloneCallbacks *optionalCallbacks=nullptr, void *closure=nullptr); + + private: + // Copy and assignment are not supported. + JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE; + JSAutoStructuredCloneBuffer &operator=(const JSAutoStructuredCloneBuffer &other) MOZ_DELETE; +}; + +// The range of tag values the application may use for its own custom object types. +#define JS_SCTAG_USER_MIN ((uint32_t) 0xFFFF8000) +#define JS_SCTAG_USER_MAX ((uint32_t) 0xFFFFFFFF) + +#define JS_SCERR_RECURSION 0 +#define JS_SCERR_TRANSFERABLE 1 + +JS_PUBLIC_API(void) +JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks); + +JS_PUBLIC_API(bool) +JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2); + +JS_PUBLIC_API(bool) +JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len); + +JS_PUBLIC_API(bool) +JS_ReadTypedArray(JSStructuredCloneReader *r, JS::MutableHandleValue vp); + +JS_PUBLIC_API(bool) +JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data); + +JS_PUBLIC_API(bool) +JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len); + +JS_PUBLIC_API(bool) +JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::HandleValue v); + +#endif /* js_StructuredClone_h */