mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backout changesets 7e6fb33fdf22:c85332df4320 (bug 905017) for windows bustage.
This commit is contained in:
parent
c8e2369441
commit
f79ae70d10
@ -302,28 +302,6 @@ def module_name(name):
|
||||
return name.replace('inlines.h', '').replace('-inl.h', '').replace('.h', '').replace('.cpp', '')
|
||||
|
||||
|
||||
def is_module_header(enclosing_inclname, header_inclname):
|
||||
'''Determine if an included name is the "module header", i.e. should be
|
||||
first in the file.'''
|
||||
|
||||
module = module_name(enclosing_inclname)
|
||||
|
||||
# Normal case, e.g. module == "foo/Bar", header_inclname == "foo/Bar.h".
|
||||
if module == module_name(header_inclname):
|
||||
return True
|
||||
|
||||
# A public header, e.g. module == "foo/Bar", header_inclname == "js/Bar.h".
|
||||
m = re.match(r'js\/(.*)\.h', header_inclname)
|
||||
if m is not None and module.endswith('/' + m.group(1)):
|
||||
return True
|
||||
|
||||
# A weird public header case.
|
||||
if module == 'jsmemorymetrics' and header_inclname == 'js/MemoryMetrics.h':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class Include(object):
|
||||
'''Important information for a single #include statement.'''
|
||||
|
||||
@ -335,7 +313,7 @@ class Include(object):
|
||||
def isLeaf(self):
|
||||
return True
|
||||
|
||||
def section(self, enclosing_inclname):
|
||||
def section(self, module):
|
||||
'''Identify which section inclname belongs to.
|
||||
|
||||
The section numbers are as follows.
|
||||
@ -355,9 +333,11 @@ class Include(object):
|
||||
if not self.inclname.endswith('.h'):
|
||||
return 7
|
||||
|
||||
# A couple of modules have the .h file in js/ and the .cpp file elsewhere and so need
|
||||
# special handling.
|
||||
if is_module_header(enclosing_inclname, self.inclname):
|
||||
# A couple of modules have the .h file in js/ and the .cpp file elsewhere and so need special
|
||||
# handling.
|
||||
if module == module_name(self.inclname) or \
|
||||
module == 'jsmemorymetrics' and self.inclname == 'js/MemoryMetrics.h' or \
|
||||
module == 'vm/PropertyKey' and self.inclname == 'js/PropertyKey.h':
|
||||
return 0
|
||||
|
||||
if '/' in self.inclname:
|
||||
@ -471,6 +451,8 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname
|
||||
if inclname == include.inclname:
|
||||
error(filename, include.linenum, 'the file includes itself')
|
||||
|
||||
module = module_name(inclname)
|
||||
|
||||
def check_includes_order(include1, include2):
|
||||
'''Check the ordering of two #include statements.'''
|
||||
|
||||
@ -478,8 +460,8 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname
|
||||
include2.inclname in oddly_ordered_inclnames:
|
||||
return
|
||||
|
||||
section1 = include1.section(inclname)
|
||||
section2 = include2.section(inclname)
|
||||
section1 = include1.section(module)
|
||||
section2 = include2.section(module)
|
||||
if (section1 > section2) or \
|
||||
((section1 == section2) and (include1.inclname.lower() > include2.inclname.lower())):
|
||||
error(filename, str(include1.linenum) + ':' + str(include2.linenum),
|
||||
|
@ -5,8 +5,6 @@
|
||||
#ifndef StructuredCloneTags_h__
|
||||
#define StructuredCloneTags_h__
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "js/Value.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIDOMDOMRequest;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
#include "mozIStorageStatement.h"
|
||||
|
||||
#include "js/Value.h"
|
||||
|
||||
namespace IPC {
|
||||
template <typename T> struct ParamTraits;
|
||||
} // namespace IPC
|
||||
@ -161,7 +159,7 @@ public:
|
||||
}
|
||||
|
||||
nsresult SetFromJSVal(JSContext* aCx,
|
||||
const JS::Value aVal)
|
||||
const jsval aVal)
|
||||
{
|
||||
mBuffer.Truncate();
|
||||
|
||||
@ -211,7 +209,7 @@ public:
|
||||
|
||||
nsresult AppendItem(JSContext* aCx,
|
||||
bool aFirstOfArray,
|
||||
const JS::Value aVal)
|
||||
const jsval aVal)
|
||||
{
|
||||
nsresult rv = EncodeJSVal(aCx, aVal, aFirstOfArray ? eMaxType : 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -305,7 +303,7 @@ private:
|
||||
}
|
||||
|
||||
// Encoding functions. These append the encoded value to the end of mBuffer
|
||||
inline nsresult EncodeJSVal(JSContext* aCx, const JS::Value aVal,
|
||||
inline nsresult EncodeJSVal(JSContext* aCx, const jsval aVal,
|
||||
uint8_t aTypeOffset)
|
||||
{
|
||||
return EncodeJSValInternal(aCx, aVal, aTypeOffset, 0);
|
||||
@ -331,7 +329,7 @@ private:
|
||||
nsCString mBuffer;
|
||||
|
||||
private:
|
||||
nsresult EncodeJSValInternal(JSContext* aCx, const JS::Value aVal,
|
||||
nsresult EncodeJSValInternal(JSContext* aCx, const jsval aVal,
|
||||
uint8_t aTypeOffset, uint16_t aRecursionDepth);
|
||||
|
||||
static nsresult DecodeJSValInternal(const unsigned char*& aPos,
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "StructuredCloneTags.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsIDOMFile.h"
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "Workers.h"
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
class JSAutoStructuredCloneBuffer;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
class Proxy;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "nsMemory.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsCSSProperty.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "JavaScriptShared.h"
|
||||
#include "mozilla/jsipc/PJavaScriptParent.h"
|
||||
#include "jsclass.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef GetClassName
|
||||
|
@ -1,94 +0,0 @@
|
||||
/* -*- 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_ProfilingStack_h
|
||||
#define js_ProfilingStack_h
|
||||
|
||||
#include "jsbytecode.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
struct JSRuntime;
|
||||
class JSScript;
|
||||
|
||||
namespace js {
|
||||
|
||||
// A call stack can be specified to the JS engine such that all JS entry/exits
|
||||
// to functions push/pop an entry to/from the specified stack.
|
||||
//
|
||||
// For more detailed information, see vm/SPSProfiler.h.
|
||||
//
|
||||
class ProfileEntry
|
||||
{
|
||||
// All fields are marked volatile to prevent the compiler from re-ordering
|
||||
// instructions. Namely this sequence:
|
||||
//
|
||||
// entry[size] = ...;
|
||||
// size++;
|
||||
//
|
||||
// If the size modification were somehow reordered before the stores, then
|
||||
// if a sample were taken it would be examining bogus information.
|
||||
//
|
||||
// A ProfileEntry represents both a C++ profile entry and a JS one. Both use
|
||||
// the string as a description, but JS uses the sp as NULL to indicate that
|
||||
// it is a JS entry. The script_ is then only ever examined for a JS entry,
|
||||
// and the idx is used by both, but with different meanings.
|
||||
//
|
||||
const char * volatile string; // Descriptive string of this entry
|
||||
void * volatile sp; // Relevant stack pointer for the entry
|
||||
JSScript * volatile script_; // if js(), non-null script which is running
|
||||
int32_t volatile idx; // if js(), idx of pc, otherwise line number
|
||||
|
||||
public:
|
||||
// All of these methods are marked with the 'volatile' keyword because SPS's
|
||||
// representation of the stack is stored such that all ProfileEntry
|
||||
// instances are volatile. These methods would not be available unless they
|
||||
// were marked as volatile as well.
|
||||
|
||||
bool js() volatile {
|
||||
JS_ASSERT_IF(sp == NULL, script_ != NULL);
|
||||
return sp == NULL;
|
||||
}
|
||||
|
||||
uint32_t line() volatile { JS_ASSERT(!js()); return idx; }
|
||||
JSScript *script() volatile { JS_ASSERT(js()); return script_; }
|
||||
void *stackAddress() volatile { return sp; }
|
||||
const char *label() volatile { return string; }
|
||||
|
||||
void setLine(uint32_t aLine) volatile { JS_ASSERT(!js()); idx = aLine; }
|
||||
void setLabel(const char *aString) volatile { string = aString; }
|
||||
void setStackAddress(void *aSp) volatile { sp = aSp; }
|
||||
void setScript(JSScript *aScript) volatile { script_ = aScript; }
|
||||
|
||||
// We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp.
|
||||
JS_FRIEND_API(jsbytecode *) pc() volatile;
|
||||
JS_FRIEND_API(void) setPC(jsbytecode *pc) volatile;
|
||||
|
||||
static size_t offsetOfString() { return offsetof(ProfileEntry, string); }
|
||||
static size_t offsetOfStackAddress() { return offsetof(ProfileEntry, sp); }
|
||||
static size_t offsetOfPCIdx() { return offsetof(ProfileEntry, idx); }
|
||||
static size_t offsetOfScript() { return offsetof(ProfileEntry, script_); }
|
||||
|
||||
// The index used in the entry can either be a line number or the offset of
|
||||
// a pc into a script's code. To signify a NULL pc, use a -1 index. This is
|
||||
// checked against in pc() and setPC() to set/get the right pc.
|
||||
static const int32_t NullPCIndex = -1;
|
||||
};
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
|
||||
uint32_t max);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
|
||||
|
||||
JS_FRIEND_API(jsbytecode*)
|
||||
ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* js_ProfilingStack_h */
|
@ -1,162 +0,0 @@
|
||||
/* -*- 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 <stdint.h>
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
struct JSContext;
|
||||
class JSObject;
|
||||
struct JSRuntime;
|
||||
struct JSStructuredCloneReader;
|
||||
struct JSStructuredCloneWriter;
|
||||
|
||||
namespace JS {
|
||||
template <typename T> class Handle;
|
||||
class Value;
|
||||
}
|
||||
|
||||
// API for the HTML5 internal structured cloning algorithm.
|
||||
|
||||
// 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, NULL 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::Handle<JSObject*> 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);
|
||||
|
||||
// The maximum supported structured-clone serialization format version.
|
||||
#define JS_STRUCTURED_CLONE_VERSION 2
|
||||
|
||||
struct JSStructuredCloneCallbacks {
|
||||
ReadStructuredCloneOp read;
|
||||
WriteStructuredCloneOp write;
|
||||
StructuredCloneErrorOp reportError;
|
||||
};
|
||||
|
||||
// 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::Value *vp, const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure);
|
||||
|
||||
// Note: On success, the caller is responsible for calling
|
||||
// JS_ClearStructuredClone(*datap, nbytesp).
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext *cx, JS::Value v, uint64_t **datap, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure, JS::Value transferable);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ClearStructuredClone(const uint64_t *data, size_t nbytes);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes, bool *hasTransferable);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredClone(JSContext *cx, JS::Value v, JS::Value *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_;
|
||||
|
||||
public:
|
||||
JSAutoStructuredCloneBuffer()
|
||||
: data_(NULL), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION) {}
|
||||
|
||||
~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=NULL);
|
||||
|
||||
bool read(JSContext *cx, JS::Value *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL, void *closure=NULL);
|
||||
|
||||
bool write(JSContext *cx, JS::Value v,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL, void *closure=NULL);
|
||||
|
||||
bool write(JSContext *cx, JS::Value v, JS::Value transferable,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL, void *closure=NULL);
|
||||
|
||||
// Swap ownership with another JSAutoStructuredCloneBuffer.
|
||||
void swap(JSAutoStructuredCloneBuffer &other);
|
||||
|
||||
private:
|
||||
// Copy and assignment are not supported.
|
||||
JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer &other);
|
||||
JSAutoStructuredCloneBuffer &operator=(const JSAutoStructuredCloneBuffer &other);
|
||||
};
|
||||
|
||||
// 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::Value *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::Value v);
|
||||
|
||||
#endif /* js_StructuredClone_h */
|
@ -1896,24 +1896,6 @@ JSVAL_TO_PRIVATE(jsval v)
|
||||
return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
|
||||
}
|
||||
|
||||
// JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and
|
||||
// constructing values from scratch (e.g. Int32Value(0)). These constants are
|
||||
// stored in memory and initialized at startup, so testing against them and
|
||||
// using them requires memory loads and will be correspondingly slow.
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
|
||||
|
||||
namespace JS {
|
||||
|
||||
extern JS_PUBLIC_DATA(const Handle<Value>) NullHandleValue;
|
||||
extern JS_PUBLIC_DATA(const Handle<Value>) UndefinedHandleValue;
|
||||
|
||||
}
|
||||
|
||||
#undef JS_VALUE_IS_CONSTEXPR
|
||||
#undef JS_RETURN_LAYOUT_FROM_BITS
|
||||
|
||||
|
@ -302,28 +302,6 @@ def module_name(name):
|
||||
return name.replace('inlines.h', '').replace('-inl.h', '').replace('.h', '').replace('.cpp', '')
|
||||
|
||||
|
||||
def is_module_header(enclosing_inclname, header_inclname):
|
||||
'''Determine if an included name is the "module header", i.e. should be
|
||||
first in the file.'''
|
||||
|
||||
module = module_name(enclosing_inclname)
|
||||
|
||||
# Normal case, e.g. module == "foo/Bar", header_inclname == "foo/Bar.h".
|
||||
if module == module_name(header_inclname):
|
||||
return True
|
||||
|
||||
# A public header, e.g. module == "foo/Bar", header_inclname == "js/Bar.h".
|
||||
m = re.match(r'js\/(.*)\.h', header_inclname)
|
||||
if m is not None and module.endswith('/' + m.group(1)):
|
||||
return True
|
||||
|
||||
# A weird public header case.
|
||||
if module == 'jsmemorymetrics' and header_inclname == 'js/MemoryMetrics.h':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class Include(object):
|
||||
'''Important information for a single #include statement.'''
|
||||
|
||||
@ -335,7 +313,7 @@ class Include(object):
|
||||
def isLeaf(self):
|
||||
return True
|
||||
|
||||
def section(self, enclosing_inclname):
|
||||
def section(self, module):
|
||||
'''Identify which section inclname belongs to.
|
||||
|
||||
The section numbers are as follows.
|
||||
@ -355,9 +333,11 @@ class Include(object):
|
||||
if not self.inclname.endswith('.h'):
|
||||
return 7
|
||||
|
||||
# A couple of modules have the .h file in js/ and the .cpp file elsewhere and so need
|
||||
# special handling.
|
||||
if is_module_header(enclosing_inclname, self.inclname):
|
||||
# A couple of modules have the .h file in js/ and the .cpp file elsewhere and so need special
|
||||
# handling.
|
||||
if module == module_name(self.inclname) or \
|
||||
module == 'jsmemorymetrics' and self.inclname == 'js/MemoryMetrics.h' or \
|
||||
module == 'vm/PropertyKey' and self.inclname == 'js/PropertyKey.h':
|
||||
return 0
|
||||
|
||||
if '/' in self.inclname:
|
||||
@ -471,6 +451,8 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname
|
||||
if inclname == include.inclname:
|
||||
error(filename, include.linenum, 'the file includes itself')
|
||||
|
||||
module = module_name(inclname)
|
||||
|
||||
def check_includes_order(include1, include2):
|
||||
'''Check the ordering of two #include statements.'''
|
||||
|
||||
@ -478,8 +460,8 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname
|
||||
include2.inclname in oddly_ordered_inclnames:
|
||||
return
|
||||
|
||||
section1 = include1.section(inclname)
|
||||
section2 = include2.section(inclname)
|
||||
section1 = include1.section(module)
|
||||
section2 = include2.section(module)
|
||||
if (section1 > section2) or \
|
||||
((section1 == section2) and (include1.inclname.lower() > include2.inclname.lower())):
|
||||
error(filename, str(include1.linenum) + ':' + str(include2.linenum),
|
||||
|
235
js/src/jsapi.cpp
235
js/src/jsapi.cpp
@ -21,6 +21,7 @@
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
#include "jsclone.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsdate.h"
|
||||
#include "jsexn.h"
|
||||
@ -59,7 +60,6 @@
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/AsmJSLink.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#if ENABLE_INTL_API
|
||||
#include "unicode/uclean.h"
|
||||
#include "unicode/utypes.h"
|
||||
@ -128,6 +128,17 @@ const jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
|
||||
const jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
|
||||
#endif
|
||||
|
||||
const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
|
||||
const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0));
|
||||
const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1));
|
||||
const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false));
|
||||
const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true));
|
||||
const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
|
||||
const HandleValue JS::NullHandleValue =
|
||||
HandleValue::fromMarkedLocation(&JSVAL_NULL);
|
||||
const HandleValue JS::UndefinedHandleValue =
|
||||
HandleValue::fromMarkedLocation(&JSVAL_VOID);
|
||||
|
||||
const jsid voidIdValue = JSID_VOID;
|
||||
const jsid emptyIdValue = JSID_EMPTY;
|
||||
const HandleId JS::JSID_VOIDHANDLE = HandleId::fromMarkedLocation(&voidIdValue);
|
||||
@ -174,22 +185,18 @@ JS_GetEmptyString(JSRuntime *rt)
|
||||
return rt->emptyString;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
void
|
||||
static void
|
||||
AssertHeapIsIdle(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt->heapState == js::Idle);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
AssertHeapIsIdle(JSContext *cx)
|
||||
{
|
||||
AssertHeapIsIdle(cx->runtime());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
AssertHeapIsIdleOrIterating(JSRuntime *rt)
|
||||
{
|
||||
@ -5918,6 +5925,220 @@ JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadStructuredClone(JSContext *cx, uint64_t *buf, size_t nbytes,
|
||||
uint32_t version, jsval *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
if (version > JS_STRUCTURED_CLONE_VERSION) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
|
||||
return false;
|
||||
}
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext *cx, jsval valueArg, uint64_t **bufp, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure, jsval transferable)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, value);
|
||||
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
return WriteStructuredClone(cx, value, (uint64_t **) bufp, nbytesp,
|
||||
callbacks, closure, transferable);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ClearStructuredClone(const uint64_t *data, size_t nbytes)
|
||||
{
|
||||
return ClearStructuredClone(data, nbytes);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes,
|
||||
bool *hasTransferable)
|
||||
{
|
||||
bool transferable;
|
||||
if (!StructuredCloneHasTransferObjects(data, nbytes, &transferable))
|
||||
return false;
|
||||
|
||||
*hasTransferable = transferable;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredClone(JSContext *cx, jsval valueArg, jsval *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, value);
|
||||
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
JSAutoStructuredCloneBuffer buf;
|
||||
return buf.write(cx, value, callbacks, closure) &&
|
||||
buf.read(cx, vp, callbacks, closure);
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::clear()
|
||||
{
|
||||
if (data_) {
|
||||
ClearStructuredClone(data_, nbytes_);
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::adopt(uint64_t *data, size_t nbytes, uint32_t version)
|
||||
{
|
||||
clear();
|
||||
data_ = data;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
|
||||
{
|
||||
// transferable objects cannot be copied
|
||||
bool hasTransferable;
|
||||
if (!StructuredCloneHasTransferObjects(data_, nbytes_, &hasTransferable) ||
|
||||
hasTransferable)
|
||||
return false;
|
||||
|
||||
uint64_t *newData = static_cast<uint64_t *>(js_malloc(nbytes));
|
||||
if (!newData)
|
||||
return false;
|
||||
|
||||
js_memcpy(newData, srcData, nbytes);
|
||||
|
||||
clear();
|
||||
data_ = newData;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
return true;
|
||||
}
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp)
|
||||
{
|
||||
*datap = data_;
|
||||
*nbytesp = nbytes_;
|
||||
if (versionp)
|
||||
*versionp = version_;
|
||||
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::read(JSContext *cx, jsval *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
JS_ASSERT(cx);
|
||||
JS_ASSERT(data_);
|
||||
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
|
||||
optionalCallbacks, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::write(JSContext *cx, jsval valueArg,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
jsval transferable = JSVAL_VOID;
|
||||
return write(cx, valueArg, transferable, optionalCallbacks, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::write(JSContext *cx, jsval valueArg,
|
||||
jsval transferable,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
clear();
|
||||
bool ok = !!JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
|
||||
optionalCallbacks, closure,
|
||||
transferable);
|
||||
if (!ok) {
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = JS_STRUCTURED_CLONE_VERSION;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::swap(JSAutoStructuredCloneBuffer &other)
|
||||
{
|
||||
uint64_t *data = other.data_;
|
||||
size_t nbytes = other.nbytes_;
|
||||
uint32_t version = other.version_;
|
||||
|
||||
other.data_ = this->data_;
|
||||
other.nbytes_ = this->nbytes_;
|
||||
other.version_ = this->version_;
|
||||
|
||||
this->data_ = data;
|
||||
this->nbytes_ = nbytes;
|
||||
this->version_ = version;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks)
|
||||
{
|
||||
rt->structuredCloneCallbacks = callbacks;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2)
|
||||
{
|
||||
return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
|
||||
{
|
||||
return r->input().readBytes(p, len);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data)
|
||||
{
|
||||
return w->output().writePair(tag, data);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
|
||||
{
|
||||
return w->output().writeBytes(p, len);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
183
js/src/jsapi.h
183
js/src/jsapi.h
@ -1147,8 +1147,54 @@ typedef void
|
||||
(* JSCompartmentNameCallback)(JSRuntime *rt, JSCompartment *compartment,
|
||||
char *buf, size_t bufsize);
|
||||
|
||||
/*
|
||||
* 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, NULL 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::Handle<JSObject*> 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);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and
|
||||
* constructing values from scratch (e.g. Int32Value(0)). These constants are
|
||||
* stored in memory and initialized at startup, so testing against them and
|
||||
* using them requires memory loads and will be correspondingly slow.
|
||||
*/
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
|
||||
extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
JS_NumberValue(double d)
|
||||
{
|
||||
@ -1830,12 +1876,6 @@ template <> struct GCMethods<jsid>
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
AssertHeapIsIdle(JSRuntime *rt);
|
||||
|
||||
void
|
||||
AssertHeapIsIdle(JSContext *cx);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
class JSAutoRequest
|
||||
@ -4669,6 +4709,134 @@ JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* API for the HTML5 internal structured cloning algorithm. */
|
||||
|
||||
/* The maximum supported structured-clone serialization format version. */
|
||||
#define JS_STRUCTURED_CLONE_VERSION 2
|
||||
|
||||
struct JSStructuredCloneCallbacks {
|
||||
ReadStructuredCloneOp read;
|
||||
WriteStructuredCloneOp write;
|
||||
StructuredCloneErrorOp reportError;
|
||||
};
|
||||
|
||||
/* 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, jsval *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure);
|
||||
|
||||
/* Note: On success, the caller is responsible for calling
|
||||
* JS_ClearStructuredClone(*datap, nbytesp). */
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64_t **datap, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure, jsval transferable);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ClearStructuredClone(const uint64_t *data, size_t nbytes);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes,
|
||||
bool *hasTransferable);
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredClone(JSContext *cx, jsval v, jsval *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_;
|
||||
|
||||
public:
|
||||
JSAutoStructuredCloneBuffer()
|
||||
: data_(NULL), nbytes_(0), version_(JS_STRUCTURED_CLONE_VERSION) {}
|
||||
|
||||
~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=NULL);
|
||||
|
||||
bool read(JSContext *cx, jsval *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL,
|
||||
void *closure=NULL);
|
||||
|
||||
bool write(JSContext *cx, jsval v,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL,
|
||||
void *closure=NULL);
|
||||
|
||||
bool write(JSContext *cx, jsval v,
|
||||
jsval transferable,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks=NULL,
|
||||
void *closure=NULL);
|
||||
|
||||
/**
|
||||
* Swap ownership with another JSAutoStructuredCloneBuffer.
|
||||
*/
|
||||
void swap(JSAutoStructuredCloneBuffer &other);
|
||||
|
||||
private:
|
||||
/* Copy and assignment are not supported. */
|
||||
JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer &other);
|
||||
JSAutoStructuredCloneBuffer &operator=(const JSAutoStructuredCloneBuffer &other);
|
||||
};
|
||||
|
||||
/* API for implementing custom serialization behavior (for ImageData, File, etc.) */
|
||||
|
||||
/* 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, jsval *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, jsval v);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* The default locale for the ECMAScript Internationalization API
|
||||
* (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
|
||||
@ -5087,6 +5255,9 @@ JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
|
||||
|
||||
namespace JS {
|
||||
|
||||
extern JS_PUBLIC_DATA(const Handle<Value>) NullHandleValue;
|
||||
extern JS_PUBLIC_DATA(const Handle<Value>) UndefinedHandleValue;
|
||||
|
||||
extern JS_PUBLIC_DATA(const Handle<jsid>) JSID_VOIDHANDLE;
|
||||
extern JS_PUBLIC_DATA(const Handle<jsid>) JSID_EMPTYHANDLE;
|
||||
|
||||
|
@ -27,13 +27,11 @@
|
||||
* array object.
|
||||
*/
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
#include "jsclone.h"
|
||||
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsdate.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
@ -88,181 +86,6 @@ enum TransferableMapHeader {
|
||||
SCTAG_TM_MARKED
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
struct SCOutput {
|
||||
public:
|
||||
explicit SCOutput(JSContext *cx);
|
||||
|
||||
JSContext *context() const { return cx; }
|
||||
|
||||
bool write(uint64_t u);
|
||||
bool writePair(uint32_t tag, uint32_t data);
|
||||
bool writeDouble(double d);
|
||||
bool writeBytes(const void *p, size_t nbytes);
|
||||
bool writeChars(const jschar *p, size_t nchars);
|
||||
bool writePtr(const void *);
|
||||
|
||||
template <class T>
|
||||
bool writeArray(const T *p, size_t nbytes);
|
||||
|
||||
bool extractBuffer(uint64_t **datap, size_t *sizep);
|
||||
|
||||
uint64_t count() { return buf.length(); }
|
||||
|
||||
private:
|
||||
JSContext *cx;
|
||||
js::Vector<uint64_t> buf;
|
||||
};
|
||||
|
||||
struct SCInput {
|
||||
public:
|
||||
SCInput(JSContext *cx, uint64_t *data, size_t nbytes);
|
||||
|
||||
JSContext *context() const { return cx; }
|
||||
|
||||
bool read(uint64_t *p);
|
||||
bool readPair(uint32_t *tagp, uint32_t *datap);
|
||||
bool readDouble(double *p);
|
||||
bool readBytes(void *p, size_t nbytes);
|
||||
bool readChars(jschar *p, size_t nchars);
|
||||
bool readPtr(void **);
|
||||
|
||||
bool get(uint64_t *p);
|
||||
bool getPair(uint32_t *tagp, uint32_t *datap);
|
||||
|
||||
bool replace(uint64_t u);
|
||||
bool replacePair(uint32_t tag, uint32_t data);
|
||||
|
||||
template <class T>
|
||||
bool readArray(T *p, size_t nelems);
|
||||
|
||||
private:
|
||||
bool eof();
|
||||
|
||||
void staticAssertions() {
|
||||
JS_STATIC_ASSERT(sizeof(jschar) == 2);
|
||||
JS_STATIC_ASSERT(sizeof(uint32_t) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(double) == 8);
|
||||
}
|
||||
|
||||
JSContext *cx;
|
||||
uint64_t *point;
|
||||
uint64_t *end;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct JSStructuredCloneReader {
|
||||
public:
|
||||
explicit JSStructuredCloneReader(js::SCInput &in, const JSStructuredCloneCallbacks *cb,
|
||||
void *cbClosure)
|
||||
: in(in), objs(in.context()), allObjs(in.context()),
|
||||
callbacks(cb), closure(cbClosure) { }
|
||||
|
||||
js::SCInput &input() { return in; }
|
||||
bool read(js::Value *vp);
|
||||
|
||||
private:
|
||||
JSContext *context() { return in.context(); }
|
||||
|
||||
bool readTransferMap();
|
||||
|
||||
bool checkDouble(double d);
|
||||
JSString *readString(uint32_t nchars);
|
||||
bool readTypedArray(uint32_t arrayType, uint32_t nelems, js::Value *vp, bool v1Read = false);
|
||||
bool readArrayBuffer(uint32_t nbytes, js::Value *vp);
|
||||
bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, js::Value *vp);
|
||||
bool readId(jsid *idp);
|
||||
bool startRead(js::Value *vp);
|
||||
|
||||
js::SCInput ∈
|
||||
|
||||
// Stack of objects with properties remaining to be read.
|
||||
js::AutoValueVector objs;
|
||||
|
||||
// Stack of all objects read during this deserialization
|
||||
js::AutoValueVector allObjs;
|
||||
|
||||
// The user defined callbacks that will be used for cloning.
|
||||
const JSStructuredCloneCallbacks *callbacks;
|
||||
|
||||
// Any value passed to JS_ReadStructuredClone.
|
||||
void *closure;
|
||||
|
||||
friend bool JS_ReadTypedArray(JSStructuredCloneReader *r, JS::Value *vp);
|
||||
};
|
||||
|
||||
struct JSStructuredCloneWriter {
|
||||
public:
|
||||
explicit JSStructuredCloneWriter(js::SCOutput &out,
|
||||
const JSStructuredCloneCallbacks *cb,
|
||||
void *cbClosure,
|
||||
jsval tVal)
|
||||
: out(out), objs(out.context()),
|
||||
counts(out.context()), ids(out.context()),
|
||||
memory(out.context()), callbacks(cb), closure(cbClosure),
|
||||
transferable(out.context(), tVal), transferableObjects(out.context()) { }
|
||||
|
||||
bool init() { return transferableObjects.init() && parseTransferable() &&
|
||||
memory.init() && writeTransferMap(); }
|
||||
|
||||
bool write(const js::Value &v);
|
||||
|
||||
js::SCOutput &output() { return out; }
|
||||
|
||||
private:
|
||||
JSContext *context() { return out.context(); }
|
||||
|
||||
bool writeTransferMap();
|
||||
|
||||
bool writeString(uint32_t tag, JSString *str);
|
||||
bool writeId(jsid id);
|
||||
bool writeArrayBuffer(JS::HandleObject obj);
|
||||
bool writeTypedArray(JS::HandleObject obj);
|
||||
bool startObject(JS::HandleObject obj, bool *backref);
|
||||
bool startWrite(const js::Value &v);
|
||||
bool traverseObject(JS::HandleObject obj);
|
||||
|
||||
bool parseTransferable();
|
||||
void reportErrorTransferable();
|
||||
|
||||
inline void checkStack();
|
||||
|
||||
js::SCOutput &out;
|
||||
|
||||
// Vector of objects with properties remaining to be written.
|
||||
//
|
||||
// NB: These can span multiple compartments, so the compartment must be
|
||||
// entered before any manipulation is performed.
|
||||
js::AutoValueVector objs;
|
||||
|
||||
// counts[i] is the number of properties of objs[i] remaining to be written.
|
||||
// counts.length() == objs.length() and sum(counts) == ids.length().
|
||||
js::Vector<size_t> counts;
|
||||
|
||||
// Ids of properties remaining to be written.
|
||||
js::AutoIdVector ids;
|
||||
|
||||
// The "memory" list described in the HTML5 internal structured cloning algorithm.
|
||||
// memory is a superset of objs; items are never removed from Memory
|
||||
// until a serialization operation is finished
|
||||
typedef js::AutoObjectUnsigned32HashMap CloneMemory;
|
||||
CloneMemory memory;
|
||||
|
||||
// The user defined callbacks that will be used for cloning.
|
||||
const JSStructuredCloneCallbacks *callbacks;
|
||||
|
||||
// Any value passed to JS_WriteStructuredClone.
|
||||
void *closure;
|
||||
|
||||
// List of transferable objects
|
||||
JS::RootedValue transferable;
|
||||
js::AutoObjectHashSet transferableObjects;
|
||||
|
||||
friend bool JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::Value v);
|
||||
};
|
||||
|
||||
JS_FRIEND_API(uint64_t)
|
||||
js_GetSCOffset(JSStructuredCloneWriter* writer)
|
||||
{
|
||||
@ -274,12 +97,10 @@ JS_STATIC_ASSERT(SCTAG_END_OF_BUILTIN_TYPES <= JS_SCTAG_USER_MIN);
|
||||
JS_STATIC_ASSERT(JS_SCTAG_USER_MIN <= JS_SCTAG_USER_MAX);
|
||||
JS_STATIC_ASSERT(TypedArrayObject::TYPE_INT8 == 0);
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
WriteStructuredClone(JSContext *cx, HandleValue v, uint64_t **bufp, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure,
|
||||
jsval transferable)
|
||||
js::WriteStructuredClone(JSContext *cx, HandleValue v, uint64_t **bufp, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure,
|
||||
jsval transferable)
|
||||
{
|
||||
SCOutput out(cx);
|
||||
JSStructuredCloneWriter w(out, cb, cbClosure, transferable);
|
||||
@ -287,8 +108,8 @@ WriteStructuredClone(JSContext *cx, HandleValue v, uint64_t **bufp, size_t *nbyt
|
||||
}
|
||||
|
||||
bool
|
||||
ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure)
|
||||
js::ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure)
|
||||
{
|
||||
SCInput in(cx, data, nbytes);
|
||||
|
||||
@ -300,7 +121,7 @@ ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
|
||||
}
|
||||
|
||||
bool
|
||||
ClearStructuredClone(const uint64_t *data, size_t nbytes)
|
||||
js::ClearStructuredClone(const uint64_t *data, size_t nbytes)
|
||||
{
|
||||
const uint64_t *point = data;
|
||||
const uint64_t *end = data + nbytes / 8;
|
||||
@ -331,7 +152,7 @@ ClearStructuredClone(const uint64_t *data, size_t nbytes)
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes, bool *hasTransferable)
|
||||
js::StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes, bool *hasTransferable)
|
||||
{
|
||||
*hasTransferable = false;
|
||||
|
||||
@ -346,8 +167,6 @@ StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes, bool *has
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
PairToUInt64(uint32_t tag, uint32_t data)
|
||||
{
|
||||
@ -742,6 +561,24 @@ JSStructuredCloneWriter::checkStack()
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
|
||||
{
|
||||
JS_ASSERT(v.isObject());
|
||||
assertSameCompartment(w->context(), v);
|
||||
RootedObject obj(w->context(), &v.toObject());
|
||||
|
||||
// If the object is a security wrapper, see if we're allowed to unwrap it.
|
||||
// If we aren't, throw.
|
||||
if (obj->is<WrapperObject>())
|
||||
obj = CheckedUnwrap(obj);
|
||||
if (!obj) {
|
||||
JS_ReportError(w->context(), "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
return w->writeTypedArray(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a typed array. Note that post-v1 structured clone buffers do not
|
||||
* perform endianness conversion on stored data, so multibyte typed arrays
|
||||
@ -1015,6 +852,26 @@ TagToV1ArrayType(uint32_t tag)
|
||||
return tag - SCTAG_TYPED_ARRAY_V1_MIN;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp)
|
||||
{
|
||||
uint32_t tag, nelems;
|
||||
if (!r->input().readPair(&tag, &nelems))
|
||||
return false;
|
||||
if (tag >= SCTAG_TYPED_ARRAY_V1_MIN && tag <= SCTAG_TYPED_ARRAY_V1_MAX) {
|
||||
return r->readTypedArray(TagToV1ArrayType(tag), nelems, vp, true);
|
||||
} else if (tag == SCTAG_TYPED_ARRAY_OBJECT) {
|
||||
uint64_t arrayType;
|
||||
if (!r->input().read(&arrayType))
|
||||
return false;
|
||||
return r->readTypedArray(arrayType, nelems, vp);
|
||||
} else {
|
||||
JS_ReportErrorNumber(r->context(), js_GetErrorMessage, NULL,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "expected type array");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::readTypedArray(uint32_t arrayType, uint32_t nelems, Value *vp,
|
||||
bool v1Read)
|
||||
@ -1423,257 +1280,3 @@ JSStructuredCloneReader::read(Value *vp)
|
||||
|
||||
return true;
|
||||
}
|
||||
using namespace js;
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadStructuredClone(JSContext *cx, uint64_t *buf, size_t nbytes,
|
||||
uint32_t version, JS::Value *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
if (version > JS_STRUCTURED_CLONE_VERSION) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
|
||||
return false;
|
||||
}
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteStructuredClone(JSContext *cx, JS::Value valueArg, uint64_t **bufp, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure, JS::Value transferable)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, value);
|
||||
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
return WriteStructuredClone(cx, value, bufp, nbytesp, callbacks, closure, transferable);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ClearStructuredClone(const uint64_t *data, size_t nbytes)
|
||||
{
|
||||
return ClearStructuredClone(data, nbytes);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredCloneHasTransferables(const uint64_t *data, size_t nbytes,
|
||||
bool *hasTransferable)
|
||||
{
|
||||
bool transferable;
|
||||
if (!StructuredCloneHasTransferObjects(data, nbytes, &transferable))
|
||||
return false;
|
||||
|
||||
*hasTransferable = transferable;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_StructuredClone(JSContext *cx, JS::Value valueArg, JS::Value *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, value);
|
||||
|
||||
const JSStructuredCloneCallbacks *callbacks =
|
||||
optionalCallbacks ?
|
||||
optionalCallbacks :
|
||||
cx->runtime()->structuredCloneCallbacks;
|
||||
JSAutoStructuredCloneBuffer buf;
|
||||
return buf.write(cx, value, callbacks, closure) &&
|
||||
buf.read(cx, vp, callbacks, closure);
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::clear()
|
||||
{
|
||||
if (data_) {
|
||||
ClearStructuredClone(data_, nbytes_);
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
|
||||
{
|
||||
// transferable objects cannot be copied
|
||||
bool hasTransferable;
|
||||
if (!StructuredCloneHasTransferObjects(data_, nbytes_, &hasTransferable) ||
|
||||
hasTransferable)
|
||||
return false;
|
||||
|
||||
uint64_t *newData = static_cast<uint64_t *>(js_malloc(nbytes));
|
||||
if (!newData)
|
||||
return false;
|
||||
|
||||
js_memcpy(newData, srcData, nbytes);
|
||||
|
||||
clear();
|
||||
data_ = newData;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::adopt(uint64_t *data, size_t nbytes, uint32_t version)
|
||||
{
|
||||
clear();
|
||||
data_ = data;
|
||||
nbytes_ = nbytes;
|
||||
version_ = version;
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp)
|
||||
{
|
||||
*datap = data_;
|
||||
*nbytesp = nbytes_;
|
||||
if (versionp)
|
||||
*versionp = version_;
|
||||
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::read(JSContext *cx, JS::Value *vp,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
JS_ASSERT(cx);
|
||||
JS_ASSERT(data_);
|
||||
return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
|
||||
optionalCallbacks, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::write(JSContext *cx, JS::Value valueArg,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
JS::Value transferable = JSVAL_VOID;
|
||||
return write(cx, valueArg, transferable, optionalCallbacks, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
JSAutoStructuredCloneBuffer::write(JSContext *cx, JS::Value valueArg,
|
||||
JS::Value transferable,
|
||||
const JSStructuredCloneCallbacks *optionalCallbacks,
|
||||
void *closure)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
clear();
|
||||
bool ok = !!JS_WriteStructuredClone(cx, value, &data_, &nbytes_,
|
||||
optionalCallbacks, closure,
|
||||
transferable);
|
||||
if (!ok) {
|
||||
data_ = NULL;
|
||||
nbytes_ = 0;
|
||||
version_ = JS_STRUCTURED_CLONE_VERSION;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void
|
||||
JSAutoStructuredCloneBuffer::swap(JSAutoStructuredCloneBuffer &other)
|
||||
{
|
||||
uint64_t *data = other.data_;
|
||||
size_t nbytes = other.nbytes_;
|
||||
uint32_t version = other.version_;
|
||||
|
||||
other.data_ = this->data_;
|
||||
other.nbytes_ = this->nbytes_;
|
||||
other.version_ = this->version_;
|
||||
|
||||
this->data_ = data;
|
||||
this->nbytes_ = nbytes;
|
||||
this->version_ = version;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks)
|
||||
{
|
||||
rt->structuredCloneCallbacks = callbacks;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2)
|
||||
{
|
||||
return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
|
||||
{
|
||||
return r->input().readBytes(p, len);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadTypedArray(JSStructuredCloneReader *r, JS::Value *vp)
|
||||
{
|
||||
uint32_t tag, nelems;
|
||||
if (!r->input().readPair(&tag, &nelems))
|
||||
return false;
|
||||
if (tag >= SCTAG_TYPED_ARRAY_V1_MIN && tag <= SCTAG_TYPED_ARRAY_V1_MAX) {
|
||||
return r->readTypedArray(TagToV1ArrayType(tag), nelems, vp, true);
|
||||
} else if (tag == SCTAG_TYPED_ARRAY_OBJECT) {
|
||||
uint64_t arrayType;
|
||||
if (!r->input().read(&arrayType))
|
||||
return false;
|
||||
return r->readTypedArray(arrayType, nelems, vp);
|
||||
} else {
|
||||
JS_ReportErrorNumber(r->context(), js_GetErrorMessage, NULL,
|
||||
JSMSG_SC_BAD_SERIALIZED_DATA, "expected type array");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data)
|
||||
{
|
||||
return w->output().writePair(tag, data);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
|
||||
{
|
||||
return w->output().writeBytes(p, len);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_WriteTypedArray(JSStructuredCloneWriter *w, JS::Value v)
|
||||
{
|
||||
JS_ASSERT(v.isObject());
|
||||
assertSameCompartment(w->context(), v);
|
||||
RootedObject obj(w->context(), &v.toObject());
|
||||
|
||||
// If the object is a security wrapper, see if we're allowed to unwrap it.
|
||||
// If we aren't, throw.
|
||||
if (obj->is<WrapperObject>())
|
||||
obj = CheckedUnwrap(obj);
|
||||
if (!obj) {
|
||||
JS_ReportError(w->context(), "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
return w->writeTypedArray(obj);
|
||||
}
|
||||
|
206
js/src/jsclone.h
Normal file
206
js/src/jsclone.h
Normal file
@ -0,0 +1,206 @@
|
||||
/* -*- 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 jsclone_h
|
||||
#define jsclone_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "js/Vector.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
bool
|
||||
WriteStructuredClone(JSContext *cx, HandleValue v, uint64_t **bufp, size_t *nbytesp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure,
|
||||
jsval transferable);
|
||||
|
||||
bool
|
||||
ReadStructuredClone(JSContext *cx, uint64_t *data, size_t nbytes, Value *vp,
|
||||
const JSStructuredCloneCallbacks *cb, void *cbClosure);
|
||||
|
||||
bool
|
||||
ClearStructuredClone(const uint64_t *data, size_t nbytes);
|
||||
|
||||
bool
|
||||
StructuredCloneHasTransferObjects(const uint64_t *data, size_t nbytes,
|
||||
bool *hasTransferable);
|
||||
|
||||
struct SCOutput {
|
||||
public:
|
||||
explicit SCOutput(JSContext *cx);
|
||||
|
||||
JSContext *context() const { return cx; }
|
||||
|
||||
bool write(uint64_t u);
|
||||
bool writePair(uint32_t tag, uint32_t data);
|
||||
bool writeDouble(double d);
|
||||
bool writeBytes(const void *p, size_t nbytes);
|
||||
bool writeChars(const jschar *p, size_t nchars);
|
||||
bool writePtr(const void *);
|
||||
|
||||
template <class T>
|
||||
bool writeArray(const T *p, size_t nbytes);
|
||||
|
||||
bool extractBuffer(uint64_t **datap, size_t *sizep);
|
||||
|
||||
uint64_t count() { return buf.length(); }
|
||||
|
||||
private:
|
||||
JSContext *cx;
|
||||
js::Vector<uint64_t> buf;
|
||||
};
|
||||
|
||||
struct SCInput {
|
||||
public:
|
||||
SCInput(JSContext *cx, uint64_t *data, size_t nbytes);
|
||||
|
||||
JSContext *context() const { return cx; }
|
||||
|
||||
bool read(uint64_t *p);
|
||||
bool readPair(uint32_t *tagp, uint32_t *datap);
|
||||
bool readDouble(double *p);
|
||||
bool readBytes(void *p, size_t nbytes);
|
||||
bool readChars(jschar *p, size_t nchars);
|
||||
bool readPtr(void **);
|
||||
|
||||
bool get(uint64_t *p);
|
||||
bool getPair(uint32_t *tagp, uint32_t *datap);
|
||||
|
||||
bool replace(uint64_t u);
|
||||
bool replacePair(uint32_t tag, uint32_t data);
|
||||
|
||||
template <class T>
|
||||
bool readArray(T *p, size_t nelems);
|
||||
|
||||
private:
|
||||
bool eof();
|
||||
|
||||
void staticAssertions() {
|
||||
JS_STATIC_ASSERT(sizeof(jschar) == 2);
|
||||
JS_STATIC_ASSERT(sizeof(uint32_t) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(double) == 8);
|
||||
}
|
||||
|
||||
JSContext *cx;
|
||||
uint64_t *point;
|
||||
uint64_t *end;
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
struct JSStructuredCloneReader {
|
||||
public:
|
||||
explicit JSStructuredCloneReader(js::SCInput &in, const JSStructuredCloneCallbacks *cb,
|
||||
void *cbClosure)
|
||||
: in(in), objs(in.context()), allObjs(in.context()),
|
||||
callbacks(cb), closure(cbClosure) { }
|
||||
|
||||
js::SCInput &input() { return in; }
|
||||
bool read(js::Value *vp);
|
||||
|
||||
private:
|
||||
JSContext *context() { return in.context(); }
|
||||
|
||||
bool readTransferMap();
|
||||
|
||||
bool checkDouble(double d);
|
||||
JSString *readString(uint32_t nchars);
|
||||
bool readTypedArray(uint32_t arrayType, uint32_t nelems, js::Value *vp, bool v1Read = false);
|
||||
bool readArrayBuffer(uint32_t nbytes, js::Value *vp);
|
||||
bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, js::Value *vp);
|
||||
bool readId(jsid *idp);
|
||||
bool startRead(js::Value *vp);
|
||||
|
||||
js::SCInput ∈
|
||||
|
||||
// Stack of objects with properties remaining to be read.
|
||||
js::AutoValueVector objs;
|
||||
|
||||
// Stack of all objects read during this deserialization
|
||||
js::AutoValueVector allObjs;
|
||||
|
||||
// The user defined callbacks that will be used for cloning.
|
||||
const JSStructuredCloneCallbacks *callbacks;
|
||||
|
||||
// Any value passed to JS_ReadStructuredClone.
|
||||
void *closure;
|
||||
|
||||
friend bool JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp);
|
||||
};
|
||||
|
||||
struct JSStructuredCloneWriter {
|
||||
public:
|
||||
explicit JSStructuredCloneWriter(js::SCOutput &out,
|
||||
const JSStructuredCloneCallbacks *cb,
|
||||
void *cbClosure,
|
||||
jsval tVal)
|
||||
: out(out), objs(out.context()),
|
||||
counts(out.context()), ids(out.context()),
|
||||
memory(out.context()), callbacks(cb), closure(cbClosure),
|
||||
transferable(out.context(), tVal), transferableObjects(out.context()) { }
|
||||
|
||||
bool init() { return transferableObjects.init() && parseTransferable() &&
|
||||
memory.init() && writeTransferMap(); }
|
||||
|
||||
bool write(const js::Value &v);
|
||||
|
||||
js::SCOutput &output() { return out; }
|
||||
|
||||
private:
|
||||
JSContext *context() { return out.context(); }
|
||||
|
||||
bool writeTransferMap();
|
||||
|
||||
bool writeString(uint32_t tag, JSString *str);
|
||||
bool writeId(jsid id);
|
||||
bool writeArrayBuffer(JS::HandleObject obj);
|
||||
bool writeTypedArray(JS::HandleObject obj);
|
||||
bool startObject(JS::HandleObject obj, bool *backref);
|
||||
bool startWrite(const js::Value &v);
|
||||
bool traverseObject(JS::HandleObject obj);
|
||||
|
||||
bool parseTransferable();
|
||||
void reportErrorTransferable();
|
||||
|
||||
inline void checkStack();
|
||||
|
||||
js::SCOutput &out;
|
||||
|
||||
// Vector of objects with properties remaining to be written.
|
||||
//
|
||||
// NB: These can span multiple compartments, so the compartment must be
|
||||
// entered before any manipulation is performed.
|
||||
js::AutoValueVector objs;
|
||||
|
||||
// counts[i] is the number of properties of objs[i] remaining to be written.
|
||||
// counts.length() == objs.length() and sum(counts) == ids.length().
|
||||
js::Vector<size_t> counts;
|
||||
|
||||
// Ids of properties remaining to be written.
|
||||
js::AutoIdVector ids;
|
||||
|
||||
// The "memory" list described in the HTML5 internal structured cloning algorithm.
|
||||
// memory is a superset of objs; items are never removed from Memory
|
||||
// until a serialization operation is finished
|
||||
typedef js::AutoObjectUnsigned32HashMap CloneMemory;
|
||||
CloneMemory memory;
|
||||
|
||||
// The user defined callbacks that will be used for cloning.
|
||||
const JSStructuredCloneCallbacks *callbacks;
|
||||
|
||||
// Any value passed to JS_WriteStructuredClone.
|
||||
void *closure;
|
||||
|
||||
// List of transferable objects
|
||||
JS::RootedValue transferable;
|
||||
js::AutoObjectHashSet transferableObjects;
|
||||
|
||||
friend bool JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v);
|
||||
};
|
||||
|
||||
#endif /* jsclone_h */
|
@ -991,6 +991,24 @@ js::GetEnterCompartmentDepth(JSContext *cx)
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size, uint32_t max)
|
||||
{
|
||||
rt->spsProfiler.setProfilingStack(stack, size, max);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled)
|
||||
{
|
||||
rt->spsProfiler.enable(enabled);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(jsbytecode*)
|
||||
js::ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip)
|
||||
{
|
||||
return rt->spsProfiler.ipToPC(script, size_t(ip));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks)
|
||||
{
|
||||
|
@ -669,6 +669,84 @@ GetPCCountScriptSummary(JSContext *cx, size_t script);
|
||||
JS_FRIEND_API(JSString *)
|
||||
GetPCCountScriptContents(JSContext *cx, size_t script);
|
||||
|
||||
/*
|
||||
* A call stack can be specified to the JS engine such that all JS entry/exits
|
||||
* to functions push/pop an entry to/from the specified stack.
|
||||
*
|
||||
* For more detailed information, see vm/SPSProfiler.h
|
||||
*/
|
||||
class ProfileEntry
|
||||
{
|
||||
/*
|
||||
* All fields are marked volatile to prevent the compiler from re-ordering
|
||||
* instructions. Namely this sequence:
|
||||
*
|
||||
* entry[size] = ...;
|
||||
* size++;
|
||||
*
|
||||
* If the size modification were somehow reordered before the stores, then
|
||||
* if a sample were taken it would be examining bogus information.
|
||||
*
|
||||
* A ProfileEntry represents both a C++ profile entry and a JS one. Both use
|
||||
* the string as a description, but JS uses the sp as NULL to indicate that
|
||||
* it is a JS entry. The script_ is then only ever examined for a JS entry,
|
||||
* and the idx is used by both, but with different meanings.
|
||||
*/
|
||||
const char * volatile string; // Descriptive string of this entry
|
||||
void * volatile sp; // Relevant stack pointer for the entry
|
||||
JSScript * volatile script_; // if js(), non-null script which is running
|
||||
int32_t volatile idx; // if js(), idx of pc, otherwise line number
|
||||
|
||||
public:
|
||||
/*
|
||||
* All of these methods are marked with the 'volatile' keyword because SPS's
|
||||
* representation of the stack is stored such that all ProfileEntry
|
||||
* instances are volatile. These methods would not be available unless they
|
||||
* were marked as volatile as well
|
||||
*/
|
||||
|
||||
bool js() volatile {
|
||||
JS_ASSERT_IF(sp == NULL, script_ != NULL);
|
||||
return sp == NULL;
|
||||
}
|
||||
|
||||
uint32_t line() volatile { JS_ASSERT(!js()); return idx; }
|
||||
JSScript *script() volatile { JS_ASSERT(js()); return script_; }
|
||||
void *stackAddress() volatile { return sp; }
|
||||
const char *label() volatile { return string; }
|
||||
|
||||
void setLine(uint32_t aLine) volatile { JS_ASSERT(!js()); idx = aLine; }
|
||||
void setLabel(const char *aString) volatile { string = aString; }
|
||||
void setStackAddress(void *aSp) volatile { sp = aSp; }
|
||||
void setScript(JSScript *aScript) volatile { script_ = aScript; }
|
||||
|
||||
/* we can't know the layout of JSScript, so look in vm/SPSProfiler.cpp */
|
||||
JS_FRIEND_API(jsbytecode *) pc() volatile;
|
||||
JS_FRIEND_API(void) setPC(jsbytecode *pc) volatile;
|
||||
|
||||
static size_t offsetOfString() { return offsetof(ProfileEntry, string); }
|
||||
static size_t offsetOfStackAddress() { return offsetof(ProfileEntry, sp); }
|
||||
static size_t offsetOfPCIdx() { return offsetof(ProfileEntry, idx); }
|
||||
static size_t offsetOfScript() { return offsetof(ProfileEntry, script_); }
|
||||
|
||||
/*
|
||||
* The index used in the entry can either be a line number or the offset of
|
||||
* a pc into a script's code. To signify a NULL pc, use a -1 index. This is
|
||||
* checked against in pc() and setPC() to set/get the right pc.
|
||||
*/
|
||||
static const int32_t NullPCIndex = -1;
|
||||
};
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
|
||||
uint32_t max);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
|
||||
|
||||
JS_FRIEND_API(jsbytecode*)
|
||||
ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_FRIEND_API(bool)
|
||||
ContextHasOutstandingRequests(const JSContext *cx);
|
||||
|
@ -68,11 +68,9 @@ EXPORTS.js += [
|
||||
'../public/HeapAPI.h',
|
||||
'../public/LegacyIntTypes.h',
|
||||
'../public/MemoryMetrics.h',
|
||||
'../public/ProfilingStack.h',
|
||||
'../public/PropertyKey.h',
|
||||
'../public/RequiredDefines.h',
|
||||
'../public/RootingAPI.h',
|
||||
'../public/StructuredClone.h',
|
||||
'../public/Utility.h',
|
||||
'../public/Value.h',
|
||||
'../public/Vector.h',
|
||||
@ -127,13 +125,11 @@ CPP_SOURCES += [
|
||||
'StoreBuffer.cpp',
|
||||
'String.cpp',
|
||||
'StringBuffer.cpp',
|
||||
'StructuredClone.cpp',
|
||||
'TestingFunctions.cpp',
|
||||
'ThreadPool.cpp',
|
||||
'TokenStream.cpp',
|
||||
'TypedArrayObject.cpp',
|
||||
'Unicode.cpp',
|
||||
'Value.cpp',
|
||||
'Verifier.cpp',
|
||||
'Xdr.cpp',
|
||||
'YarrCanonicalizeUCS2.cpp',
|
||||
@ -147,6 +143,7 @@ CPP_SOURCES += [
|
||||
'jsarray.cpp',
|
||||
'jsatom.cpp',
|
||||
'jsbool.cpp',
|
||||
'jsclone.cpp',
|
||||
'jscntxt.cpp',
|
||||
'jscompartment.cpp',
|
||||
'jscrashreport.cpp',
|
||||
|
@ -62,7 +62,6 @@
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/Parser.h"
|
||||
#include "jit/Ion.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "perf/jsperf.h"
|
||||
#include "shell/jsheaptools.h"
|
||||
#include "shell/jsoptparse.h"
|
||||
|
@ -4,11 +4,11 @@
|
||||
* 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/. */
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsprf.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
using namespace JS;
|
||||
|
||||
Latin1CharsZ
|
||||
|
@ -265,33 +265,14 @@ SPSEntryMarker::~SPSEntryMarker()
|
||||
}
|
||||
|
||||
JS_FRIEND_API(jsbytecode*)
|
||||
ProfileEntry::pc() volatile
|
||||
{
|
||||
ProfileEntry::pc() volatile {
|
||||
JS_ASSERT_IF(idx != NullPCIndex, idx >= 0 && uint32_t(idx) < script()->length);
|
||||
return idx == NullPCIndex ? NULL : script()->code + idx;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
ProfileEntry::setPC(jsbytecode *pc) volatile
|
||||
{
|
||||
JS_ASSERT_IF(pc != NULL, script()->code <= pc && pc < script()->code + script()->length);
|
||||
ProfileEntry::setPC(jsbytecode *pc) volatile {
|
||||
JS_ASSERT_IF(pc != NULL, script()->code <= pc &&
|
||||
pc < script()->code + script()->length);
|
||||
idx = pc == NULL ? NullPCIndex : pc - script()->code;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size, uint32_t max)
|
||||
{
|
||||
rt->spsProfiler.setProfilingStack(stack, size, max);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled)
|
||||
{
|
||||
rt->spsProfiler.enable(enabled);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(jsbytecode*)
|
||||
js::ProfilingGetPC(JSRuntime *rt, JSScript *script, void *ip)
|
||||
{
|
||||
return rt->spsProfiler.ipToPC(script, size_t(ip));
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
#include "jsscript.h"
|
||||
|
||||
#include "js/ProfilingStack.h"
|
||||
|
||||
/*
|
||||
* SPS Profiler integration with the JS Engine
|
||||
* https://developer.mozilla.org/en/Performance/Profiling_with_the_Built-in_Profiler
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "js/Value.h"
|
||||
|
||||
const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
|
||||
const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0));
|
||||
const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1));
|
||||
const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, false));
|
||||
const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, true));
|
||||
const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
|
||||
|
||||
namespace JS {
|
||||
|
||||
const HandleValue NullHandleValue = HandleValue::fromMarkedLocation(&JSVAL_NULL);
|
||||
const HandleValue UndefinedHandleValue = HandleValue::fromMarkedLocation(&JSVAL_VOID);
|
||||
|
||||
} // namespace JS
|
@ -7,10 +7,9 @@
|
||||
#define __NSAUTOJSVALHOLDER_H__
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
/**
|
||||
* Simple class that looks and acts like a JS::Value except that it unroots
|
||||
* Simple class that looks and acts like a jsval except that it unroots
|
||||
* itself automatically if Root() is ever called. Designed to be rooted on the
|
||||
* context or runtime (but not both!).
|
||||
*/
|
||||
@ -45,7 +44,7 @@ public:
|
||||
else {
|
||||
this->Release();
|
||||
}
|
||||
*this = static_cast<JS::Value>(aOther);
|
||||
*this = static_cast<jsval>(aOther);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -77,10 +76,10 @@ public:
|
||||
|
||||
/**
|
||||
* Manually release, nullifying mVal, and mRt, but returning
|
||||
* the original JS::Value.
|
||||
* the original jsval.
|
||||
*/
|
||||
JS::Value Release() {
|
||||
JS::Value oldval = mVal;
|
||||
jsval Release() {
|
||||
jsval oldval = mVal;
|
||||
|
||||
if (mRt) {
|
||||
JS_RemoveValueRootRT(mRt, &mVal); // infallible
|
||||
@ -108,20 +107,20 @@ public:
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
JS::Value* ToJSValPtr() {
|
||||
jsval* ToJSValPtr() {
|
||||
return &mVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend to be a JS::Value.
|
||||
* Pretend to be a jsval.
|
||||
*/
|
||||
operator JS::Value() const { return mVal; }
|
||||
operator jsval() const { return mVal; }
|
||||
|
||||
nsAutoJSValHolder &operator=(JSObject* aOther) {
|
||||
return *this = OBJECT_TO_JSVAL(aOther);
|
||||
}
|
||||
|
||||
nsAutoJSValHolder &operator=(JS::Value aOther) {
|
||||
nsAutoJSValHolder &operator=(jsval aOther) {
|
||||
#ifdef DEBUG
|
||||
if (JSVAL_IS_GCTHING(aOther) && !JSVAL_IS_NULL(aOther)) {
|
||||
MOZ_ASSERT(IsHeld(), "Not rooted!");
|
||||
@ -132,7 +131,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
JS::Value mVal;
|
||||
jsval mVal;
|
||||
JSRuntime* mRt;
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nsNSSIOLayer.h"
|
||||
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include <stdint.h>
|
||||
#include "js/ProfilingStack.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user