merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-11-10 14:24:51 +01:00
commit 1d9d0ab094
220 changed files with 3119 additions and 2453 deletions

View File

@ -93,7 +93,7 @@ include backend.RecursiveMakeBackend.pp
default:: backend.RecursiveMakeBackend
install_manifests := \
$(addprefix dist/,bin idl include public private sdk) \
$(addprefix dist/,bin idl include public private sdk xpi-stage) \
_tests \
$(NULL)
install_manifest_depends = \

View File

@ -30,10 +30,11 @@ ClearCacheEntry(const void* aKey, nsRefPtr<T>& aAccessible, void* aUserArg)
* Clear the cache and shutdown the accessibles.
*/
template <class T>
static void
ClearCache(mozilla::a11y::AccessibleHashtable& aCache)
ClearCache(nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
aCache.Enumerate(ClearCacheEntry<mozilla::a11y::Accessible>, nullptr);
aCache.Enumerate(ClearCacheEntry<T>, nullptr);
}
#endif

View File

@ -16,6 +16,7 @@
#include "Relation.h"
#include "Role.h"
#include "States.h"
#include "XULTreeGridAccessible.h"
#include "nsComponentManagerUtils.h"
#include "nsIAccessibleRelation.h"

View File

@ -16,6 +16,8 @@ class nsTreeBodyFrame;
namespace mozilla {
namespace a11y {
class XULTreeGridCellAccessible;
/*
* A class the represents the XUL Tree widget.
*/
@ -174,7 +176,7 @@ public:
* Return cell accessible for the given column. If XUL tree accessible is not
* accessible table then return null.
*/
virtual Accessible* GetCellAccessible(nsITreeColumn* aColumn) const
virtual XULTreeGridCellAccessible* GetCellAccessible(nsITreeColumn* aColumn) const
{ return nullptr; }
/**

View File

@ -361,17 +361,17 @@ XULTreeGridRowAccessible::ChildCount() const
////////////////////////////////////////////////////////////////////////////////
// XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
Accessible*
XULTreeGridCellAccessible*
XULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) const
{
NS_PRECONDITION(aColumn, "No tree column!");
void* key = static_cast<void*>(aColumn);
Accessible* cachedCell = mAccessibleCache.GetWeak(key);
XULTreeGridCellAccessible* cachedCell = mAccessibleCache.GetWeak(key);
if (cachedCell)
return cachedCell;
nsRefPtr<Accessible> cell =
nsRefPtr<XULTreeGridCellAccessible> cell =
new XULTreeGridCellAccessibleWrap(mContent, mDoc,
const_cast<XULTreeGridRowAccessible*>(this),
mTree, mTreeView, mRow, aColumn);
@ -394,12 +394,9 @@ XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
nsCOMPtr<nsITreeColumn> column;
treeColumns->GetColumnAt(colIdx, getter_AddRefs(column));
if (column && !nsCoreUtils::IsColumnHidden(column)) {
Accessible* cellAccessible = GetCellAccessible(column);
if (cellAccessible) {
nsRefPtr<XULTreeGridCellAccessible> cellAcc = do_QueryObject(cellAccessible);
nameChanged |= cellAcc->CellInvalidated();
}
XULTreeGridCellAccessible* cell = GetCellAccessible(column);
if (cell)
nameChanged |= cell->CellInvalidated();
}
}
@ -452,10 +449,8 @@ XULTreeGridCellAccessible::~XULTreeGridCellAccessible()
NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
mTree, mColumn)
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
NS_INTERFACE_TABLE_INHERITED(XULTreeGridCellAccessible,
XULTreeGridCellAccessible)
NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
NS_INTERFACE_MAP_END_INHERITING(LeafAccessible)
NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible)

View File

@ -15,6 +15,8 @@
namespace mozilla {
namespace a11y {
class XULTreeGridCellAccessible;
/**
* Represents accessible for XUL tree in the case when it has multiple columns.
*/
@ -88,7 +90,8 @@ public:
virtual uint32_t ChildCount() const MOZ_OVERRIDE;
// XULTreeItemAccessibleBase
virtual Accessible* GetCellAccessible(nsITreeColumn* aColumn) const MOZ_OVERRIDE;
virtual XULTreeGridCellAccessible* GetCellAccessible(nsITreeColumn* aColumn)
const MOZ_OVERRIDE MOZ_FINAL;
virtual void RowInvalidated(int32_t aStartColIdx, int32_t aEndColIdx);
protected:
@ -98,7 +101,8 @@ protected:
virtual void CacheChildren();
// XULTreeItemAccessibleBase
mutable AccessibleHashtable mAccessibleCache;
mutable nsRefPtrHashtable<nsPtrHashKey<const void>, XULTreeGridCellAccessible>
mAccessibleCache;
};
@ -107,14 +111,6 @@ protected:
* multiple columns.
*/
#define XULTREEGRIDCELLACCESSIBLE_IMPL_CID \
{ /* 84588ad4-549c-4196-a932-4c5ca5de5dff */ \
0x84588ad4, \
0x549c, \
0x4196, \
{ 0xa9, 0x32, 0x4c, 0x5c, 0xa5, 0xde, 0x5d, 0xff } \
}
class XULTreeGridCellAccessible : public LeafAccessible,
public TableCellAccessible
{
@ -155,9 +151,6 @@ public:
virtual void RowHeaderCells(nsTArray<Accessible*>* aCells) MOZ_OVERRIDE { }
virtual bool Selected() MOZ_OVERRIDE;
// XULTreeGridCellAccessible
NS_DECLARE_STATIC_IID_ACCESSOR(XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
/**
* Fire name or state change event if the accessible text or value has been
* changed.
@ -191,9 +184,6 @@ protected:
nsString mCachedTextEquiv;
};
NS_DEFINE_STATIC_IID_ACCESSOR(XULTreeGridCellAccessible,
XULTREEGRIDCELLACCESSIBLE_IMPL_CID)
} // namespace a11y
} // namespace mozilla

View File

@ -69,9 +69,6 @@ libs::
$(INSTALL) $(IFLAGS1) $(DIST)/branding/default48.png $(FINAL_TARGET)/chrome/icons/default
endif
libs:: $(srcdir)/profile/prefs.js
$(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/defaults/profile
ifndef LIBXUL_SDK
# channel-prefs.js is handled separate from other prefs due to bug 756325
libs:: $(srcdir)/profile/channel-prefs.js
@ -79,9 +76,6 @@ libs:: $(srcdir)/profile/channel-prefs.js
$(call py_action,preprocessor,-Fsubstitution $(PREF_PPFLAGS) $(ACDEFINES) $^ -o $(DIST)/bin/defaults/pref/channel-prefs.js)
endif
libs:: $(srcdir)/blocklist.xml
$(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
MAC_APP_NAME = $(MOZ_APP_DISPLAYNAME)

View File

@ -15,6 +15,9 @@ SOURCES += [
'nsBrowserApp.cpp',
]
FINAL_TARGET_FILES += ['blocklist.xml']
FINAL_TARGET_FILES.defaults.profile += ['profile/prefs.js']
DEFINES['APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
for var in ('MOZILLA_OFFICIAL', 'LIBXUL_SDK'):

View File

@ -1961,7 +1961,7 @@ Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
#endif
bool
Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc)
{

View File

@ -274,7 +274,7 @@ public:
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
@ -358,7 +358,7 @@ private:
nsRefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
nsCOMPtr<nsPIDOMWindow> mWindow;
// Hashtable for saving cached objects newresolve created, so we don't create
// Hashtable for saving cached objects DoResolve created, so we don't create
// the object twice if asked for it twice, whether due to use of "delete" or
// due to Xrays. We could probably use a nsJSThingHashtable here, but then
// we'd need to figure out exactly how to trace that, and that seems to be

View File

@ -192,13 +192,13 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
DOM_BASE_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_PRECREATE |
nsIXPCScriptable::WANT_NEWRESOLVE |
nsIXPCScriptable::WANT_RESOLVE |
nsIXPCScriptable::WANT_HASINSTANCE |
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
NS_DEFINE_CLASSINFO_DATA(DOMConstructor, nsDOMConstructorSH,
DOM_BASE_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_PRECREATE |
nsIXPCScriptable::WANT_NEWRESOLVE |
nsIXPCScriptable::WANT_RESOLVE |
nsIXPCScriptable::WANT_HASINSTANCE |
nsIXPCScriptable::WANT_CALL |
nsIXPCScriptable::WANT_CONSTRUCT |
@ -1015,11 +1015,18 @@ nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
return NS_ERROR_UNEXPECTED;
}
nsresult
nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *aObj,
JSObject **objp)
NS_IMETHODIMP
nsDOMClassInfo::Resolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *aObj, jsid aId, bool *resolvedp, bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
JS::Rooted<jsid> id(cx, aId);
if (id != sConstructor_id) {
*resolvedp = false;
return NS_OK;
}
JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj));
JS::Rooted<JS::Value> val(cx);
@ -1032,27 +1039,13 @@ nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *aObj,
// constructor for this class, or someone messed with
// window.classname, just fall through and let the JS engine
// return the Object constructor.
JS::Rooted<jsid> id(cx, sConstructor_id);
if (!::JS_DefinePropertyById(cx, obj, id, val,
JSPROP_ENUMERATE,
JS_STUBGETTER, JS_STUBSETTER)) {
return NS_ERROR_UNEXPECTED;
}
*objp = obj;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMClassInfo::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, JSObject **objp,
bool *_retval)
{
if (id == sConstructor_id) {
return ResolveConstructor(cx, obj, objp);
*resolvedp = true;
}
return NS_OK;
@ -2158,7 +2151,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
// Note - Our only caller is nsGlobalWindow::DoNewResolve, which checks that
// Note - Our only caller is nsGlobalWindow::DoResolve, which checks that
// JSID_IS_STRING(id) is true.
nsAutoJSString name;
if (!name.init(cx, JSID_TO_STRING(id))) {
@ -2622,8 +2615,8 @@ nsDOMConstructorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
}
NS_IMETHODIMP
nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *aObj, jsid aId, JSObject **objp,
nsDOMConstructorSH::Resolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *aObj, jsid aId, bool *resolvedp,
bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
@ -2645,7 +2638,7 @@ nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx
// Now re-lookup the ID to see if we should report back that we resolved the
// looked-for constant. Note that we don't have to worry about infinitely
// recurring back here because the Xray wrapper's holder object doesn't call
// NewResolve hooks.
// Resolve hooks.
bool found;
if (!JS_HasPropertyById(cx, nativePropsObj, id, &found)) {
*_retval = false;
@ -2653,7 +2646,7 @@ nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx
}
if (found) {
*objp = obj;
*resolvedp = true;
}
return NS_OK;
}

View File

@ -138,8 +138,6 @@ protected:
static nsresult RegisterClassProtos(int32_t aDOMClassInfoID);
static nsresult RegisterExternalClasses();
nsresult ResolveConstructor(JSContext *cx, JSObject *obj,
JSObject **objp);
static nsIXPConnect *sXPConnect;
@ -276,8 +274,8 @@ public:
{
return NS_OK;
}
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, JSObject **objp,
NS_IMETHOD Resolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, bool *resolvedp,
bool *_retval) MOZ_OVERRIDE;
NS_IMETHOD Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, const JS::CallArgs &args, bool *_retval) MOZ_OVERRIDE;

View File

@ -704,7 +704,6 @@ const js::Class OuterWindowProxyClass =
PROXY_MAKE_EXT(
nullptr, /* outerObject */
js::proxy_innerObject,
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nsOuterWindowProxy::ObjectMoved
));
@ -4239,7 +4238,7 @@ nsGlobalWindow::GetSupportedNames(nsTArray<nsString>& aNames)
}
bool
nsGlobalWindow::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc)
{

View File

@ -483,7 +483,7 @@ public:
static bool IsShowModalDialogEnabled(JSContext* /* unused */ = nullptr,
JSObject* /* unused */ = nullptr);
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);

View File

@ -23,7 +23,7 @@
#define DEFAULT_SCRIPTABLE_FLAGS \
(DOM_BASE_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_NEWRESOLVE | \
nsIXPCScriptable::WANT_RESOLVE | \
nsIXPCScriptable::WANT_PRECREATE)
#define DOM_DEFAULT_SCRIPTABLE_FLAGS \

View File

@ -45,6 +45,7 @@
#include "jsapi.h"
#include "jswrapper.h"
#include "js/SliceBudget.h"
#include "nsIArray.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
@ -1692,24 +1693,24 @@ nsJSContext::RunCycleCollectorSlice()
// Decide how long we want to budget for this slice. By default,
// use an unlimited budget.
int64_t sliceBudget = -1;
js::SliceBudget budget;
if (sIncrementalCC) {
if (gCCStats.mBeginTime.IsNull()) {
// If no CC is in progress, use the standard slice time.
sliceBudget = kICCSliceBudget;
budget = js::SliceBudget(js::TimeBudget(kICCSliceBudget));
} else {
TimeStamp now = TimeStamp::Now();
// Only run a limited slice if we're within the max running time.
if (TimeBetween(gCCStats.mBeginTime, now) < kMaxICCDuration) {
float sliceMultiplier = std::max(TimeBetween(gCCStats.mEndSliceTime, now) / (float)kICCIntersliceDelay, 1.0f);
sliceBudget = kICCSliceBudget * sliceMultiplier;
budget = js::SliceBudget(js::TimeBudget(kICCSliceBudget * sliceMultiplier));
}
}
}
nsCycleCollector_collectSlice(sliceBudget);
nsCycleCollector_collectSlice(budget);
gCCStats.FinishCycleCollectionSlice();
}
@ -1726,7 +1727,10 @@ nsJSContext::RunCycleCollectorWorkSlice(int64_t aWorkBudget)
js::ProfileEntry::Category::CC);
gCCStats.PrepareForCycleCollectionSlice();
nsCycleCollector_collectSliceWork(aWorkBudget);
js::SliceBudget budget = js::SliceBudget(js::WorkBudget(aWorkBudget));
nsCycleCollector_collectSlice(budget);
gCCStats.FinishCycleCollectionSlice();
}

View File

@ -3622,7 +3622,7 @@ nsObjectLoadingContent::TeardownProtoChain()
}
bool
nsObjectLoadingContent::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
nsObjectLoadingContent::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc)
{
@ -3642,7 +3642,7 @@ nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
nsTArray<nsString>& /* unused */,
ErrorResult& aRv)
{
// Just like DoNewResolve, just make sure we're instantiated. That will do
// Just like DoResolve, just make sure we're instantiated. That will do
// the work our Enumerate hook needs to do. This purposefully does not fire
// for xray resolves, see bug 967694
nsRefPtr<nsNPAPIPluginInstance> pi;

View File

@ -157,7 +157,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
* SetupProtoChain handles actually inserting the plug-in
* scriptable object into the proto chain if needed.
*
* DoNewResolve is a hook that allows us to find out when the web
* DoResolve is a hook that allows us to find out when the web
* page is looking up a property name on our object and make sure
* that our plug-in, if any, is instantiated.
*/
@ -167,8 +167,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// Remove plugin from protochain
void TeardownProtoChain();
// Helper for WebIDL newResolve
bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
// Helper for WebIDL NeedResolve
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
// Helper for WebIDL enumeration

View File

@ -2292,15 +2292,9 @@ FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj)
bool
ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId, JS::MutableHandle<JSObject*> aObjp)
JS::Handle<jsid> aId, bool* aResolvedp)
{
bool resolved;
if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
return false;
}
aObjp.set(resolved ? aObj.get() : nullptr);
return true;
return JS_ResolveStandardClass(aCx, aObj, aId, aResolvedp);
}
bool

View File

@ -2803,7 +2803,7 @@ FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
bool
ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId, JS::MutableHandle<JSObject*> aObjp);
JS::Handle<jsid> aId, bool* aResolvedp);
bool
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);

View File

@ -21,7 +21,7 @@ OBJECT_MOVED_HOOK_NAME = '_objectMoved'
CONSTRUCT_HOOK_NAME = '_constructor'
LEGACYCALLER_HOOK_NAME = '_legacycaller'
HASINSTANCE_HOOK_NAME = '_hasInstance'
NEWRESOLVE_HOOK_NAME = '_newResolve'
RESOLVE_HOOK_NAME = '_resolve'
ENUMERATE_HOOK_NAME = '_enumerate'
ENUM_ENTRY_VARIABLE_NAME = 'strings'
INSTANCE_RESERVED_SLOTS = 1
@ -275,7 +275,7 @@ class CGNativePropertyHooks(CGThing):
resolveOwnProperty = "ResolveOwnProperty"
enumerateOwnProperties = "EnumerateOwnProperties"
elif self.descriptor.needsXrayResolveHooks():
resolveOwnProperty = "ResolveOwnPropertyViaNewresolve"
resolveOwnProperty = "ResolveOwnPropertyViaResolve"
enumerateOwnProperties = "EnumerateOwnPropertiesViaGetOwnPropertyNames"
else:
resolveOwnProperty = "nullptr"
@ -370,7 +370,6 @@ class CGDOMJSClass(CGThing):
{
nullptr, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nullptr, /* weakmapKeyDelegateOp */
${objectMoved} /* objectMovedOp */
@ -388,7 +387,6 @@ class CGDOMJSClass(CGThing):
{
nsGlobalWindow::OuterObject, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nullptr, /* weakmapKeyDelegateOp */
${objectMoved} /* objectMovedOp */
@ -420,16 +418,14 @@ class CGDOMJSClass(CGThing):
else:
classFlags += "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount
reservedSlots = slotCount
if self.descriptor.interface.getExtendedAttribute("NeedNewResolve"):
newResolveHook = "(JSResolveOp)" + NEWRESOLVE_HOOK_NAME
classFlags += " | JSCLASS_NEW_RESOLVE"
if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
resolveHook = RESOLVE_HOOK_NAME
enumerateHook = ENUMERATE_HOOK_NAME
elif self.descriptor.isGlobal():
newResolveHook = "(JSResolveOp) mozilla::dom::ResolveGlobal"
classFlags += " | JSCLASS_NEW_RESOLVE"
resolveHook = "mozilla::dom::ResolveGlobal"
enumerateHook = "mozilla::dom::EnumerateGlobal"
else:
newResolveHook = "JS_ResolveStub"
resolveHook = "JS_ResolveStub"
enumerateHook = "JS_EnumerateStub"
return fill(
@ -463,7 +459,7 @@ class CGDOMJSClass(CGThing):
flags=classFlags,
addProperty=ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'JS_PropertyStub',
enumerate=enumerateHook,
resolve=newResolveHook,
resolve=resolveHook,
finalize=FINALIZE_HOOK_NAME,
call=callHook,
trace=traceHook,
@ -500,7 +496,6 @@ class CGDOMProxyJSClass(CGThing):
${flags},
PROXY_MAKE_EXT(nullptr, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
${objectMoved})),
$*{descriptor}
@ -7602,32 +7597,32 @@ class CGLegacyCallHook(CGAbstractBindingMethod):
self._legacycaller)
class CGNewResolveHook(CGAbstractBindingMethod):
class CGResolveHook(CGAbstractBindingMethod):
"""
NewResolve hook for objects with custom hooks.
Resolve hook for objects that have the NeedResolve extended attribute.
"""
def __init__(self, descriptor):
assert descriptor.interface.getExtendedAttribute("NeedNewResolve")
assert descriptor.interface.getExtendedAttribute("NeedResolve")
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'obj'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JSObject*>', 'objp')]
Argument('bool*', 'resolvedp')]
# Our "self" is actually the "obj" argument in this case, not the thisval.
CGAbstractBindingMethod.__init__(
self, descriptor, NEWRESOLVE_HOOK_NAME,
self, descriptor, RESOLVE_HOOK_NAME,
args, getThisObj="", callArgs="")
def generate_code(self):
return CGGeneric(dedent("""
JS::Rooted<JSPropertyDescriptor> desc(cx);
if (!self->DoNewResolve(cx, obj, id, &desc)) {
if (!self->DoResolve(cx, obj, id, &desc)) {
return false;
}
if (!desc.object()) {
return true;
}
// If desc.value() is undefined, then the DoNewResolve call
// If desc.value() is undefined, then the DoResolve call
// has already defined it on the object. Don't try to also
// define it.
if (!desc.value().isUndefined() &&
@ -7637,7 +7632,7 @@ class CGNewResolveHook(CGAbstractBindingMethod):
JS_PROPERTYOP_SETTER(desc.setter()))) {
return false;
}
objp.set(obj);
*resolvedp = true;
return true;
"""))
@ -7645,10 +7640,10 @@ class CGNewResolveHook(CGAbstractBindingMethod):
if self.descriptor.isGlobal():
# Resolve standard classes
prefix = dedent("""
if (!ResolveGlobal(cx, obj, id, objp)) {
if (!ResolveGlobal(cx, obj, id, resolvedp)) {
return false;
}
if (objp) {
if (*resolvedp) {
return true;
}
@ -7663,7 +7658,7 @@ class CGEnumerateHook(CGAbstractBindingMethod):
Enumerate hook for objects with custom hooks.
"""
def __init__(self, descriptor):
assert descriptor.interface.getExtendedAttribute("NeedNewResolve")
assert descriptor.interface.getExtendedAttribute("NeedResolve")
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'obj')]
@ -9569,10 +9564,10 @@ class CGResolveOwnProperty(CGAbstractStaticMethod):
return "return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, desc);\n"
class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
class CGResolveOwnPropertyViaResolve(CGAbstractBindingMethod):
"""
An implementation of Xray ResolveOwnProperty stuff for things that have a
newresolve hook.
resolve hook.
"""
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'),
@ -9581,7 +9576,7 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc')]
CGAbstractBindingMethod.__init__(self, descriptor,
"ResolveOwnPropertyViaNewresolve",
"ResolveOwnPropertyViaResolve",
args, getThisObj="",
callArgs="")
@ -9596,10 +9591,10 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
// them.
JSAutoCompartment ac(cx, obj);
JS::Rooted<JSPropertyDescriptor> objDesc(cx);
if (!self->DoNewResolve(cx, obj, id, &objDesc)) {
if (!self->DoResolve(cx, obj, id, &objDesc)) {
return false;
}
// If desc.value() is undefined, then the DoNewResolve call
// If desc.value() is undefined, then the DoResolve call
// has already defined the property on the object. Don't
// try to also define it.
if (objDesc.object() &&
@ -9611,7 +9606,7 @@ class CGResolveOwnPropertyViaNewresolve(CGAbstractBindingMethod):
return false;
}
}
return self->DoNewResolve(cx, wrapper, id, desc);
return self->DoResolve(cx, wrapper, id, desc);
"""))
@ -9631,7 +9626,7 @@ class CGEnumerateOwnProperties(CGAbstractStaticMethod):
class CGEnumerateOwnPropertiesViaGetOwnPropertyNames(CGAbstractBindingMethod):
"""
An implementation of Xray EnumerateOwnProperties stuff for things
that have a newresolve hook.
that have a resolve hook.
"""
def __init__(self, descriptor):
args = [Argument('JSContext*', 'cx'),
@ -11097,7 +11092,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGResolveOwnProperty(descriptor))
cgThings.append(CGEnumerateOwnProperties(descriptor))
elif descriptor.needsXrayResolveHooks():
cgThings.append(CGResolveOwnPropertyViaNewresolve(descriptor))
cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
# Now that we have our ResolveOwnProperty/EnumerateOwnProperties stuff
@ -11114,8 +11109,8 @@ class CGDescriptor(CGThing):
cgThings.append(CGNamedConstructors(descriptor))
cgThings.append(CGLegacyCallHook(descriptor))
if descriptor.interface.getExtendedAttribute("NeedNewResolve"):
cgThings.append(CGNewResolveHook(descriptor))
if descriptor.interface.getExtendedAttribute("NeedResolve"):
cgThings.append(CGResolveHook(descriptor))
cgThings.append(CGEnumerateHook(descriptor))
if descriptor.hasNamedPropertiesObject:
@ -11881,8 +11876,7 @@ class CGResolveSystemBinding(CGAbstractMethod):
[Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'aObj'),
Argument('JS::Handle<jsid>', 'aId'),
Argument('JS::MutableHandle<JSObject*>',
'aObjp')])
Argument('bool*', 'aResolvedp')])
self.config = config
def definition_body(self):
@ -11915,7 +11909,7 @@ class CGResolveSystemBinding(CGAbstractMethod):
defineCode = "!%s::GetConstructorObject(aCx, aObj)" % bindingNS
defineCode = CGIfWrapper(CGGeneric("return false;\n"), defineCode)
defineCode = CGList([defineCode,
CGGeneric("aObjp.set(aObj);\n")])
CGGeneric("*aResolvedp = true;\n")])
condition = "JSID_IS_VOID(aId) || aId == %s" % descNameToId(desc.name)
if desc.isExposedConditionally():

View File

@ -663,14 +663,14 @@ class Descriptor(DescriptorProvider):
def needsXrayResolveHooks(self):
"""
Generally, any interface with NeedNewResolve needs Xray
Generally, any interface with NeedResolve needs Xray
resolveOwnProperty and enumerateOwnProperties hooks. But for
the special case of plugin-loading elements, we do NOT want
those, because we don't want to instantiate plug-ins simply
due to chrome touching them and that's all those hooks do on
those elements. So we special-case those here.
"""
return (self.interface.getExtendedAttribute("NeedNewResolve") and
return (self.interface.getExtendedAttribute("NeedResolve") and
self.interface.identifier.name not in ["HTMLObjectElement",
"HTMLEmbedElement",
"HTMLAppletElement"])

View File

@ -1225,7 +1225,7 @@ class IDLInterface(IDLObjectWithScope):
self.parentScope.globalNames.add(self.identifier.name)
self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name)
self._isOnGlobalProtoChain = True
elif (identifier == "NeedNewResolve" or
elif (identifier == "NeedResolve" or
identifier == "OverrideBuiltins" or
identifier == "ChromeOnly" or
identifier == "Unforgeable" or

View File

@ -2027,7 +2027,6 @@ BackgroundCursorChild::SendContinueInternal(const CursorRequestParams& aParams)
MOZ_ASSERT(!mStrongCursor);
// Make sure all our DOM objects stay alive.
mStrongRequest = mRequest;
mStrongCursor = mCursor;
MOZ_ASSERT(mRequest->ReadyState() == IDBRequestReadyState::Done);
@ -2119,9 +2118,7 @@ BackgroundCursorChild::HandleResponse(
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(cloneReadInfo));
} else {
newCursor = IDBCursor::Create(mObjectStore,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(cloneReadInfo));
mCursor = newCursor;
@ -2150,10 +2147,7 @@ BackgroundCursorChild::HandleResponse(
if (mCursor) {
mCursor->Reset(Move(response.key()));
} else {
newCursor = IDBCursor::Create(mObjectStore,
this,
mDirection,
Move(response.key()));
newCursor = IDBCursor::Create(this, Move(response.key()));
mCursor = newCursor;
}
@ -2187,9 +2181,7 @@ BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
Move(response.objectKey()),
Move(cloneReadInfo));
} else {
newCursor = IDBCursor::Create(mIndex,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.objectKey()),
Move(cloneReadInfo));
@ -2218,9 +2210,7 @@ BackgroundCursorChild::HandleResponse(const IndexKeyCursorResponse& aResponse)
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(response.objectKey()));
} else {
newCursor = IDBCursor::Create(mIndex,
this,
mDirection,
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.objectKey()));
mCursor = newCursor;
@ -2265,8 +2255,8 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
MOZ_ASSERT(mRequest);
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mStrongRequest);
MOZ_ASSERT_IF(mCursor, mStrongCursor);
MOZ_ASSERT_IF(!mCursor, mStrongRequest);
MaybeCollectGarbageOnIPCMessage();

View File

@ -568,6 +568,38 @@ public:
void
SendDeleteMeInternal();
IDBRequest*
GetRequest() const
{
AssertIsOnOwningThread();
return mRequest;
}
IDBObjectStore*
GetObjectStore() const
{
AssertIsOnOwningThread();
return mObjectStore;
}
IDBIndex*
GetIndex() const
{
AssertIsOnOwningThread();
return mIndex;
}
Direction
GetDirection() const
{
AssertIsOnOwningThread();
return mDirection;
}
private:
// Only destroyed by BackgroundTransactionChild or
// BackgroundVersionChangeTransactionChild.

View File

@ -27,23 +27,20 @@ namespace dom {
namespace indexedDB {
IDBCursor::IDBCursor(Type aType,
IDBObjectStore* aSourceObjectStore,
IDBIndex* aSourceIndex,
IDBTransaction* aTransaction,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey)
: mSourceObjectStore(aSourceObjectStore)
, mSourceIndex(aSourceIndex)
, mTransaction(aTransaction)
, mBackgroundActor(aBackgroundActor)
, mScriptOwner(aTransaction->Database()->GetScriptOwner())
: mBackgroundActor(aBackgroundActor)
, mRequest(aBackgroundActor->GetRequest())
, mSourceObjectStore(aBackgroundActor->GetObjectStore())
, mSourceIndex(aBackgroundActor->GetIndex())
, mTransaction(mRequest->GetTransaction())
, mScriptOwner(mTransaction->Database()->GetScriptOwner())
, mCachedKey(JSVAL_VOID)
, mCachedPrimaryKey(JSVAL_VOID)
, mCachedValue(JSVAL_VOID)
, mKey(aKey)
, mType(aType)
, mDirection(aDirection)
, mDirection(aBackgroundActor->GetDirection())
, mHaveCachedKey(false)
, mHaveCachedPrimaryKey(false)
, mHaveCachedValue(false)
@ -51,12 +48,13 @@ IDBCursor::IDBCursor(Type aType,
, mContinueCalled(false)
, mHaveValue(true)
{
MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
aSourceObjectStore);
MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, aSourceIndex);
MOZ_ASSERT(aTransaction);
aTransaction->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(mRequest);
MOZ_ASSERT_IF(aType == Type_ObjectStore || aType == Type_ObjectStoreKey,
mSourceObjectStore);
MOZ_ASSERT_IF(aType == Type_Index || aType == Type_IndexKey, mSourceIndex);
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(mScriptOwner);
@ -80,25 +78,18 @@ IDBCursor::~IDBCursor()
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
StructuredCloneReadInfo&& aCloneInfo)
{
MOZ_ASSERT(aObjectStore);
aObjectStore->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStore,
aObjectStore,
nullptr,
aObjectStore->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_ObjectStore, aBackgroundActor, aKey);
cursor->mCloneInfo = Move(aCloneInfo);
@ -107,51 +98,37 @@ IDBCursor::Create(IDBObjectStore* aObjectStore,
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey)
{
MOZ_ASSERT(aObjectStore);
aObjectStore->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aBackgroundActor->GetIndex());
MOZ_ASSERT(!aKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_ObjectStoreKey,
aObjectStore,
nullptr,
aObjectStore->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_ObjectStoreKey, aBackgroundActor, aKey);
return cursor.forget();
}
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey,
StructuredCloneReadInfo&& aCloneInfo)
{
MOZ_ASSERT(aIndex);
aIndex->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_Index,
nullptr,
aIndex,
aIndex->ObjectStore()->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_Index, aBackgroundActor, aKey);
cursor->mPrimaryKey = Move(aPrimaryKey);
cursor->mCloneInfo = Move(aCloneInfo);
@ -161,26 +138,19 @@ IDBCursor::Create(IDBIndex* aIndex,
// static
already_AddRefed<IDBCursor>
IDBCursor::Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
IDBCursor::Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey)
{
MOZ_ASSERT(aIndex);
aIndex->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor);
aBackgroundActor->AssertIsOnOwningThread();
MOZ_ASSERT(aBackgroundActor->GetIndex());
MOZ_ASSERT(!aBackgroundActor->GetObjectStore());
MOZ_ASSERT(!aKey.IsUnset());
MOZ_ASSERT(!aPrimaryKey.IsUnset());
nsRefPtr<IDBCursor> cursor =
new IDBCursor(Type_IndexKey,
nullptr,
aIndex,
aIndex->ObjectStore()->Transaction(),
aBackgroundActor,
aDirection,
aKey);
new IDBCursor(Type_IndexKey, aBackgroundActor, aKey);
cursor->mPrimaryKey = Move(aPrimaryKey);
@ -800,9 +770,9 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceIndex)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
@ -819,7 +789,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
// Don't unlink mSourceObjectStore or mSourceIndex or mTransaction!
// Don't unlink mRequest, mSourceObjectStore, or mSourceIndex!
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

View File

@ -59,11 +59,14 @@ private:
Type_IndexKey,
};
BackgroundCursorChild* mBackgroundActor;
nsRefPtr<IDBRequest> mRequest;
nsRefPtr<IDBObjectStore> mSourceObjectStore;
nsRefPtr<IDBIndex> mSourceIndex;
nsRefPtr<IDBTransaction> mTransaction;
BackgroundCursorChild* mBackgroundActor;
// mSourceObjectStore or mSourceIndex will hold this alive.
IDBTransaction* mTransaction;
JS::Heap<JSObject*> mScriptOwner;
@ -88,30 +91,22 @@ private:
public:
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
StructuredCloneReadInfo&& aCloneInfo);
static already_AddRefed<IDBCursor>
Create(IDBObjectStore* aObjectStore,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey);
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey,
StructuredCloneReadInfo&& aCloneInfo);
static already_AddRefed<IDBCursor>
Create(IDBIndex* aIndex,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
Create(BackgroundCursorChild* aBackgroundActor,
const Key& aKey,
const Key& aPrimaryKey);
@ -194,11 +189,7 @@ public:
private:
IDBCursor(Type aType,
IDBObjectStore* aSourceObjectStore,
IDBIndex* aSourceIndex,
IDBTransaction* aTransaction,
BackgroundCursorChild* aBackgroundActor,
Direction aDirection,
const Key& aKey);
~IDBCursor();

View File

@ -46,6 +46,7 @@ support-files =
unit/test_indexes.js
unit/test_indexes_bad_values.js
unit/test_indexes_funny_things.js
unit/test_invalid_cursor.js
unit/test_invalid_version.js
unit/test_invalidate.js
unit/test_key_requirements.js
@ -267,6 +268,8 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_indexes_funny_things.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalid_cursor.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalid_version.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_invalidate.html]

View File

@ -0,0 +1,18 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>IndexedDB Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_invalid_cursor.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,62 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
let testGenerator = testSteps();
function testSteps()
{
const dbName = ("window" in this) ? window.location.pathname : "test";
const dbVersion = 1;
const objectStoreName = "foo";
const data = 0;
let req = indexedDB.open(dbName, dbVersion);
req.onerror = errorHandler;
req.onupgradeneeded = grabEventAndContinueHandler;
req.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "upgradeneeded", "Got upgradeneeded event");
let db = event.target.result;
let objectStore =
db.createObjectStore(objectStoreName, { autoIncrement: true });
objectStore.add(data);
event = yield undefined;
is(event.type, "success", "Got success event for open");
objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
objectStore.openCursor().onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.type, "success", "Got success event for openCursor");
let cursor = event.target.result;
is(cursor.value, data, "Got correct cursor value");
objectStore.get(cursor.key).onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.target.result, data, "Got correct get value");
info("Collecting garbage");
gc();
info("Done collecting garbage");
cursor.continue();
event = yield undefined;
is(event.target.result, null, "No more entries");
finishTest();
yield undefined;
}

View File

@ -36,6 +36,7 @@ skip-if = toolkit == 'android' # bug 1079278
[test_indexes.js]
[test_indexes_bad_values.js]
[test_indexes_funny_things.js]
[test_invalid_cursor.js]
[test_invalid_version.js]
[test_key_requirements.js]
[test_keys.js]

View File

@ -345,11 +345,9 @@ DOMMediaStream::CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
switch (aType) {
case MediaSegment::AUDIO:
track = new AudioStreamTrack(this, aTrackID);
mTrackTypesAvailable |= HINT_CONTENTS_AUDIO;
break;
case MediaSegment::VIDEO:
track = new VideoStreamTrack(this, aTrackID);
mTrackTypesAvailable |= HINT_CONTENTS_VIDEO;
break;
default:
MOZ_CRASH("Unhandled track type");
@ -369,7 +367,7 @@ DOMMediaStream::BindDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
track = mTracks[i]->AsAudioStreamTrack();
if (track) {
track->BindTrackID(aTrackID);
MOZ_ASSERT(mTrackTypesAvailable & HINT_CONTENTS_AUDIO);
mTrackTypesAvailable |= HINT_CONTENTS_AUDIO;
break;
}
}
@ -380,7 +378,7 @@ DOMMediaStream::BindDOMTrack(TrackID aTrackID, MediaSegment::Type aType)
track = mTracks[i]->AsVideoStreamTrack();
if (track) {
track->BindTrackID(aTrackID);
MOZ_ASSERT(mTrackTypesAvailable & HINT_CONTENTS_VIDEO);
mTrackTypesAvailable |= HINT_CONTENTS_VIDEO;
break;
}
}

View File

@ -288,7 +288,7 @@ protected:
// Indicate what track types we eventually expect to add to this stream
uint8_t mHintContents;
// Indicate what track types have been added to this stream
// Indicate what track types have arrived in this stream
uint8_t mTrackTypesAvailable;
bool mNotifiedOfMediaStreamGraphShutdown;

View File

@ -1823,11 +1823,15 @@ MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll)
BLOCK_SIZE - blockOffset);
gMediaCache->AllocateAndWriteBlock(this, mPartialBlockBuffer,
mMetadataInPartialBlockBuffer ? MODE_METADATA : MODE_PLAYBACK);
if (aNotifyAll) {
}
// |mChannelOffset == 0| means download ends with no bytes received.
// We should also wake up those readers who are waiting for data
// that will never come.
if ((blockOffset > 0 || mChannelOffset == 0) && aNotifyAll) {
// Wake up readers who may be waiting for this data
mon.NotifyAll();
}
}
}
void

View File

@ -91,6 +91,19 @@ public:
return true;
}
virtual bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) MOZ_OVERRIDE
{
nsresult rv = mResource->ReadFromCache(reinterpret_cast<char*>(aBuffer),
aOffset, aCount);
if (NS_FAILED(rv)) {
*aBytesRead = 0;
return false;
}
*aBytesRead = aCount;
return true;
}
virtual bool Length(int64_t* aSize) MOZ_OVERRIDE
{
if (mResource->GetLength() < 0)
@ -785,14 +798,7 @@ void
MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
int64_t aOffset)
{
if (NS_IsMainThread()) {
if (GetTaskQueue()) {
GetTaskQueue()->Dispatch(
NS_NewRunnableMethod(this, &MP4Reader::UpdateIndex));
}
} else {
UpdateIndex();
}
}
void

View File

@ -135,7 +135,8 @@ SourceBufferResource::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCo
this, aBuffer, aOffset, aCount);
ReentrantMonitorAutoEnter mon(mMonitor);
int64_t oldOffset = mOffset;
nsresult rv = ReadAt(aOffset, aBuffer, aCount, nullptr);
uint32_t bytesRead;
nsresult rv = ReadAt(aOffset, aBuffer, aCount, &bytesRead);
mOffset = oldOffset;
return rv;
}

View File

@ -366,6 +366,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
[test_eme_stream_capture_blocked.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
[test_empty_resource.html]
[test_error_in_video_document.html]
skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634
[test_error_on_404.html]
@ -436,8 +437,8 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_events_2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_twice.html]
# Seamonkey: Bug 598252, B2G: Bug 982100, Android: Bug 758476, bug 981086
skip-if = appname == "seamonkey" || toolkit == 'gonk' || toolkit == 'android'
# Seamonkey: Bug 598252
skip-if = appname == "seamonkey"
[test_playback.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_playback_errors.html]

View File

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1094549
-->
<head>
<title>Test for Bug 1094549</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094549">Mozilla Bug 1094549</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
function onTimeout() {
ok(false, "timed out without getting an error event");
SimpleTest.finish();
}
// We expect this test to finish very soon.
// A timeout of 15s should be enough for the slow B2G emulator.
var timer = setTimeout(onTimeout, 15000);
function finish(v) {
clearTimeout(timer);
isnot(v.error, null, "should've got an error event");
SimpleTest.finish();
}
function onload() {
info("iframe loaded");
var v = document.body.getElementsByTagName("iframe")[0]
.contentDocument.body.getElementsByTagName("video")[0];
// Got 'error' as expected, finish the test.
if (v.error) {
finish(v);
return;
}
// Otherwise, wait for it.
v.onerror = function() {
finish(v);
}
}
SimpleTest.waitForExplicitFinish();
var f = document.createElement("iframe");
// Assign a resource file with zero length and expect the error event from
// the video element since decoding metadata will fail.
f.src = "data:video/webm,";
f.addEventListener("load", onload, false);
document.body.appendChild(f);
</script>
</pre>
</body>
</html>

View File

@ -14,51 +14,67 @@ var manager = new MediaTestManager;
function startTest(test, token) {
var v = document.createElement('video');
v.preload = "metadata";
v.token = token;
manager.started(token);
v.src = test.name;
v.name = test.name;
v.playingCount = 0;
v._playedOnce = false;
var check = function(test, v) { return function() {
checkMetadata(test.name, v, test);
}}(test, v);
var noLoad = function(test, v) { return function() {
ok(false, test.name + " should not fire 'load' event");
}}(test, v);
function finish(v) {
removeNodeAndSource(v);
manager.finished(v.token);
}
function mayFinish(v) {
if (v.seenEnded && v.seenSuspend) {
finish(v);
}
}
var checkEnded = function(test, v) { return function() {
if (test.duration) {
ok(Math.abs(v.currentTime - test.duration) < 0.1,
test.name + " current time at end: " + v.currentTime);
}
is(v.readyState, v.HAVE_CURRENT_DATA, test.name + " checking readyState");
ok(v.readyState != v.NETWORK_LOADED, test.name + " shouldn't report NETWORK_LOADED");
ok(v.ended, test.name + " checking playback has ended");
ok(v.playingCount > 0, "Expect at least one playing event");
v.playingCount = 0;
if (v._playedOnce && v.seenSuspend) {
v.parentNode.removeChild(v);
manager.finished(v.token);
if (v._playedOnce) {
v.seenEnded = true;
mayFinish(v);
} else {
v._playedOnce = true;
v.play();
}
}}(test, v);
var checkSuspended = function(test, v) { return function() {
if (v.seenSuspend)
if (v.seenSuspend) {
return;
}
v.seenSuspend = true;
ok(true, test.name + " got suspend");
if (v._playedOnce && v.seenSuspend) {
v.parentNode.removeChild(v);
manager.finished(v.token);
}
mayFinish(v);
}}(test, v);
var checkPlaying = function(test, v) { return function() {
is(test.name, v.name, "Should be testing file we think we're testing...");
v.playingCount++;
}}(test, v);
v.addEventListener("load", noLoad, false);
v.addEventListener("loadedmetadata", check, false);
v.addEventListener("playing", checkPlaying, false);

View File

@ -158,8 +158,8 @@ NPObjWrapper_newEnumerate(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp
JS::Value *statep, jsid *idp);
static bool
NPObjWrapper_NewResolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSObject*> objp);
NPObjWrapper_Resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool *resolvedp);
static bool
NPObjWrapper_Convert(JSContext *cx, JS::Handle<JSObject*> obj, JSType type, JS::MutableHandle<JS::Value> vp);
@ -184,13 +184,13 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
const static js::Class sNPObjectJSWrapperClass =
{
NPRUNTIME_JSCLASS_NAME,
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_ENUMERATE,
NPObjWrapper_AddProperty,
NPObjWrapper_DelProperty,
NPObjWrapper_GetProperty,
NPObjWrapper_SetProperty,
(JSEnumerateOp)NPObjWrapper_newEnumerate,
(JSResolveOp)NPObjWrapper_NewResolve,
NPObjWrapper_Resolve,
NPObjWrapper_Convert,
NPObjWrapper_Finalize,
NPObjWrapper_Call,
@ -201,7 +201,6 @@ const static js::Class sNPObjectJSWrapperClass =
{
nullptr, /* outerObject */
nullptr, /* innerObject */
nullptr, /* iteratorObject */
false, /* isWrappedNative */
nullptr, /* weakmapKeyDelegateOp */
NPObjWrapper_ObjectMoved
@ -1654,8 +1653,8 @@ NPObjWrapper_newEnumerate(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp
}
static bool
NPObjWrapper_NewResolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSObject*> objp)
NPObjWrapper_Resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
bool *resolvedp)
{
if (JSID_IS_SYMBOL(id))
return true;
@ -1685,7 +1684,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsi
return false;
}
objp.set(obj);
*resolvedp = true;
return true;
}
@ -1701,7 +1700,7 @@ NPObjWrapper_NewResolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsi
JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallNPMethod, 0,
JSPROP_ENUMERATE);
objp.set(obj);
*resolvedp = true;
return fnc != nullptr;
}

View File

@ -22,6 +22,7 @@ support-files =
[test_event_stopping.html]
[test_template.html]
[test_template_xhtml.html]
[test_template_custom_elements.html]
[test_shadowroot.html]
[test_shadowroot_inert_element.html]
[test_shadowroot_host.html]

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1091425
-->
<head>
<title>Test for custom elements in template</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<template>
<x-foo></x-foo>
</template>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1091425">Bug 1091425</a>
<script>
var p = {};
p.createdCallback = function() {
ok(false, "Created callback should not be called for custom elements in templates.");
};
document.registerElement("x-foo", { prototype: p });
ok(true, "Created callback should not be called for custom elements in templates.");
</script>
<template>
<x-foo></x-foo>
</template>
</body>
</html>

View File

@ -12,7 +12,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-applet-element
[NeedNewResolve]
[NeedResolve]
interface HTMLAppletElement : HTMLElement {
[Pure, SetterThrows]
attribute DOMString align;

View File

@ -13,7 +13,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-embed-element
[NeedNewResolve]
[NeedResolve]
interface HTMLEmbedElement : HTMLElement {
[Pure, SetterThrows]
attribute DOMString src;

View File

@ -13,7 +13,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-object-element
[NeedNewResolve]
[NeedResolve]
interface HTMLObjectElement : HTMLElement {
[Pure, SetterThrows]
attribute DOMString data;

View File

@ -19,7 +19,7 @@
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object
[HeaderFile="Navigator.h", NeedNewResolve]
[HeaderFile="Navigator.h", NeedResolve]
interface Navigator {
// objects implementing this interface also implement the interfaces given below
};

View File

@ -24,7 +24,7 @@ interface nsIDOMCrypto;
typedef any Transferable;
// http://www.whatwg.org/specs/web-apps/current-work/
[PrimaryGlobal, NeedNewResolve]
[PrimaryGlobal, NeedResolve]
/*sealed*/ interface Window : EventTarget {
// the current browsing context
[Unforgeable, Throws,

View File

@ -15,12 +15,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1027221
SimpleTest.waitForExplicitFinish();
var x = "x";
// Trigger some incremental gc
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
SpecialPowers.Cu.getJSTestingFunctions().gcslice(1);
// Kick off a worker that uses this same atom
var w = new Worker("data:text/plain,Promise.resolve('x').then(function() { postMessage(1); });");
// Maybe trigger some more incremental gc
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
SpecialPowers.Cu.getJSTestingFunctions().gcslice(1);
w.onmessage = function() {
ok(true, "Got here");

View File

@ -90,7 +90,6 @@ XBLEnumerate(JSContext *cx, JS::Handle<JSObject*> obj)
static const JSClass gPrototypeJSClass = {
"XBL prototype JSClass",
JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
JSCLASS_NEW_RESOLVE |
// Our one reserved slot holds the relevant nsXBLPrototypeBinding
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, JS_DeletePropertyStub,

View File

@ -598,7 +598,6 @@ gfxFontconfigUtils::UpdateFontListInternal(bool aForce)
mFontsByFamily.Clear();
mFontsByFullname.Clear();
mLangSupportTable.Clear();
mAliasForMultiFonts.Clear();
// Record the existing font families
for (unsigned fs = 0; fs < ArrayLength(fontSets); ++fs) {
@ -632,36 +631,6 @@ gfxFontconfigUtils::UpdateFontListInternal(bool aForce)
}
}
// XXX we don't support all alias names.
// Because if we don't check whether the given font name is alias name,
// fontconfig converts the non existing font to sans-serif.
// This is not good if the web page specifies font-family
// that has Windows font name in the first.
NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
nsAdoptingCString list = Preferences::GetCString("font.alias-list");
if (!list.IsEmpty()) {
const char kComma = ',';
const char *p, *p_end;
list.BeginReading(p);
list.EndReading(p_end);
while (p < p_end) {
while (nsCRT::IsAsciiSpace(*p)) {
if (++p == p_end)
break;
}
if (p == p_end)
break;
const char *start = p;
while (++p != p_end && *p != kComma)
/* nothing */ ;
nsAutoCString name(Substring(start, p));
name.CompressWhitespace(false, true);
mAliasForMultiFonts.AppendElement(name);
p++;
}
}
mLastConfig = currentConfig;
return NS_OK;
}

View File

@ -302,8 +302,6 @@ protected:
nsTHashtable<LangSupportEntry> mLangSupportTable;
const nsTArray< nsCountedRef<FcPattern> > mEmptyPatternArray;
nsTArray<nsCString> mAliasForMultiFonts;
FcConfig *mLastConfig;
#ifdef MOZ_BUNDLED_FONTS

View File

@ -1227,12 +1227,6 @@ PrepareSortPattern(FcPattern *aPattern, double aFallbackSize,
cairo_font_options_destroy(options);
FcPatternAddBool(aPattern, PRINTING_FC_PROPERTY, FcTrue);
} else {
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
cairo_font_options_t *options = cairo_font_options_create();
cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
cairo_ft_font_options_substitute(options, aPattern);
cairo_font_options_destroy(options);
#endif
#ifdef MOZ_WIDGET_GTK
ApplyGdkScreenFontOptions(aPattern);
#endif
@ -1965,15 +1959,11 @@ CreateScaledFont(FcPattern *aPattern, cairo_font_face_t *aFace)
// font will be used, but currently we don't have different gfxFonts for
// different surface font_options, so we'll create a font suitable for the
// Screen. Image and xlib surfaces default to CAIRO_HINT_METRICS_ON.
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
#else
if (printing) {
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
} else {
cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_ON);
}
#endif
// The remaining options have been recorded on the pattern and the face.
// _cairo_ft_options_merge has some logic to decide which options from the
@ -1998,11 +1988,10 @@ CreateScaledFont(FcPattern *aPattern, cairo_font_face_t *aFace)
//
// Fallback values here mirror treatment of defaults in cairo-ft-font.c.
FcBool hinting = FcFalse;
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
if (FcPatternGetBool(aPattern, FC_HINTING, 0, &hinting) != FcResultMatch) {
hinting = FcTrue;
}
#endif
cairo_hint_style_t hint_style;
if (printing || !hinting) {
hint_style = CAIRO_HINT_STYLE_NONE;

View File

@ -949,7 +949,8 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
gfxFloat
gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
PropertyProvider *aProvider)
PropertyProvider *aProvider,
PropertyProvider::Spacing* aSpacing)
{
NS_ASSERTION(aStart + aLength <= GetLength(), "Substring out of range");
@ -960,6 +961,10 @@ gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
gfxFloat result = ComputePartialLigatureWidth(aStart, ligatureRunStart, aProvider) +
ComputePartialLigatureWidth(ligatureRunEnd, aStart + aLength, aProvider);
if (aSpacing) {
aSpacing->mBefore = aSpacing->mAfter = 0;
}
// Account for all remaining spacing here. This is more efficient than
// processing it along with the glyphs.
if (aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) {
@ -972,6 +977,10 @@ gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
PropertyProvider::Spacing *space = &spacingBuffer[i];
result += space->mBefore + space->mAfter;
}
if (aSpacing) {
aSpacing->mBefore = spacingBuffer[0].mBefore;
aSpacing->mAfter = spacingBuffer.LastElement().mAfter;
}
}
}

View File

@ -267,9 +267,13 @@ public:
/**
* Computes just the advance width for a substring.
* Uses GetSpacing from aBreakProvider.
* If aSpacing is not null, the spacing attached before and after
* the substring would be returned in it. NOTE: the spacing is
* included in the advance width.
*/
gfxFloat GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
PropertyProvider *aProvider);
PropertyProvider *aProvider,
PropertyProvider::Spacing* aSpacing = nullptr);
/**
* Clear all stored line breaks for the given range (both before and after),

View File

@ -26,6 +26,9 @@ interface nsITextToSubURI : nsISupports
* give the original escaped string
* <li> In case of a conversion error, the URI fragment (escaped) is
* assumed to be in UTF-8 and converted to AString (UTF-16)
* <li> In case of successful conversion to unicode but it contains
* any characters in network.IDN.blacklist_chars (except space)
* then the final result is escaped
* <li> Always succeeeds (callers don't need to do error checking)
* </ul>
*

View File

@ -10,11 +10,38 @@
#include "nsTextToSubURI.h"
#include "nsCRT.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/Preferences.h"
#include "nsISupportsPrimitives.h"
using mozilla::dom::EncodingUtils;
// Fallback value for the pref "network.IDN.blacklist_chars".
// UnEscapeURIForUI allows unescaped space; other than that, this is
// the same as the default "network.IDN.blacklist_chars" value.
static const char16_t sNetworkIDNBlacklistChars[] =
{
/*0x0020,*/
0x00A0, 0x00BC, 0x00BD, 0x00BE, 0x01C3, 0x02D0, 0x0337,
0x0338, 0x0589, 0x05C3, 0x05F4, 0x0609, 0x060A, 0x066A, 0x06D4,
0x0701, 0x0702, 0x0703, 0x0704, 0x115F, 0x1160, 0x1735, 0x2000,
0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
0x2009, 0x200A, 0x200B, 0x200E, 0x200F, 0x2024, 0x2027, 0x2028,
0x2029, 0x202A, 0x202B, 0x202C, 0x202D, 0x202E, 0x202F, 0x2039,
0x203A, 0x2041, 0x2044, 0x2052, 0x205F, 0x2153, 0x2154, 0x2155,
0x2156, 0x2157, 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D,
0x215E, 0x215F, 0x2215, 0x2236, 0x23AE, 0x2571, 0x29F6, 0x29F8,
0x2AFB, 0x2AFD, 0x2FF0, 0x2FF1, 0x2FF2, 0x2FF3, 0x2FF4, 0x2FF5,
0x2FF6, 0x2FF7, 0x2FF8, 0x2FF9, 0x2FFA, 0x2FFB, 0x3000, 0x3002,
0x3014, 0x3015, 0x3033, 0x3164, 0x321D, 0x321E, 0x33AE, 0x33AF,
0x33C6, 0x33DF, 0xA789, 0xFE14, 0xFE15, 0xFE3F, 0xFE5D, 0xFE5E,
0xFEFF, 0xFF0E, 0xFF0F, 0xFF61, 0xFFA0, 0xFFF9, 0xFFFA, 0xFFFB,
0xFFFC, 0xFFFD,
'\0'
};
nsTextToSubURI::nsTextToSubURI()
{
mUnsafeChars.SetIsVoid(true);
}
nsTextToSubURI::~nsTextToSubURI()
{
@ -213,9 +240,36 @@ NS_IMETHODIMP nsTextToSubURI::UnEscapeURIForUI(const nsACString & aCharset,
// sequences are also considered failure in this context
if (convertURItoUnicode(
PromiseFlatCString(aCharset), unescapedSpec, true, _retval)
!= NS_OK)
!= NS_OK) {
// assume UTF-8 instead of ASCII because hostname (IDN) may be in UTF-8
CopyUTF8toUTF16(aURIFragment, _retval);
}
// if there are any characters that are unsafe for IRIs, reescape.
if (mUnsafeChars.IsVoid()) {
nsCOMPtr<nsISupportsString> blacklist;
nsresult rv = mozilla::Preferences::GetComplex("network.IDN.blacklist_chars",
NS_GET_IID(nsISupportsString),
getter_AddRefs(blacklist));
if (NS_SUCCEEDED(rv)) {
blacklist->ToString(getter_Copies(mUnsafeChars));
mUnsafeChars.StripChars(" "); // we allow SPACE in this method
MOZ_ASSERT(!mUnsafeChars.IsVoid());
} else {
NS_WARNING("Failed to get the 'network.IDN.blacklist_chars' preference");
}
}
// We check IsEmpty() intentionally here instead of IsVoid() because an
// empty (or just spaces) pref value is likely a mistake/error of some sort.
const char16_t* unsafeChars =
mUnsafeChars.IsEmpty() ? sNetworkIDNBlacklistChars : mUnsafeChars;
if (PromiseFlatString(_retval).FindCharInSet(unsafeChars) != kNotFound) {
// Note that this reescapes all non-ASCII characters in the URI, not just
// the unsafe characters.
nsString reescapedSpec;
_retval = NS_EscapeURL(_retval, esc_OnlyNonASCII, reescapedSpec);
}
return NS_OK;
}

View File

@ -32,6 +32,9 @@ private:
const nsAFlatCString &aURI,
bool aIRI,
nsAString &_retval);
// Void until we get the pref "network.IDN.blacklist_chars" successfully.
nsXPIDLString mUnsafeChars;
};
#endif // nsTextToSubURI_h__

View File

@ -119,24 +119,12 @@ typedef bool
// (e.g., the DOM attributes for a given node reflected as obj) on demand.
//
// JS looks for a property in an object, and if not found, tries to resolve
// the given id. If resolve succeeds, the engine looks again in case resolve
// defined obj[id]. If no such property exists directly in obj, the process
// is repeated with obj's prototype, etc.
// the given id. *resolvedp should be set to true iff the property was
// was defined on |obj|.
//
// NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
typedef bool
(* JSResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
// Like JSResolveOp, except the *objp out parameter, on success, should be null
// to indicate that id was not resolved; and non-null, referring to obj or one
// of its prototypes, if id was resolved. The hook may assume *objp is null on
// entry.
//
// This hook instead of JSResolveOp is called via the JSClass.resolve member
// if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
typedef bool
(* JSNewResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleObject objp);
(* JSResolveOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
bool *resolvedp);
// Convert obj to the given type, returning true with the resulting value in
// *vp on success, and returning false on error or exception.
@ -177,11 +165,6 @@ typedef bool
typedef void
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
// Hook that creates an iterator object for a given object. Returns the
// iterator object or null if an error or exception was thrown on cx.
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JS::HandleObject obj, bool keysonly);
typedef JSObject *
(* JSWeakmapKeyDelegateOp)(JSObject *obj);
@ -325,7 +308,6 @@ struct ClassExtension
{
ObjectOp outerObject;
InnerObjectOp innerObject;
JSIteratorOp iteratorObject;
/*
* isWrappedNative is true only if the class is an XPCWrappedNative.
@ -361,7 +343,7 @@ struct ClassExtension
};
#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
#define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr,nullptr}
#define JS_NULL_CLASS_EXT {nullptr,nullptr,false,nullptr,nullptr}
struct ObjectOps
{
@ -401,12 +383,11 @@ typedef void (*JSClassInternal)();
struct JSClass {
JS_CLASS_MEMBERS(JSFinalizeOp);
void *reserved[33];
void *reserved[32];
};
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
#define JSCLASS_NEW_ENUMERATE (1<<1) // has JSNewEnumerateOp hook
#define JSCLASS_NEW_RESOLVE (1<<2) // has JSNewResolveOp hook
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports *)
#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
#define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) // Correctly implements GC read

View File

@ -11,11 +11,25 @@
namespace js {
struct JS_PUBLIC_API(TimeBudget)
{
int64_t budget;
explicit TimeBudget(int64_t milliseconds) { budget = milliseconds; }
};
struct JS_PUBLIC_API(WorkBudget)
{
int64_t budget;
explicit WorkBudget(int64_t work) { budget = work; }
};
/*
* This class records how much work has been done in a given collection slice, so that
* we can return before pausing for too long. Some slices are allowed to run for
* unlimited time, and others are bounded. To reduce the number of gettimeofday
* calls, we only check the time every 1000 operations.
* This class records how much work has been done in a given collection slice,
* so that we can return before pausing for too long. Some slices are allowed
* to run for unlimited time, and others are bounded. To reduce the number of
* gettimeofday calls, we only check the time every 1000 operations.
*/
struct JS_PUBLIC_API(SliceBudget)
{
@ -24,17 +38,18 @@ struct JS_PUBLIC_API(SliceBudget)
static const intptr_t CounterReset = 1000;
static const int64_t Unlimited = 0;
static int64_t TimeBudget(int64_t millis);
static int64_t WorkBudget(int64_t work);
static const int64_t Unlimited = -1;
/* Equivalent to SliceBudget(UnlimitedBudget). */
/* Use to create an unlimited budget. */
SliceBudget();
/* Instantiate as SliceBudget(Time/WorkBudget(n)). */
explicit SliceBudget(int64_t budget);
/* Instantiate as SliceBudget(TimeBudget(n)). */
explicit SliceBudget(TimeBudget time);
void reset() {
/* Instantiate as SliceBudget(WorkBudget(n)). */
explicit SliceBudget(WorkBudget work);
void makeUnlimited() {
deadline = unlimitedDeadline;
counter = unlimitedStartCounter;
}
@ -43,10 +58,8 @@ struct JS_PUBLIC_API(SliceBudget)
counter -= amt;
}
bool checkOverBudget();
bool isOverBudget() {
if (counter >= 0)
if (counter > 0)
return false;
return checkOverBudget();
}
@ -55,10 +68,11 @@ struct JS_PUBLIC_API(SliceBudget)
return deadline == unlimitedDeadline;
}
private:
private:
bool checkOverBudget();
static const int64_t unlimitedDeadline = INT64_MAX;
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
};
} // namespace js

View File

@ -9,8 +9,11 @@
#include "mozilla/NullPtr.h"
#include "jsalloc.h"
#include "jspubtd.h"
#include "js/HashTable.h"
class JS_PUBLIC_API(JSTracer);
namespace JS {
@ -212,6 +215,15 @@ JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
extern JS_PUBLIC_API(void)
JS_TraceRuntime(JSTracer *trc);
namespace JS {
typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
}
// Trace every value within |zones| that is wrapped by a cross-compartment
// wrapper from a zone that is not an element of |zones|.
extern JS_PUBLIC_API(void)
JS_TraceIncomingCCWs(JSTracer *trc, const JS::ZoneSet &zones);
extern JS_PUBLIC_API(void)
JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
void *thing, JSGCTraceKind kind, bool includeDetails);

View File

@ -17,6 +17,7 @@
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
// JS::ubi::Node
@ -135,7 +136,6 @@
// teach the GC how to root ubi::Nodes, fix up hash tables that use them as
// keys, etc.
namespace JS {
namespace ubi {

View File

@ -560,14 +560,15 @@ TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t
return true;
}
// Enable
// The exit may have become optimized while executing the FFI.
if (module.exitIsOptimized(exitIndex))
return true;
IonScript *ionScript = script->ionScript();
if (!ionScript->addDependentAsmJSModule(cx, DependentAsmJSModuleExit(&module, exitIndex)))
return false;
AsmJSModule::ExitDatum &exitDatum = module.exitIndexToGlobalDatum(exitIndex);
exitDatum.exit = module.ionExitTrampoline(module.exit(exitIndex));
exitDatum.ionScript = ionScript;
module.optimizeExit(exitIndex, ionScript);
return true;
}

View File

@ -1280,6 +1280,7 @@ class AsmJSModule
MOZ_ASSERT(isFinished());
return pc >= code_ && pc < (code_ + codeBytes());
}
private:
uint8_t *interpExitTrampoline(const Exit &exit) const {
MOZ_ASSERT(isFinished());
MOZ_ASSERT(exit.interpCodeOffset_);
@ -1290,6 +1291,7 @@ class AsmJSModule
MOZ_ASSERT(exit.ionCodeOffset_);
return code_ + exit.ionCodeOffset_;
}
public:
// Lookup a callsite by the return pc (from the callee to the caller).
// Return null if no callsite was found.
@ -1417,6 +1419,17 @@ class AsmJSModule
MOZ_ASSERT(isFinished());
return *(ExitDatum *)(globalData() + exitIndexToGlobalDataOffset(exitIndex));
}
bool exitIsOptimized(unsigned exitIndex) const {
MOZ_ASSERT(isFinished());
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
return exitDatum.exit != interpExitTrampoline(exit(exitIndex));
}
void optimizeExit(unsigned exitIndex, jit::IonScript *ionScript) const {
MOZ_ASSERT(!exitIsOptimized(exitIndex));
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
exitDatum.exit = ionExitTrampoline(exit(exitIndex));
exitDatum.ionScript = ionScript;
}
void detachIonCompilation(size_t exitIndex) const {
MOZ_ASSERT(isFinished());
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);

View File

@ -628,16 +628,15 @@ GCSlice(JSContext *cx, unsigned argc, Value *vp)
return false;
}
bool limit = true;
uint32_t budget = 0;
SliceBudget budget;
if (args.length() == 1) {
if (!ToUint32(cx, args[0], &budget))
uint32_t work = 0;
if (!ToUint32(cx, args[0], &work))
return false;
} else {
limit = false;
budget = SliceBudget(WorkBudget(work));
}
cx->runtime()->gc.gcDebugSlice(limit, budget);
cx->runtime()->gc.gcDebugSlice(budget);
args.rval().setUndefined();
return true;
}

View File

@ -160,7 +160,7 @@ function loadCallgraph(file)
suppressedFunctions[name] = true;
}
for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, int64, uint32, uint32)',
for (var gcName of [ 'void js::gc::GCRuntime::collect(uint8, js::SliceBudget*, uint32, uint32)',
'void js::gc::GCRuntime::minorGC(uint32)',
'void js::gc::GCRuntime::minorGC(uint32)' ])
{

View File

@ -281,7 +281,7 @@ class GCRuntime
void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0);
void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason);
void gcDebugSlice(bool limit, int64_t objCount);
void gcDebugSlice(SliceBudget &budget);
void runDebugGC();
inline void poke();
@ -510,14 +510,14 @@ class GCRuntime
bool initZeal();
void requestMajorGC(JS::gcreason::Reason reason);
void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind,
void collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
JS::gcreason::Reason reason);
bool gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind,
bool gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gckind,
JS::gcreason::Reason reason);
gcstats::ZoneGCStats scanZonesBeforeGC();
void budgetIncrementalGC(int64_t *budget);
void budgetIncrementalGC(SliceBudget &budget);
void resetIncrementalGC(const char *reason);
void incrementalCollectSlice(int64_t budget, JS::gcreason::Reason reason);
void incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason reason);
void pushZealSelectedObjects();
void purgeRuntime();
bool beginMarkPhase(JS::gcreason::Reason reason);

View File

@ -18,6 +18,7 @@
#include "gc/GCInternals.h"
#include "gc/Marking.h"
#include "gc/Zone.h"
#include "vm/Symbol.h"
@ -119,6 +120,37 @@ JS_TraceRuntime(JSTracer *trc)
TraceRuntime(trc);
}
JS_PUBLIC_API(void)
JS_TraceIncomingCCWs(JSTracer *trc, const JS::ZoneSet &zones)
{
for (js::ZonesIter z(trc->runtime(), SkipAtoms); !z.done(); z.next()) {
Zone *zone = z.get();
if (!zone || zones.has(zone))
continue;
for (js::CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
JSCompartment *comp = c.get();
if (!comp)
continue;
for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
const CrossCompartmentKey &key = e.front().key();
// StringWrappers are just used to avoid copying strings across
// zones multiple times, and don't hold a strong reference.
if (key.kind == CrossCompartmentKey::StringWrapper)
continue;
// Ignore CCWs whose wrapped value doesn't live in our given set
// of zones.
if (!zones.has(static_cast<JSObject *>(key.wrapped)->zone()))
continue;
void *thing = key.wrapped;
trc->callback(trc, &thing, GetGCThingTraceKind(key.wrapped));
}
}
}
}
static size_t
CountDecimalDigits(size_t num)
{

View File

@ -16,6 +16,7 @@
#include "gc/FindSCCs.h"
#include "gc/GCRuntime.h"
#include "js/TracingAPI.h"
namespace js {
@ -259,7 +260,6 @@ struct Zone : public JS::shadow::Zone,
//
// This is used during GC while calculating zone groups to record edges that
// can't be determined by examining this zone by itself.
typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
ZoneSet gcZoneGroupEdges;
// Malloc counter to measure memory pressure for GC scheduling. It runs from

View File

@ -28,7 +28,7 @@ gcPreserveCode();
try {
mjitChunkLimit(1);
} catch(exc1) {}
gcslice(0);
gcslice(1);
m(1);
gc();
m(2);

View File

@ -3,4 +3,4 @@
//
gc();
evaluate("gcslice(0);");
evaluate("gcslice(1);");

View File

@ -20,7 +20,7 @@ function h(code) {
h("\
p=m();\
gcPreserveCode();\
gcslice(7);\
gcslice(8);\
")
h("\"\"")
h("")

View File

@ -3,7 +3,7 @@
//
gc()
schedulegc(this)
gcslice(2)
gcslice(3)
function f() {
this["x"] = this["x"] = {}
}

View File

@ -5,8 +5,8 @@
function printBugNumber (num) {
BUGNUMBER = num;
}
gcslice(0)
gcslice(1)
schedulegc(this);
gcslice(1);
gcslice(2);
var BUGNUMBER = ("one");
printBugNumber();

View File

@ -116,7 +116,12 @@ var proxyObj = {
};
var p = new Proxy([1, 2, 3, 4, 5], proxyObj);
assertDeepEq(Array.prototype.copyWithin.call(p, 0, 3), [6, 7, , , 5]);
Array.prototype.copyWithin.call(p, 0, 3);
for (name of Object.getOwnPropertyNames(p)) {
print(name + ": " + uneval(Object.getOwnPropertyDescriptor(p, name)));
}
assertDeepEq(p, [6, 7, , , 5]);
// test if we throw in between
arr = [1, 2, 3, 4, 5];

View File

@ -1,6 +1,6 @@
var g1 = newGlobal();
schedulegc(g1);
gcslice(0);
gcslice(1);
function testEq(b) {
var a = deserialize(serialize(b));
}

View File

@ -4,7 +4,7 @@ function gen()
yield 1;
local = null;
gc();
gcslice(0);
gcslice(0); // Start IGC, but don't mark anything.
yield 2;
}

View File

@ -12,5 +12,5 @@ function recur(n)
}
validategc(false);
gcslice(0);
gcslice(1);
recur(10);

View File

@ -11,8 +11,8 @@ expect = "generator function foo returns a value";
actual = (function (j) {}).message;
reportCompare(expect, actual, summary + ": 1");
reportCompare(expect, actual, summary + ": 2");
gcslice(0);
gcslice(1);
gcslice(2);
gc();
var strings = [ (0), ];
for (var i = 0; i < strings.length; i++)

View File

@ -4,7 +4,7 @@ evalcx("\
gcslice = function() { };\
array = new Uint8Array;\
t0 = array.subarray();\
gcslice(11); \
gcslice(12); \
array.subarray();\
gc();\
gc();\

View File

@ -3,7 +3,7 @@
if (typeof evalInWorker == "undefined")
quit();
gcslice(10);
gcslice(11);
evalInWorker("print('helo world');");
for (i = 0; i < 100000; i++) {}

View File

@ -1,6 +1,6 @@
if (this.hasOwnProperty('Intl')) {
gc();
gcslice(0);
gcslice(1);
var thisValues = [ "x" ];
thisValues.forEach(function (value) {
var format = Intl.DateTimeFormat.call(value);

View File

@ -1,5 +1,5 @@
gc();
gcslice(0);
gcslice(1);
function isClone(a, b) {
var rmemory = new WeakMap();
rmemory.set(a,b);

View File

@ -9,5 +9,5 @@ var recursiveFunctions = [{
eval(a.text.replace(/@/g, ""))
}
})();
gcslice(2868);
gcslice(2869);
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()

View File

@ -10,5 +10,5 @@ var recursiveFunctions = [{
eval(a.text.replace(/@/g, ""))
}
})();
gcslice(2868);
gcslice(2869);
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()

View File

@ -10,5 +10,5 @@ var recursiveFunctions = [{
eval(a.text.replace(/@/g, ""))
}
})();
gcslice(2868);
gcslice(2869);
Function("v={c:[{x:[[]],N:{x:[{}[d]]}}]}=minorgc(true)")()

View File

@ -4,6 +4,6 @@ var juneDate = new Date(2000, 5, 20, 0, 0, 0, 0);
for (var i = 0; i < function(x) myObj(Date.prototype.toString.apply(x)); void i) {
eval(a.text.replace(/@/g, ""))
}
gcslice(2600);
gcslice(2601);
function testcase() {}
new Uint16Array(testcase);

View File

@ -23,7 +23,7 @@ function init()
*/
eval("init()");
gcslice(0);
gcslice(0); // Start IGC, but don't mark anything.
selectforgc(objs.root2);
gcslice(1);
objs.root2.ptr = objs.root1.ptr;

View File

@ -22,7 +22,7 @@ function init()
*/
eval("init()");
gcslice(0);
gcslice(0); // Start IGC, but don't mark anything.
selectforgc(objs.root);
gcslice(1);
delete objs.root.b;

View File

@ -4,7 +4,7 @@ var g1 = newGlobal();
var g2 = newGlobal();
schedulegc(g1);
gcslice(0);
gcslice(0); // Start IGC, but don't mark anything.
schedulegc(g2);
gcslice(1);
gcslice();

View File

@ -5,7 +5,7 @@ var g2 = newGlobal();
schedulegc(g1);
schedulegc(g2);
gcslice(0);
gcslice(0); // Start IGC, but don't mark anything.
schedulegc(g1);
gcslice(1);
gcslice();

View File

@ -0,0 +1,20 @@
// Assigning to a proxy with no set handler calls the defineProperty handler
// when no such property already exists.
var hits = 0;
var t = {};
var p = new Proxy(t, {
defineProperty(t, id, desc) { hits++; }
});
p.x = 1;
assertEq(hits, 1);
assertEq("x" in t, false);
// Same thing, but the receiver is a plain object inheriting from p:
var receiver = Object.create(p);
hits = 0;
receiver.x = 2;
assertEq(hits, 0);
assertEq("x" in t, false);
assertEq(receiver.hasOwnProperty("x"), true);
assertEq(receiver.x, 2);

View File

@ -0,0 +1,21 @@
// Assigning to a proxy with no set handler calls the defineProperty handler
// when an existing inherited data property already exists.
var hits = 0;
var proto = {x: 1};
var t = Object.create(proto);
var p = new Proxy(t, {
defineProperty(t, id, desc) { hits++; }
});
p.x = 2;
assertEq(hits, 1);
assertEq(proto.x, 1);
assertEq(t.hasOwnProperty("x"), false);
// Same thing, but the receiver is a plain object inheriting from p:
var receiver = Object.create(p);
receiver.x = 2;
assertEq(hits, 1);
assertEq(t.hasOwnProperty("x"), false);
assertEq(receiver.hasOwnProperty("x"), true);
assertEq(receiver.x, 2);

View File

@ -0,0 +1,24 @@
// Assigning to a missing array element (a hole) via a proxy with no set handler
// calls the defineProperty handler.
function test(id) {
var arr = [, 1, 2, 3];
var p = new Proxy(arr, {
defineProperty(t, id, desc) {
hits++;
assertEq(desc.value, "ponies");
assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
assertEq(desc.writable, true);
}
});
var hits = 0;
p[id] = "ponies";
assertEq(hits, 1);
assertEq(id in arr, false);
assertEq(arr.length, 4);
}
test(0);
test(4);
test("str");

View File

@ -0,0 +1,15 @@
"use strict";
if (this.Reflect && Reflect.set)
throw new Error("Congrats on implementing Reflect.set! Uncomment this test for 1 karma point.");
/*
load("asserts.js");
var a = [0, 1, 2, 3];
var p = new Proxy({}, {});
Reflect.set(p, "length", 2, a);
assertEq("length" in p, false);
assertEq(a.length, 2);
assertDeepEq(a, [0, 1]);
*/

View File

@ -0,0 +1,15 @@
// The receiver argument is passed through proxies with no "set" handler.
var hits;
var a = new Proxy({}, {
set(t, id, value, receiver) {
assertEq(id, "prop");
assertEq(value, 3);
assertEq(receiver, b);
hits++;
}
});
var b = new Proxy(a, {});
hits = 0;
b.prop = 3;
assertEq(hits, 1);

View File

@ -0,0 +1,26 @@
// BaseProxyHandler::set correctly defines a property on receiver if the
// property being assigned doesn't exist anywhere on the proto chain.
var p = Proxy.create({
getOwnPropertyDescriptor() { return undefined; },
getPropertyDescriptor() { return undefined; },
defineProperty() { throw "FAIL"; }
});
var q = new Proxy(p, {
defineProperty(t, id, desc) {
assertEq(t, p);
assertEq(id, "x");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, 3);
hits++;
}
});
var hits = 0;
// This assignment eventually reaches ScriptedIndirectProxyHandler::set
// with arguments (proxy=p, receiver=q). Test that it finishes by defining
// a property on receiver, not on proxy.
q.x = 3;
assertEq(hits, 1);

View File

@ -0,0 +1,8 @@
// A scripted proxy can delegate a [[Set]] along to a target
// that's a different kind of proxy.
var target = {};
var wrapper = wrapWithProto(target, null);
var p = new Proxy(wrapper, {});
p.prop = 3;
assertEq(target.prop, 3);

View File

@ -6533,12 +6533,12 @@ ClassHasResolveHook(CompileCompartment *comp, const Class *clasp, PropertyName *
if (clasp->resolve == JS_ResolveStub)
return false;
if (clasp->resolve == (JSResolveOp)str_resolve) {
if (clasp->resolve == str_resolve) {
// str_resolve only resolves integers, not names.
return false;
}
if (clasp->resolve == (JSResolveOp)fun_resolve)
if (clasp->resolve == fun_resolve)
return FunctionHasResolveHook(comp->runtime()->names(), name);
return true;

View File

@ -354,6 +354,7 @@ class MacroAssemblerNone : public Assembler
template <typename T> void unboxObject(T, Register) { MOZ_CRASH(); }
template <typename T> void unboxDouble(T, FloatRegister) { MOZ_CRASH(); }
void unboxValue(const ValueOperand &, AnyRegister) { MOZ_CRASH(); }
void unboxNonDouble(const ValueOperand &, Register ) { MOZ_CRASH();}
void notBoolean(ValueOperand) { MOZ_CRASH(); }
Register extractObject(Address, Register) { MOZ_CRASH(); }
Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }

View File

@ -19,7 +19,6 @@ UNIFIED_SOURCES += [
'testClassGetter.cpp',
'testCloneScript.cpp',
'testContexts.cpp',
'testCustomIterator.cpp',
'testDebugger.cpp',
'testDeepFreeze.cpp',
'testDefineGetterSetterNonEnumerable.cpp',
@ -38,6 +37,7 @@ UNIFIED_SOURCES += [
'testGCExactRooting.cpp',
'testGCFinalizeCallback.cpp',
'testGCHeapPostBarriers.cpp',
'testGCMarking.cpp',
'testGCOutOfMemory.cpp',
'testGCStoreBufferRemoval.cpp',
'testHashTable.cpp',

Some files were not shown because too many files have changed in this diff Show More