mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
55c995b79c
53 changed files with 1013 additions and 478 deletions
|
|
@ -37,6 +37,7 @@ pref("@GUAO_PREF@.dailymotion.com","Mozilla/5.0 (@OS_SLICE@ rv:52.0) @GK_SLICE@
|
|||
// The following requires native mode. Or it blocks.. "too old firefox", breakage, etc.
|
||||
|
||||
// UA-Sniffing domains below have indicated no interest in supporting Pale Moon (BOO!)
|
||||
pref("@GUAO_PREF@.whatsapp.com","Mozilla/5.0 (@OS_SLICE@ rv:61.0) @GK_SLICE@ Firefox/61.0");
|
||||
|
||||
// UA-sniffing domains that are "app/vendor-specific" and do not like Pale Moon
|
||||
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,9 @@ pref("security.csp.speccompliant", true);
|
|||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
// Disable Microsoft Family Safety MitM support
|
||||
pref("security.family_safety.mode", 0);
|
||||
|
||||
// Override the Gecko-default value of false for Pale Moon.
|
||||
pref("plain_text.wrap_long_lines", true);
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ pref("@GUAO_PREF@.deviantart.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GR
|
|||
pref("@GUAO_PREF@.deviantart.net","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
|
||||
pref("@GUAO_PREF@.altibox.dk","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
|
||||
pref("@GUAO_PREF@.altibox.no","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
|
||||
pref("@GUAO_PREF@.firefox.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@");
|
||||
|
||||
// UA-Sniffing domains below have indicated no interest in supporting Pale Moon (BOO!)
|
||||
pref("@GUAO_PREF@.humblebundle.com","Mozilla/5.0 (@OS_SLICE@ rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)");
|
||||
|
|
|
|||
|
|
@ -2558,7 +2558,7 @@ NonVoidByteStringToJsval(JSContext *cx, const nsACString &str,
|
|||
|
||||
|
||||
template<typename T> static void
|
||||
NormalizeUSVStringInternal(JSContext* aCx, T& aString)
|
||||
NormalizeUSVStringInternal(T& aString)
|
||||
{
|
||||
char16_t* start = aString.BeginWriting();
|
||||
// Must use const here because we can't pass char** to UTF16CharEnumerator as
|
||||
|
|
@ -2575,15 +2575,15 @@ NormalizeUSVStringInternal(JSContext* aCx, T& aString)
|
|||
}
|
||||
|
||||
void
|
||||
NormalizeUSVString(JSContext* aCx, nsAString& aString)
|
||||
NormalizeUSVString(nsAString& aString)
|
||||
{
|
||||
NormalizeUSVStringInternal(aCx, aString);
|
||||
NormalizeUSVStringInternal(aString);
|
||||
}
|
||||
|
||||
void
|
||||
NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString)
|
||||
NormalizeUSVString(binding_detail::FakeString& aString)
|
||||
{
|
||||
NormalizeUSVStringInternal(aCx, aString);
|
||||
NormalizeUSVStringInternal(aString);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace mozilla {
|
|||
enum UseCounter : int16_t;
|
||||
|
||||
namespace dom {
|
||||
template<typename DataType> class MozMap;
|
||||
template<typename KeyType, typename ValueType> class Record;
|
||||
|
||||
nsresult
|
||||
UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg);
|
||||
|
|
@ -2127,11 +2127,30 @@ ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v,
|
|||
return AssignJSString(cx, result, s);
|
||||
}
|
||||
|
||||
void
|
||||
NormalizeUSVString(JSContext* aCx, nsAString& aString);
|
||||
template<typename T>
|
||||
static inline bool
|
||||
ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v, T& result)
|
||||
{
|
||||
return ConvertJSValueToString(cx, v, eStringify, eStringify, result);
|
||||
}
|
||||
|
||||
void
|
||||
NormalizeUSVString(JSContext* aCx, binding_detail::FakeString& aString);
|
||||
NormalizeUSVString(nsAString& aString);
|
||||
|
||||
void
|
||||
NormalizeUSVString(binding_detail::FakeString& aString);
|
||||
|
||||
template<typename T>
|
||||
static inline bool
|
||||
ConvertJSValueToUSVString(JSContext* cx, JS::Handle<JS::Value> v, T& result)
|
||||
{
|
||||
if (!ConvertJSValueToString(cx, v, eStringify, eStringify, result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NormalizeUSVString(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
|
|
@ -2158,6 +2177,13 @@ bool
|
|||
ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
|
||||
bool nullable, nsACString& result);
|
||||
|
||||
inline bool
|
||||
ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
|
||||
nsACString& result)
|
||||
{
|
||||
return ConvertJSValueToByteString(cx, v, false, result);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq);
|
||||
template<typename T>
|
||||
|
|
@ -2293,31 +2319,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
TraceMozMapValue(T* aValue, void* aClosure)
|
||||
template<typename K, typename V>
|
||||
void TraceRecord(JSTracer* trc, Record<K, V>& record)
|
||||
{
|
||||
JSTracer* trc = static_cast<JSTracer*>(aClosure);
|
||||
// Act like it's a one-element sequence to leverage all that infrastructure.
|
||||
SequenceTracer<T>::TraceSequence(trc, aValue, aValue + 1);
|
||||
for (auto& entry : record.Entries()) {
|
||||
// Act like it's a one-element sequence to leverage all that infrastructure.
|
||||
SequenceTracer<V>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TraceMozMap(JSTracer* trc, MozMap<T>& map)
|
||||
{
|
||||
map.EnumerateValues(TraceMozMapValue<T>, trc);
|
||||
}
|
||||
|
||||
// sequence<MozMap>
|
||||
template<typename T>
|
||||
class SequenceTracer<MozMap<T>, false, false, false>
|
||||
// sequence<record>
|
||||
template<typename K, typename V>
|
||||
class SequenceTracer<Record<K, V>, false, false, false>
|
||||
{
|
||||
explicit SequenceTracer() = delete; // Should never be instantiated
|
||||
|
||||
public:
|
||||
static void TraceSequence(JSTracer* trc, MozMap<T>* seqp, MozMap<T>* end) {
|
||||
static void TraceSequence(JSTracer* trc, Record<K, V>* seqp,
|
||||
Record<K, V>* end) {
|
||||
for (; seqp != end; ++seqp) {
|
||||
seqp->EnumerateValues(TraceMozMapValue<T>, trc);
|
||||
TraceRecord(trc, *seqp);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -2395,51 +2416,51 @@ public:
|
|||
SequenceType mSequenceType;
|
||||
};
|
||||
|
||||
// Rooter class for MozMap; this is what we mostly use in the codegen.
|
||||
template<typename T>
|
||||
class MOZ_RAII MozMapRooter final : private JS::CustomAutoRooter
|
||||
// Rooter class for Record; this is what we mostly use in the codegen.
|
||||
template<typename K, typename V>
|
||||
class MOZ_RAII RecordRooter final : private JS::CustomAutoRooter
|
||||
{
|
||||
public:
|
||||
MozMapRooter(JSContext *aCx, MozMap<T>* aMozMap
|
||||
RecordRooter(JSContext *aCx, Record<K, V>* aRecord
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
|
||||
mMozMap(aMozMap),
|
||||
mMozMapType(eMozMap)
|
||||
mRecord(aRecord),
|
||||
mRecordType(eRecord)
|
||||
{
|
||||
}
|
||||
|
||||
MozMapRooter(JSContext *aCx, Nullable<MozMap<T>>* aMozMap
|
||||
RecordRooter(JSContext *aCx, Nullable<Record<K, V>>* aRecord
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
|
||||
mNullableMozMap(aMozMap),
|
||||
mMozMapType(eNullableMozMap)
|
||||
mNullableRecord(aRecord),
|
||||
mRecordType(eNullableRecord)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
enum MozMapType {
|
||||
eMozMap,
|
||||
eNullableMozMap
|
||||
enum RecordType {
|
||||
eRecord,
|
||||
eNullableRecord
|
||||
};
|
||||
|
||||
virtual void trace(JSTracer *trc) override
|
||||
{
|
||||
if (mMozMapType == eMozMap) {
|
||||
TraceMozMap(trc, *mMozMap);
|
||||
if (mRecordType == eRecord) {
|
||||
TraceRecord(trc, *mRecord);
|
||||
} else {
|
||||
MOZ_ASSERT(mMozMapType == eNullableMozMap);
|
||||
if (!mNullableMozMap->IsNull()) {
|
||||
TraceMozMap(trc, mNullableMozMap->Value());
|
||||
MOZ_ASSERT(mRecordType == eNullableRecord);
|
||||
if (!mNullableRecord->IsNull()) {
|
||||
TraceRecord(trc, mNullableRecord->Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
union {
|
||||
MozMap<T>* mMozMap;
|
||||
Nullable<MozMap<T>>* mNullableMozMap;
|
||||
Record<K, V>* mRecord;
|
||||
Nullable<Record<K, V>>* mNullableRecord;
|
||||
};
|
||||
|
||||
MozMapType mMozMapType;
|
||||
RecordType mRecordType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ def idlTypeNeedsCycleCollection(type):
|
|||
return True
|
||||
elif type.isUnion():
|
||||
return any(idlTypeNeedsCycleCollection(t) for t in type.flatMemberTypes)
|
||||
elif type.isMozMap():
|
||||
elif type.isRecord():
|
||||
if idlTypeNeedsCycleCollection(type.inner):
|
||||
raise TypeError("Cycle collection for type %s is not supported" % type)
|
||||
return False
|
||||
|
|
@ -996,6 +996,8 @@ class CGElseChain(CGThing):
|
|||
|
||||
class CGTemplatedType(CGWrapper):
|
||||
def __init__(self, templateName, child, isConst=False, isReference=False):
|
||||
if isinstance(child, list):
|
||||
child = CGList(child, ", ")
|
||||
const = "const " if isConst else ""
|
||||
pre = "%s%s<" % (const, templateName)
|
||||
ref = "&" if isReference else ""
|
||||
|
|
@ -1171,12 +1173,12 @@ class CGHeaders(CGWrapper):
|
|||
declareIncludes.add(filename)
|
||||
elif unrolled.isPrimitive():
|
||||
bindingHeaders.add("mozilla/dom/PrimitiveConversions.h")
|
||||
elif unrolled.isMozMap():
|
||||
elif unrolled.isRecord():
|
||||
if dictionary or jsImplementedDescriptors:
|
||||
declareIncludes.add("mozilla/dom/MozMap.h")
|
||||
declareIncludes.add("mozilla/dom/Record.h")
|
||||
else:
|
||||
bindingHeaders.add("mozilla/dom/MozMap.h")
|
||||
# Also add headers for the type the MozMap is
|
||||
bindingHeaders.add("mozilla/dom/Record.h")
|
||||
# Also add headers for the type the record is
|
||||
# parametrized over, if needed.
|
||||
addHeadersForType((t.inner, dictionary))
|
||||
|
||||
|
|
@ -1388,8 +1390,8 @@ def UnionTypes(unionTypes, config):
|
|||
# the right header to be able to Release() in our inlined
|
||||
# code.
|
||||
headers.add(CGHeaders.getDeclarationFilename(f.callback))
|
||||
elif f.isMozMap():
|
||||
headers.add("mozilla/dom/MozMap.h")
|
||||
elif f.isRecord():
|
||||
headers.add("mozilla/dom/Record.h")
|
||||
# And add headers for the type we're parametrized over
|
||||
addHeadersForType(f.inner)
|
||||
|
||||
|
|
@ -1448,9 +1450,9 @@ def UnionConversions(unionTypes, config):
|
|||
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||
elif f.isPrimitive():
|
||||
headers.add("mozilla/dom/PrimitiveConversions.h")
|
||||
elif f.isMozMap():
|
||||
headers.add("mozilla/dom/MozMap.h")
|
||||
# And the internal type of the MozMap
|
||||
elif f.isRecord():
|
||||
headers.add("mozilla/dom/Record.h")
|
||||
# And the internal type of the record
|
||||
addHeadersForType(f.inner)
|
||||
|
||||
# We plan to include UnionTypes.h no matter what, so it's
|
||||
|
|
@ -4290,6 +4292,9 @@ class JSToNativeConversionInfo():
|
|||
for whether we have a JS::Value. Only used when
|
||||
defaultValue is not None or when True is passed for
|
||||
checkForValue to instantiateJSToNativeConversion.
|
||||
This expression may not be already-parenthesized, so if
|
||||
you use it with && or || make sure to put parens
|
||||
around it.
|
||||
${passedToJSImpl} replaced by an expression that evaluates to a boolean
|
||||
for whether this value is being passed to a JS-
|
||||
implemented interface.
|
||||
|
|
@ -4355,7 +4360,9 @@ def handleDefaultStringValue(defaultValue, method):
|
|||
passing as the second argument of handleDefault; in particular it does not
|
||||
end with a ';'
|
||||
"""
|
||||
assert defaultValue.type.isDOMString() or defaultValue.type.isByteString()
|
||||
assert (defaultValue.type.isDOMString() or
|
||||
defaultValue.type.isUSVString() or
|
||||
defaultValue.type.isByteString())
|
||||
return ("static const %(char_t)s data[] = { %(data)s };\n"
|
||||
"%(method)s(data, ArrayLength(data) - 1)") % {
|
||||
'char_t': "char" if defaultValue.type.isByteString() else "char16_t",
|
||||
|
|
@ -4365,6 +4372,17 @@ def handleDefaultStringValue(defaultValue, method):
|
|||
}
|
||||
|
||||
|
||||
def recordKeyType(recordType):
|
||||
assert recordType.keyType.isString()
|
||||
if recordType.keyType.isByteString():
|
||||
return "nsCString"
|
||||
return "nsString"
|
||||
|
||||
|
||||
def recordKeyDeclType(recordType):
|
||||
return CGGeneric(recordKeyType(recordType))
|
||||
|
||||
|
||||
# If this function is modified, modify CGNativeMember.getArg and
|
||||
# CGNativeMember.getRetvalInfo accordingly. The latter cares about the decltype
|
||||
# and holdertype we end up using, because it needs to be able to return the code
|
||||
|
|
@ -4559,7 +4577,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
declArgs = "cx"
|
||||
else:
|
||||
assert (isMember in
|
||||
("Sequence", "Variadic", "Dictionary", "OwningUnion", "MozMap"))
|
||||
("Sequence", "Variadic", "Dictionary", "OwningUnion", "Record"))
|
||||
# We'll get traced by the sequence or dictionary or union tracer
|
||||
declType = CGGeneric("JSObject*")
|
||||
declArgs = None
|
||||
|
|
@ -4725,39 +4743,41 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
dealWithOptional=isOptional,
|
||||
holderArgs=holderArgs)
|
||||
|
||||
if type.isMozMap():
|
||||
if type.isRecord():
|
||||
assert not isEnforceRange and not isClamp
|
||||
if failureCode is None:
|
||||
notMozMap = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
|
||||
notRecord = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
|
||||
"%s" % (firstCap(sourceDescription), exceptionCode))
|
||||
else:
|
||||
notMozMap = failureCode
|
||||
notRecord = failureCode
|
||||
|
||||
nullable = type.nullable()
|
||||
# Be very careful not to change "type": we need it later
|
||||
if nullable:
|
||||
valueType = type.inner.inner
|
||||
recordType = type.inner
|
||||
else:
|
||||
valueType = type.inner
|
||||
recordType = type
|
||||
valueType = recordType.inner
|
||||
|
||||
valueInfo = getJSToNativeConversionInfo(
|
||||
valueType, descriptorProvider, isMember="MozMap",
|
||||
valueType, descriptorProvider, isMember="Record",
|
||||
exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode,
|
||||
isCallbackReturnValue=isCallbackReturnValue,
|
||||
sourceDescription="value in %s" % sourceDescription,
|
||||
nestingLevel=incrementNestingLevel())
|
||||
if valueInfo.dealWithOptional:
|
||||
raise TypeError("Shouldn't have optional things in MozMap")
|
||||
raise TypeError("Shouldn't have optional things in record")
|
||||
if valueInfo.holderType is not None:
|
||||
raise TypeError("Shouldn't need holders for MozMap")
|
||||
raise TypeError("Shouldn't need holders for record")
|
||||
|
||||
typeName = CGTemplatedType("MozMap", valueInfo.declType)
|
||||
mozMapType = typeName.define()
|
||||
declType = CGTemplatedType("Record", [recordKeyDeclType(recordType),
|
||||
valueInfo.declType])
|
||||
typeName = declType.define()
|
||||
if nullable:
|
||||
typeName = CGTemplatedType("Nullable", typeName)
|
||||
mozMapRef = "${declName}.SetValue()"
|
||||
declType = CGTemplatedType("Nullable", declType)
|
||||
recordRef = "${declName}.SetValue()"
|
||||
else:
|
||||
mozMapRef = "${declName}"
|
||||
recordRef = "${declName}"
|
||||
|
||||
valueConversion = string.Template(valueInfo.template).substitute({
|
||||
"val": "temp",
|
||||
|
|
@ -4770,68 +4790,122 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
"passedToJSImpl": "${passedToJSImpl}"
|
||||
})
|
||||
|
||||
keyType = recordKeyType(recordType)
|
||||
if recordType.keyType.isByteString():
|
||||
keyConversionFunction = "ConvertJSValueToByteString"
|
||||
hashKeyType = "nsCStringHashKey"
|
||||
else:
|
||||
hashKeyType = "nsStringHashKey"
|
||||
if recordType.keyType.isDOMString():
|
||||
keyConversionFunction = "ConvertJSValueToString"
|
||||
else:
|
||||
assert recordType.keyType.isUSVString()
|
||||
keyConversionFunction = "ConvertJSValueToUSVString"
|
||||
|
||||
templateBody = fill(
|
||||
"""
|
||||
${mozMapType} &mozMap = ${mozMapRef};
|
||||
auto& recordEntries = ${recordRef}.Entries();
|
||||
|
||||
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject());
|
||||
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
|
||||
if (!JS_Enumerate(cx, mozMapObj, &ids)) {
|
||||
JS::Rooted<JSObject*> recordObj(cx, &$${val}.toObject());
|
||||
JS::AutoIdVector ids(cx);
|
||||
if (!js::GetPropertyKeys(cx, recordObj,
|
||||
JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &ids)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
$*{exceptionCode}
|
||||
}
|
||||
JS::Rooted<JS::Value> propNameValue(cx);
|
||||
JS::Rooted<JS::Value> temp(cx);
|
||||
JS::Rooted<jsid> curId(cx);
|
||||
JS::Rooted<JS::Value> idVal(cx);
|
||||
// Use a hashset to keep track of ids seen, to avoid
|
||||
// introducing nasty O(N^2) behavior scanning for them all the
|
||||
// time. Ideally we'd use a data structure with O(1) lookup
|
||||
// _and_ ordering for the MozMap, but we don't have one lying
|
||||
// around.
|
||||
nsTHashtable<${hashKeyType}> idsSeen;
|
||||
for (size_t i = 0; i < ids.length(); ++i) {
|
||||
// Make sure we get the value before converting the name, since
|
||||
// getting the value can trigger GC but our name is a dependent
|
||||
// string.
|
||||
curId = ids[i];
|
||||
binding_detail::FakeString propName;
|
||||
bool isSymbol;
|
||||
if (!ConvertIdToString(cx, curId, propName, isSymbol) ||
|
||||
(!isSymbol && !JS_GetPropertyById(cx, mozMapObj, curId, &temp))) {
|
||||
|
||||
JS::Rooted<JS::PropertyDescriptor> desc(cx);
|
||||
if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId,
|
||||
&desc)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
if (isSymbol) {
|
||||
|
||||
if (!desc.object() /* == undefined in spec terms */ ||
|
||||
!desc.enumerable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
${valueType}* slotPtr = mozMap.AddEntry(propName);
|
||||
if (!slotPtr) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
idVal = js::IdToValue(curId);
|
||||
${keyType} propName;
|
||||
// This will just throw if idVal is a Symbol, like the spec says
|
||||
// to do.
|
||||
if (!${keyConversionFunction}(cx, idVal, propName)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
${valueType}& slot = *slotPtr;
|
||||
|
||||
if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
|
||||
${typeName}::EntryType* entry;
|
||||
if (idsSeen.Contains(propName)) {
|
||||
// Find the existing entry.
|
||||
auto idx = recordEntries.IndexOf(propName);
|
||||
MOZ_ASSERT(idx != recordEntries.NoIndex,
|
||||
"Why is it not found?");
|
||||
// Now blow it away to make it look like it was just added
|
||||
// to the array, because it's not obvious that it's
|
||||
// safe to write to its already-initialized mValue via our
|
||||
// normal codegen conversions. For example, the value
|
||||
// could be a union and this would change its type, but
|
||||
// codegen assumes we won't do that.
|
||||
entry = recordEntries.ReconstructElementAt(idx);
|
||||
} else {
|
||||
// Safe to do an infallible append here, because we did a
|
||||
// SetCapacity above to the right capacity.
|
||||
entry = recordEntries.AppendElement();
|
||||
idsSeen.PutEntry(propName);
|
||||
}
|
||||
entry->mKey = propName;
|
||||
${valueType}& slot = entry->mValue;
|
||||
$*{valueConversion}
|
||||
}
|
||||
""",
|
||||
exceptionCode=exceptionCode,
|
||||
mozMapType=mozMapType,
|
||||
mozMapRef=mozMapRef,
|
||||
recordRef=recordRef,
|
||||
hashKeyType=hashKeyType,
|
||||
keyType=keyType,
|
||||
keyConversionFunction=keyConversionFunction,
|
||||
typeName=typeName,
|
||||
valueType=valueInfo.declType.define(),
|
||||
valueConversion=valueConversion)
|
||||
|
||||
templateBody = wrapObjectTemplate(templateBody, type,
|
||||
"${declName}.SetNull();\n",
|
||||
notMozMap)
|
||||
notRecord)
|
||||
|
||||
declType = typeName
|
||||
declArgs = None
|
||||
holderType = None
|
||||
holderArgs = None
|
||||
# MozMap arguments that might contain traceable things need
|
||||
# record arguments that might contain traceable things need
|
||||
# to get traced
|
||||
if not isMember and isCallbackReturnValue:
|
||||
# Go ahead and just convert directly into our actual return value
|
||||
declType = CGWrapper(declType, post="&")
|
||||
declArgs = "aRetVal"
|
||||
elif not isMember and typeNeedsRooting(valueType):
|
||||
holderType = CGTemplatedType("MozMapRooter", valueInfo.declType)
|
||||
# If our MozMap is nullable, this will set the Nullable to be
|
||||
holderType = CGTemplatedType("RecordRooter",
|
||||
[recordKeyDeclType(recordType),
|
||||
valueInfo.declType])
|
||||
# If our record is nullable, this will set the Nullable to be
|
||||
# not-null, but that's ok because we make an explicit SetNull() call
|
||||
# on it as needed if our JS value is actually null.
|
||||
holderArgs = "cx, &%s" % mozMapRef
|
||||
holderArgs = "cx, &%s" % recordRef
|
||||
|
||||
return JSToNativeConversionInfo(templateBody, declType=declType,
|
||||
declArgs=declArgs,
|
||||
|
|
@ -4914,16 +4988,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
else:
|
||||
setDictionary = None
|
||||
|
||||
mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes)
|
||||
if len(mozMapMemberTypes) > 0:
|
||||
assert len(mozMapMemberTypes) == 1
|
||||
name = getUnionMemberName(mozMapMemberTypes[0])
|
||||
mozMapObject = CGGeneric(
|
||||
recordMemberTypes = filter(lambda t: t.isRecord(), memberTypes)
|
||||
if len(recordMemberTypes) > 0:
|
||||
assert len(recordMemberTypes) == 1
|
||||
name = getUnionMemberName(recordMemberTypes[0])
|
||||
recordObject = CGGeneric(
|
||||
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
|
||||
(unionArgumentObj, name))
|
||||
names.append(name)
|
||||
else:
|
||||
mozMapObject = None
|
||||
recordObject = None
|
||||
|
||||
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
|
||||
if len(objectMemberTypes) > 0:
|
||||
|
|
@ -4939,10 +5013,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
else:
|
||||
object = None
|
||||
|
||||
hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or mozMapObject
|
||||
hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or recordObject
|
||||
if hasObjectTypes:
|
||||
# "object" is not distinguishable from other types
|
||||
assert not object or not (interfaceObject or sequenceObject or dateObject or callbackObject or mozMapObject)
|
||||
assert not object or not (interfaceObject or sequenceObject or dateObject or callbackObject or recordObject)
|
||||
if sequenceObject or dateObject or callbackObject:
|
||||
# An object can be both an sequence object and a callback or
|
||||
# dictionary, but we shouldn't have both in the union's members
|
||||
|
|
@ -4962,9 +5036,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if dateObject:
|
||||
templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());\n"))
|
||||
|
||||
if mozMapObject:
|
||||
if recordObject:
|
||||
templateBody = CGList([templateBody,
|
||||
CGIfWrapper(mozMapObject, "!done")])
|
||||
CGIfWrapper(recordObject, "!done")])
|
||||
|
||||
templateBody = CGIfWrapper(templateBody, "${val}.isObject()")
|
||||
else:
|
||||
|
|
@ -5144,7 +5218,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if isinstance(defaultValue, IDLNullValue):
|
||||
extraConditionForNull = "!(${haveValue}) || "
|
||||
else:
|
||||
extraConditionForNull = "${haveValue} && "
|
||||
extraConditionForNull = "(${haveValue}) && "
|
||||
else:
|
||||
extraConditionForNull = ""
|
||||
templateBody = handleNull(templateBody, declLoc,
|
||||
|
|
@ -5525,7 +5599,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
def getConversionCode(varName):
|
||||
normalizeCode = ""
|
||||
if type.isUSVString():
|
||||
normalizeCode = "NormalizeUSVString(cx, %s);\n" % varName
|
||||
normalizeCode = "NormalizeUSVString(%s);\n" % varName
|
||||
|
||||
conversionCode = fill("""
|
||||
if (!ConvertJSValueToString(cx, $${val}, ${nullBehavior}, ${undefinedBehavior}, ${varName})) {
|
||||
|
|
@ -5688,7 +5762,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
haveCallable = "${val}.isObject() && " + haveCallable
|
||||
if defaultValue is not None:
|
||||
assert(isinstance(defaultValue, IDLNullValue))
|
||||
haveCallable = "${haveValue} && " + haveCallable
|
||||
haveCallable = "(${haveValue}) && " + haveCallable
|
||||
template = (
|
||||
("if (%s) {\n" % haveCallable) +
|
||||
conversion +
|
||||
|
|
@ -5700,7 +5774,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
haveObject = "${val}.isObject()"
|
||||
if defaultValue is not None:
|
||||
assert(isinstance(defaultValue, IDLNullValue))
|
||||
haveObject = "${haveValue} && " + haveObject
|
||||
haveObject = "(${haveValue}) && " + haveObject
|
||||
template = CGIfElseWrapper(haveObject,
|
||||
CGGeneric(conversion),
|
||||
CGGeneric("${declName} = nullptr;\n")).define()
|
||||
|
|
@ -5724,7 +5798,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
assert not isEnforceRange and not isClamp
|
||||
|
||||
declArgs = None
|
||||
if isMember in ("Variadic", "Sequence", "Dictionary", "MozMap"):
|
||||
if isMember in ("Variadic", "Sequence", "Dictionary", "Record"):
|
||||
# Rooting is handled by the sequence and dictionary tracers.
|
||||
declType = "JS::Value"
|
||||
else:
|
||||
|
|
@ -5768,8 +5842,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
return handleJSObjectType(type, isMember, failureCode, exceptionCode, sourceDescription)
|
||||
|
||||
if type.isDictionary():
|
||||
# There are no nullable dictionaries
|
||||
assert not type.nullable() or isCallbackReturnValue
|
||||
# There are no nullable dictionary arguments or dictionary members
|
||||
assert(not type.nullable() or isCallbackReturnValue or
|
||||
(isMember and isMember != "Dictionary"))
|
||||
# All optional dictionaries always have default values, so we
|
||||
# should be able to assume not isOptional here.
|
||||
assert not isOptional
|
||||
|
|
@ -6256,7 +6331,7 @@ def getMaybeWrapValueFuncForType(type):
|
|||
|
||||
|
||||
sequenceWrapLevel = 0
|
||||
mozMapWrapLevel = 0
|
||||
recordWrapLevel = 0
|
||||
|
||||
|
||||
def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||
|
|
@ -6361,7 +6436,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
if type is None or type.isVoid():
|
||||
return (setUndefined(), True)
|
||||
|
||||
if (type.isSequence() or type.isMozMap()) and type.nullable():
|
||||
if (type.isSequence() or type.isRecord()) and type.nullable():
|
||||
# These are both wrapped in Nullable<>
|
||||
recTemplate, recInfall = getWrapTemplateForType(type.inner, descriptorProvider,
|
||||
"%s.Value()" % result, successCode,
|
||||
|
|
@ -6434,14 +6509,14 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
|
||||
return (code, False)
|
||||
|
||||
if type.isMozMap():
|
||||
# Now do non-nullable MozMap. Our success code is just to break to
|
||||
if type.isRecord():
|
||||
# Now do non-nullable record. Our success code is just to break to
|
||||
# where we define the property on the object. Note that we bump the
|
||||
# mozMapWrapLevel around this call so that nested MozMap conversions
|
||||
# recordWrapLevel around this call so that nested record conversions
|
||||
# will use different temp value names.
|
||||
global mozMapWrapLevel
|
||||
valueName = "mozMapValue%d" % mozMapWrapLevel
|
||||
mozMapWrapLevel += 1
|
||||
global recordWrapLevel
|
||||
valueName = "recordValue%d" % recordWrapLevel
|
||||
recordWrapLevel += 1
|
||||
innerTemplate = wrapForType(
|
||||
type.inner, descriptorProvider,
|
||||
{
|
||||
|
|
@ -6454,12 +6529,22 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
'obj': "returnObj",
|
||||
'typedArraysAreStructs': typedArraysAreStructs
|
||||
})
|
||||
mozMapWrapLevel -= 1
|
||||
recordWrapLevel -= 1
|
||||
if type.keyType.isByteString():
|
||||
# There is no length-taking JS_DefineProperty. So to keep
|
||||
# things sane with embedded nulls, we want to byte-inflate
|
||||
# to an nsAString. The only byte-inflation function we
|
||||
# have around is AppendASCIItoUTF16, which luckily doesn't
|
||||
# assert anything about the input being ASCII.
|
||||
expandedKeyDecl = "NS_ConvertASCIItoUTF16 expandedKey(entry.mKey);\n"
|
||||
keyName = "expandedKey"
|
||||
else:
|
||||
expandedKeyDecl = ""
|
||||
keyName = "entry.mKey"
|
||||
|
||||
code = fill(
|
||||
"""
|
||||
|
||||
nsTArray<nsString> keys;
|
||||
${result}.GetKeys(keys);
|
||||
JS::Rooted<JSObject*> returnObj(cx, JS_NewPlainObject(cx));
|
||||
if (!returnObj) {
|
||||
$*{exceptionCode}
|
||||
|
|
@ -6467,15 +6552,17 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
// Scope for 'tmp'
|
||||
{
|
||||
JS::Rooted<JS::Value> tmp(cx);
|
||||
for (size_t idx = 0; idx < keys.Length(); ++idx) {
|
||||
auto& ${valueName} = ${result}.Get(keys[idx]);
|
||||
for (auto& entry : ${result}.Entries()) {
|
||||
auto& ${valueName} = entry.mValue;
|
||||
// Control block to let us common up the JS_DefineUCProperty calls when there
|
||||
// are different ways to succeed at wrapping the value.
|
||||
do {
|
||||
$*{innerTemplate}
|
||||
} while (0);
|
||||
if (!JS_DefineUCProperty(cx, returnObj, keys[idx].get(),
|
||||
keys[idx].Length(), tmp,
|
||||
$*{expandedKeyDecl}
|
||||
if (!JS_DefineUCProperty(cx, returnObj,
|
||||
${keyName}.BeginReading(),
|
||||
${keyName}.Length(), tmp,
|
||||
JSPROP_ENUMERATE)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
|
|
@ -6487,6 +6574,8 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
exceptionCode=exceptionCode,
|
||||
valueName=valueName,
|
||||
innerTemplate=innerTemplate,
|
||||
expandedKeyDecl=expandedKeyDecl,
|
||||
keyName=keyName,
|
||||
set=setObject("*returnObj"))
|
||||
|
||||
return (code, False)
|
||||
|
|
@ -6770,7 +6859,7 @@ def typeMatchesLambda(type, func):
|
|||
return False
|
||||
if type.nullable():
|
||||
return typeMatchesLambda(type.inner, func)
|
||||
if type.isSequence() or type.isMozMap():
|
||||
if type.isSequence() or type.isRecord():
|
||||
return typeMatchesLambda(type.inner, func)
|
||||
if type.isUnion():
|
||||
return any(typeMatchesLambda(t, func) for t in
|
||||
|
|
@ -6866,20 +6955,21 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
|||
if nullable:
|
||||
result = CGTemplatedType("Nullable", result)
|
||||
return result, "ref", rooter, None, None
|
||||
if returnType.isMozMap():
|
||||
if returnType.isRecord():
|
||||
nullable = returnType.nullable()
|
||||
if nullable:
|
||||
returnType = returnType.inner
|
||||
result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner,
|
||||
descriptorProvider,
|
||||
isMember="MozMap")
|
||||
isMember="Record")
|
||||
# While we have our inner type, set up our rooter, if needed
|
||||
if not isMember and typeNeedsRooting(returnType):
|
||||
rooter = CGGeneric("MozMapRooter<%s> resultRooter(cx, &result);\n" %
|
||||
result.define())
|
||||
rooter = CGGeneric("RecordRooter<%s> resultRooter(cx, &result);\n" %
|
||||
("nsString, " + result.define()))
|
||||
else:
|
||||
rooter = None
|
||||
result = CGTemplatedType("MozMap", result)
|
||||
result = CGTemplatedType("Record", [recordKeyDeclType(returnType),
|
||||
result])
|
||||
if nullable:
|
||||
result = CGTemplatedType("Nullable", result)
|
||||
return result, "ref", rooter, None, None
|
||||
|
|
@ -6976,7 +7066,7 @@ class CGCallGenerator(CGThing):
|
|||
return True
|
||||
if a.type.isSequence():
|
||||
return True
|
||||
if a.type.isMozMap():
|
||||
if a.type.isRecord():
|
||||
return True
|
||||
# isObject() types are always a JS::Rooted, whether
|
||||
# nullable or not, and it turns out a const JS::Rooted
|
||||
|
|
@ -7138,7 +7228,7 @@ class MethodNotNewObjectError(Exception):
|
|||
# nested sequences we don't use the same variable name to iterate over
|
||||
# different sequences.
|
||||
sequenceWrapLevel = 0
|
||||
mapWrapLevel = 0
|
||||
recordWrapLevel = 0
|
||||
|
||||
|
||||
def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
|
||||
|
|
@ -7199,29 +7289,27 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
|
|||
wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % origValue)
|
||||
return wrapCode
|
||||
|
||||
if type.isMozMap():
|
||||
origValue = value
|
||||
if type.isRecord():
|
||||
origType = type
|
||||
if type.nullable():
|
||||
type = type.inner
|
||||
value = "%s.Value()" % value
|
||||
global mapWrapLevel
|
||||
key = "mapName%d" % mapWrapLevel
|
||||
mapWrapLevel += 1
|
||||
recordRef = "%s.Value()" % value
|
||||
else:
|
||||
recordRef = value
|
||||
global recordWrapLevel
|
||||
entryRef = "mapEntry%d" % recordWrapLevel
|
||||
recordWrapLevel += 1
|
||||
wrapElement = wrapTypeIntoCurrentCompartment(type.inner,
|
||||
"%s.Get(%sKeys[%sIndex])" % (value, key, key))
|
||||
mapWrapLevel -= 1
|
||||
"%s.mValue" % entryRef)
|
||||
recordWrapLevel -= 1
|
||||
if not wrapElement:
|
||||
return None
|
||||
wrapCode = CGWrapper(CGIndenter(wrapElement),
|
||||
pre=("""
|
||||
nsTArray<nsString> %sKeys;
|
||||
%s.GetKeys(%sKeys);
|
||||
for (uint32_t %sIndex = 0; %sIndex < %sKeys.Length(); ++%sIndex) {
|
||||
""" % (key, value, key, key, key, key, key)),
|
||||
pre=("for (auto& %s : %s.Entries()) {\n" %
|
||||
(entryRef, recordRef)),
|
||||
post="}\n")
|
||||
if origType.nullable():
|
||||
wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % origValue)
|
||||
wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % value)
|
||||
return wrapCode
|
||||
|
||||
if type.isDictionary():
|
||||
|
|
@ -8110,11 +8198,11 @@ class CGMethodCall(CGThing):
|
|||
if distinguishingType(s).isSequence())
|
||||
|
||||
# Now append all the overloads that take a dictionary or callback
|
||||
# interface or MozMap. There should be only one of these!
|
||||
# interface or record. There should be only one of these!
|
||||
genericObjectSigs = [
|
||||
s for s in possibleSignatures
|
||||
if (distinguishingType(s).isDictionary() or
|
||||
distinguishingType(s).isMozMap() or
|
||||
distinguishingType(s).isRecord() or
|
||||
distinguishingType(s).isCallbackInterface())]
|
||||
assert len(genericObjectSigs) <= 1
|
||||
objectSigs.extend(genericObjectSigs)
|
||||
|
|
@ -9408,7 +9496,7 @@ class CGMemberJITInfo(CGThing):
|
|||
return "JSVAL_TYPE_UNDEFINED"
|
||||
if t.isSequence():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isMozMap():
|
||||
if t.isRecord():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isGeckoInterface():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
|
|
@ -9669,17 +9757,22 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
|
|||
# Flat member types have already unwrapped nullables.
|
||||
assert not type.nullable()
|
||||
|
||||
if type.isSequence() or type.isMozMap():
|
||||
if type.isSequence() or type.isRecord():
|
||||
if type.isSequence():
|
||||
wrapperType = "Sequence"
|
||||
else:
|
||||
wrapperType = "MozMap"
|
||||
wrapperType = "Record"
|
||||
# We don't use the returned template here, so it's OK to just pass no
|
||||
# sourceDescription.
|
||||
elementInfo = getJSToNativeConversionInfo(type.inner,
|
||||
descriptorProvider,
|
||||
isMember=wrapperType)
|
||||
return CGTemplatedType(wrapperType, elementInfo.declType,
|
||||
if wrapperType == "Sequence":
|
||||
innerType = elementInfo.declType
|
||||
else:
|
||||
innerType = [recordKeyDeclType(type), elementInfo.declType]
|
||||
|
||||
return CGTemplatedType(wrapperType, innerType,
|
||||
isConst=True, isReference=True)
|
||||
|
||||
# Nested unions are unwrapped automatically into our flatMemberTypes.
|
||||
|
|
@ -10040,10 +10133,10 @@ class CGUnionStruct(CGThing):
|
|||
CGCase("e" + vars["name"],
|
||||
CGGeneric("DoTraceSequence(trc, mValue.m%s.Value());\n" %
|
||||
vars["name"])))
|
||||
elif t.isMozMap():
|
||||
elif t.isRecord():
|
||||
traceCases.append(
|
||||
CGCase("e" + vars["name"],
|
||||
CGGeneric("TraceMozMap(trc, mValue.m%s.Value());\n" %
|
||||
CGGeneric("TraceRecord(trc, mValue.m%s.Value());\n" %
|
||||
vars["name"])))
|
||||
else:
|
||||
assert t.isSpiderMonkeyInterface()
|
||||
|
|
@ -13172,8 +13265,8 @@ class CGDictionary(CGThing):
|
|||
trace = CGGeneric('%s.TraceSelf(trc);\n' % memberData)
|
||||
if type.nullable():
|
||||
trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable)
|
||||
elif type.isMozMap():
|
||||
# If you implement this, add a MozMap<object> to
|
||||
elif type.isRecord():
|
||||
# If you implement this, add a record<DOMString, object> to
|
||||
# TestInterfaceJSDictionary and test it in test_bug1036214.html
|
||||
# to make sure we end up with the correct security properties.
|
||||
assert False
|
||||
|
|
@ -13583,7 +13676,7 @@ class ForwardDeclarationBuilder:
|
|||
# since we don't know which one we might want
|
||||
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, False))
|
||||
self.addInMozillaDom(CGUnionStruct.unionTypeName(t, True))
|
||||
elif t.isMozMap():
|
||||
elif t.isRecord():
|
||||
self.forwardDeclareForType(t.inner, config)
|
||||
# Don't need to do anything for void, primitive, string, any or object.
|
||||
# There may be some other cases we are missing.
|
||||
|
|
@ -14089,9 +14182,9 @@ class CGNativeMember(ClassMethod):
|
|||
else:
|
||||
returnCode = "aRetVal.SwapElements(${declName});\n"
|
||||
return "void", "", returnCode
|
||||
if type.isMozMap():
|
||||
# If we want to handle MozMap-of-MozMap return values, we're
|
||||
# going to need to fix example codegen to not produce MozMap<void>
|
||||
if type.isRecord():
|
||||
# If we want to handle record-of-record return values, we're
|
||||
# going to need to fix example codegen to not produce record<void>
|
||||
# for the relevant argument...
|
||||
assert not isMember
|
||||
# In this case we convert directly into our outparam to start with
|
||||
|
|
@ -14139,13 +14232,14 @@ class CGNativeMember(ClassMethod):
|
|||
if nullable:
|
||||
type = CGTemplatedType("Nullable", type)
|
||||
args.append(Argument("%s&" % type.define(), "aRetVal"))
|
||||
elif returnType.isMozMap():
|
||||
elif returnType.isRecord():
|
||||
nullable = returnType.nullable()
|
||||
if nullable:
|
||||
returnType = returnType.inner
|
||||
# And now the actual underlying type
|
||||
elementDecl = self.getReturnType(returnType.inner, True)
|
||||
type = CGTemplatedType("MozMap", CGGeneric(elementDecl))
|
||||
type = CGTemplatedType("Record", [recordKeyDeclType(returnType),
|
||||
CGGeneric(elementDecl)])
|
||||
if nullable:
|
||||
type = CGTemplatedType("Nullable", type)
|
||||
args.append(Argument("%s&" % type.define(), "aRetVal"))
|
||||
|
|
@ -14206,7 +14300,7 @@ class CGNativeMember(ClassMethod):
|
|||
Nullable as needed.
|
||||
|
||||
isMember can be false or one of the strings "Sequence", "Variadic",
|
||||
"MozMap"
|
||||
"Record"
|
||||
"""
|
||||
if type.isSequence():
|
||||
nullable = type.nullable()
|
||||
|
|
@ -14217,13 +14311,13 @@ class CGNativeMember(ClassMethod):
|
|||
decl = CGTemplatedType("Sequence", argType)
|
||||
return decl.define(), True, True
|
||||
|
||||
if type.isMozMap():
|
||||
if type.isRecord():
|
||||
nullable = type.nullable()
|
||||
if nullable:
|
||||
type = type.inner
|
||||
elementType = type.inner
|
||||
argType = self.getArgType(elementType, False, "MozMap")[0]
|
||||
decl = CGTemplatedType("MozMap", argType)
|
||||
argType = self.getArgType(elementType, False, "Record")[0]
|
||||
decl = CGTemplatedType("Record", [recordKeyDeclType(type), argType])
|
||||
return decl.define(), True, True
|
||||
|
||||
if type.isUnion():
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class Configuration(DescriptorProvider):
|
|||
|
||||
for (t, _) in getAllTypes(self.descriptors, self.dictionaries, self.callbacks):
|
||||
while True:
|
||||
if t.isMozMap():
|
||||
if t.isRecord():
|
||||
t = t.inner
|
||||
elif t.unroll() != t:
|
||||
t = t.unroll()
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Class for representing MozMap arguments. This is an nsTHashtable
|
||||
* under the hood, but we don't want to leak that implementation
|
||||
* detail.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_MozMap_h
|
||||
#define mozilla_dom_MozMap_h
|
||||
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace binding_detail {
|
||||
template<typename DataType>
|
||||
class MozMapEntry : public nsStringHashKey
|
||||
{
|
||||
public:
|
||||
explicit MozMapEntry(const nsAString* aKeyTypePointer)
|
||||
: nsStringHashKey(aKeyTypePointer)
|
||||
{
|
||||
}
|
||||
|
||||
// Move constructor so we can do MozMaps of MozMaps.
|
||||
MozMapEntry(MozMapEntry<DataType>&& aOther)
|
||||
: nsStringHashKey(aOther),
|
||||
mData(Move(aOther.mData))
|
||||
{
|
||||
}
|
||||
|
||||
DataType mData;
|
||||
};
|
||||
|
||||
} // namespace binding_detail
|
||||
|
||||
template<typename DataType>
|
||||
class MozMap : protected nsTHashtable<binding_detail::MozMapEntry<DataType>>
|
||||
{
|
||||
public:
|
||||
typedef typename binding_detail::MozMapEntry<DataType> EntryType;
|
||||
typedef nsTHashtable<EntryType> Base;
|
||||
typedef MozMap<DataType> SelfType;
|
||||
|
||||
MozMap()
|
||||
{
|
||||
}
|
||||
|
||||
// Move constructor so we can do MozMap of MozMap.
|
||||
MozMap(SelfType&& aOther) :
|
||||
Base(Move(aOther))
|
||||
{
|
||||
}
|
||||
|
||||
// The return value is only safe to use until an AddEntry call.
|
||||
const DataType& Get(const nsAString& aKey) const
|
||||
{
|
||||
const EntryType* ent = this->GetEntry(aKey);
|
||||
MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?");
|
||||
return ent->mData;
|
||||
}
|
||||
|
||||
DataType& Get(const nsAString& aKey)
|
||||
{
|
||||
EntryType* ent = this->GetEntry(aKey);
|
||||
MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?");
|
||||
return ent->mData;
|
||||
}
|
||||
|
||||
// The return value is only safe to use until an AddEntry call.
|
||||
const DataType* GetIfExists(const nsAString& aKey) const
|
||||
{
|
||||
const EntryType* ent = this->GetEntry(aKey);
|
||||
if (!ent) {
|
||||
return nullptr;
|
||||
}
|
||||
return &ent->mData;
|
||||
}
|
||||
|
||||
void GetKeys(nsTArray<nsString>& aKeys) const {
|
||||
for (auto iter = this->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
aKeys.AppendElement(iter.Get()->GetKey());
|
||||
}
|
||||
}
|
||||
|
||||
// XXXbz we expose this generic enumerator for tracing. Otherwise we'd end up
|
||||
// with a dependency on BindingUtils.h here for the SequenceTracer bits.
|
||||
typedef void (* Enumerator)(DataType* aValue, void* aClosure);
|
||||
void EnumerateValues(Enumerator aEnumerator, void *aClosure)
|
||||
{
|
||||
for (auto iter = this->Iter(); !iter.Done(); iter.Next()) {
|
||||
aEnumerator(&iter.Get()->mData, aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
DataType* AddEntry(const nsAString& aKey)
|
||||
{
|
||||
EntryType* ent = this->PutEntry(aKey, fallible);
|
||||
if (!ent) {
|
||||
return nullptr;
|
||||
}
|
||||
return &ent->mData;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_MozMap_h
|
||||
91
dom/bindings/Record.h
Normal file
91
dom/bindings/Record.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Class for representing record arguments. Basically an array under the hood.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_Record_h
|
||||
#define mozilla_dom_Record_h
|
||||
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace binding_detail {
|
||||
template<typename KeyType, typename ValueType>
|
||||
class RecordEntry
|
||||
{
|
||||
public:
|
||||
RecordEntry()
|
||||
{
|
||||
}
|
||||
|
||||
// Move constructor so we can do Records of Records.
|
||||
RecordEntry(RecordEntry<KeyType, ValueType>&& aOther)
|
||||
: mKey(Move(aOther.mKey)),
|
||||
mValue(Move(aOther.mValue))
|
||||
{
|
||||
}
|
||||
|
||||
KeyType mKey;
|
||||
ValueType mValue;
|
||||
};
|
||||
|
||||
} // namespace binding_detail
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
class Record
|
||||
{
|
||||
public:
|
||||
typedef typename binding_detail::RecordEntry<KeyType, ValueType> EntryType;
|
||||
typedef Record<KeyType, ValueType> SelfType;
|
||||
|
||||
Record()
|
||||
{
|
||||
}
|
||||
|
||||
// Move constructor so we can do Record of Record.
|
||||
Record(SelfType&& aOther) :
|
||||
mEntries(Move(aOther.mEntries))
|
||||
{
|
||||
}
|
||||
|
||||
const nsTArray<EntryType>& Entries() const
|
||||
{
|
||||
return mEntries;
|
||||
}
|
||||
|
||||
nsTArray<EntryType>& Entries()
|
||||
{
|
||||
return mEntries;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray<EntryType> mEntries;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
template<typename K, typename V>
|
||||
class nsDefaultComparator<mozilla::dom::binding_detail::RecordEntry<K, V>, K>
|
||||
{
|
||||
public:
|
||||
bool Equals(const mozilla::dom::binding_detail::RecordEntry<K, V>& aEntry,
|
||||
const K& aKey) const
|
||||
{
|
||||
return aEntry.mKey == aKey;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // mozilla_dom_Record_h
|
||||
|
|
@ -32,10 +32,10 @@ EXPORTS.mozilla.dom += [
|
|||
'FakeString.h',
|
||||
'IterableIterator.h',
|
||||
'JSSlots.h',
|
||||
'MozMap.h',
|
||||
'NonRefcountedDOMObject.h',
|
||||
'Nullable.h',
|
||||
'PrimitiveConversions.h',
|
||||
'Record.h',
|
||||
'RootedDictionary.h',
|
||||
'SimpleGlobalObject.h',
|
||||
'StructuredClone.h',
|
||||
|
|
|
|||
|
|
@ -1867,7 +1867,7 @@ class IDLDictionary(IDLObjectWithScope):
|
|||
|
||||
if (memberType.nullable() or
|
||||
memberType.isSequence() or
|
||||
memberType.isMozMap()):
|
||||
memberType.isRecord()):
|
||||
return typeContainsDictionary(memberType.inner, dictionary)
|
||||
|
||||
if memberType.isDictionary():
|
||||
|
|
@ -1988,7 +1988,7 @@ class IDLType(IDLObject):
|
|||
'callback',
|
||||
'union',
|
||||
'sequence',
|
||||
'mozmap'
|
||||
'record'
|
||||
)
|
||||
|
||||
def __init__(self, location, name):
|
||||
|
|
@ -2038,7 +2038,7 @@ class IDLType(IDLObject):
|
|||
def isSequence(self):
|
||||
return False
|
||||
|
||||
def isMozMap(self):
|
||||
def isRecord(self):
|
||||
return False
|
||||
|
||||
def isArrayBuffer(self):
|
||||
|
|
@ -2263,8 +2263,8 @@ class IDLNullableType(IDLParameterizedType):
|
|||
def isSequence(self):
|
||||
return self.inner.isSequence()
|
||||
|
||||
def isMozMap(self):
|
||||
return self.inner.isMozMap()
|
||||
def isRecord(self):
|
||||
return self.inner.isRecord()
|
||||
|
||||
def isArrayBuffer(self):
|
||||
return self.inner.isArrayBuffer()
|
||||
|
|
@ -2321,8 +2321,10 @@ class IDLNullableType(IDLParameterizedType):
|
|||
return self
|
||||
|
||||
def isDistinguishableFrom(self, other):
|
||||
if (other.nullable() or (other.isUnion() and other.hasNullableType) or
|
||||
other.isDictionary()):
|
||||
if (other.nullable() or
|
||||
other.isDictionary() or
|
||||
(other.isUnion() and
|
||||
(other.hasNullableType or other.hasDictionaryType()))):
|
||||
# Can't tell which type null should become
|
||||
return False
|
||||
return self.inner.isDistinguishableFrom(other)
|
||||
|
|
@ -2397,34 +2399,38 @@ class IDLSequenceType(IDLParameterizedType):
|
|||
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||
other.isDate() or other.isInterface() or
|
||||
other.isDictionary() or
|
||||
other.isCallback() or other.isMozMap())
|
||||
other.isCallback() or other.isRecord())
|
||||
|
||||
|
||||
class IDLMozMapType(IDLParameterizedType):
|
||||
def __init__(self, location, parameterType):
|
||||
assert not parameterType.isVoid()
|
||||
class IDLRecordType(IDLParameterizedType):
|
||||
def __init__(self, location, keyType, valueType):
|
||||
assert keyType.isString()
|
||||
assert keyType.isComplete()
|
||||
assert not valueType.isVoid()
|
||||
|
||||
IDLParameterizedType.__init__(self, location, valueType.name, valueType)
|
||||
self.keyType = keyType
|
||||
|
||||
IDLParameterizedType.__init__(self, location, parameterType.name, parameterType)
|
||||
# Need to set self.name up front if our inner type is already complete,
|
||||
# since in that case our .complete() won't be called.
|
||||
if self.inner.isComplete():
|
||||
self.name = self.inner.name + "MozMap"
|
||||
self.name = self.keyType.name + self.inner.name + "Record"
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, IDLMozMapType) and self.inner == other.inner
|
||||
return isinstance(other, IDLRecordType) and self.inner == other.inner
|
||||
|
||||
def __str__(self):
|
||||
return self.inner.__str__() + "MozMap"
|
||||
return self.keyType.__str__() + self.inner.__str__() + "Record"
|
||||
|
||||
def isMozMap(self):
|
||||
def isRecord(self):
|
||||
return True
|
||||
|
||||
def tag(self):
|
||||
return IDLType.Tags.mozmap
|
||||
return IDLType.Tags.record
|
||||
|
||||
def complete(self, scope):
|
||||
self.inner = self.inner.complete(scope)
|
||||
self.name = self.inner.name + "MozMap"
|
||||
self.name = self.keyType.name + self.inner.name + "Record"
|
||||
return self
|
||||
|
||||
def unroll(self):
|
||||
|
|
@ -2614,8 +2620,8 @@ class IDLTypedefType(IDLType):
|
|||
def isSequence(self):
|
||||
return self.inner.isSequence()
|
||||
|
||||
def isMozMap(self):
|
||||
return self.inner.isMozMap()
|
||||
def isRecord(self):
|
||||
return self.inner.isRecord()
|
||||
|
||||
def isDictionary(self):
|
||||
return self.inner.isDictionary()
|
||||
|
|
@ -2798,7 +2804,7 @@ class IDLWrapperType(IDLType):
|
|||
if self.isEnum():
|
||||
return (other.isPrimitive() or other.isInterface() or other.isObject() or
|
||||
other.isCallback() or other.isDictionary() or
|
||||
other.isSequence() or other.isMozMap() or other.isDate())
|
||||
other.isSequence() or other.isRecord() or other.isDate())
|
||||
if self.isDictionary() and other.nullable():
|
||||
return False
|
||||
if (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||
|
|
@ -2820,7 +2826,7 @@ class IDLWrapperType(IDLType):
|
|||
(self.isNonCallbackInterface() or
|
||||
other.isNonCallbackInterface()))
|
||||
if (other.isDictionary() or other.isCallback() or
|
||||
other.isMozMap()):
|
||||
other.isRecord()):
|
||||
return self.isNonCallbackInterface()
|
||||
|
||||
# Not much else |other| can be
|
||||
|
|
@ -3030,17 +3036,17 @@ class IDLBuiltinType(IDLType):
|
|||
return (other.isNumeric() or other.isString() or other.isEnum() or
|
||||
other.isInterface() or other.isObject() or
|
||||
other.isCallback() or other.isDictionary() or
|
||||
other.isSequence() or other.isMozMap() or other.isDate())
|
||||
other.isSequence() or other.isRecord() or other.isDate())
|
||||
if self.isNumeric():
|
||||
return (other.isBoolean() or other.isString() or other.isEnum() or
|
||||
other.isInterface() or other.isObject() or
|
||||
other.isCallback() or other.isDictionary() or
|
||||
other.isSequence() or other.isMozMap() or other.isDate())
|
||||
other.isSequence() or other.isRecord() or other.isDate())
|
||||
if self.isString():
|
||||
return (other.isPrimitive() or other.isInterface() or
|
||||
other.isObject() or
|
||||
other.isCallback() or other.isDictionary() or
|
||||
other.isSequence() or other.isMozMap() or other.isDate())
|
||||
other.isSequence() or other.isRecord() or other.isDate())
|
||||
if self.isAny():
|
||||
# Can't tell "any" apart from anything
|
||||
return False
|
||||
|
|
@ -3050,7 +3056,7 @@ class IDLBuiltinType(IDLType):
|
|||
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||
other.isInterface() or other.isCallback() or
|
||||
other.isDictionary() or other.isSequence() or
|
||||
other.isMozMap())
|
||||
other.isRecord())
|
||||
if self.isVoid():
|
||||
return not other.isVoid()
|
||||
# Not much else we could be!
|
||||
|
|
@ -3058,7 +3064,7 @@ class IDLBuiltinType(IDLType):
|
|||
# Like interfaces, but we know we're not a callback
|
||||
return (other.isPrimitive() or other.isString() or other.isEnum() or
|
||||
other.isCallback() or other.isDictionary() or
|
||||
other.isSequence() or other.isMozMap() or other.isDate() or
|
||||
other.isSequence() or other.isRecord() or other.isDate() or
|
||||
(other.isInterface() and (
|
||||
# ArrayBuffer is distinguishable from everything
|
||||
# that's not an ArrayBuffer or a callback interface
|
||||
|
|
@ -3843,6 +3849,9 @@ class IDLConst(IDLInterfaceMember):
|
|||
if type.isDictionary():
|
||||
raise WebIDLError("A constant cannot be of a dictionary type",
|
||||
[self.location])
|
||||
if type.isRecord():
|
||||
raise WebIDLError("A constant cannot be of a record type",
|
||||
[self.location])
|
||||
self.type = type
|
||||
self.value = value
|
||||
|
||||
|
|
@ -3954,8 +3963,8 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
|
||||
raise WebIDLError("A non-cached attribute cannot be of a sequence "
|
||||
"type", [self.location])
|
||||
if self.type.isMozMap() and not self.getExtendedAttribute("Cached"):
|
||||
raise WebIDLError("A non-cached attribute cannot be of a MozMap "
|
||||
if self.type.isRecord() and not self.getExtendedAttribute("Cached"):
|
||||
raise WebIDLError("A non-cached attribute cannot be of a record "
|
||||
"type", [self.location])
|
||||
if self.type.isUnion():
|
||||
for f in self.type.unroll().flatMemberTypes:
|
||||
|
|
@ -3971,11 +3980,11 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
"one of its member types's member "
|
||||
"types, and so on) is a sequence "
|
||||
"type", [self.location, f.location])
|
||||
if f.isMozMap():
|
||||
if f.isRecord():
|
||||
raise WebIDLError("An attribute cannot be of a union "
|
||||
"type if one of its member types (or "
|
||||
"one of its member types's member "
|
||||
"types, and so on) is a MozMap "
|
||||
"types, and so on) is a record "
|
||||
"type", [self.location, f.location])
|
||||
if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
|
||||
raise WebIDLError("An attribute with [PutForwards] must have an "
|
||||
|
|
@ -3989,7 +3998,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
def typeContainsChromeOnlyDictionaryMember(type):
|
||||
if (type.nullable() or
|
||||
type.isSequence() or
|
||||
type.isMozMap()):
|
||||
type.isRecord()):
|
||||
return typeContainsChromeOnlyDictionaryMember(type.inner)
|
||||
|
||||
if type.isUnion():
|
||||
|
|
@ -4035,10 +4044,10 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
[self.location, location])
|
||||
if self.getExtendedAttribute("Frozen"):
|
||||
if (not self.type.isSequence() and not self.type.isDictionary() and
|
||||
not self.type.isMozMap()):
|
||||
not self.type.isRecord()):
|
||||
raise WebIDLError("[Frozen] is only allowed on "
|
||||
"sequence-valued, dictionary-valued, and "
|
||||
"MozMap-valued attributes",
|
||||
"record-valued attributes",
|
||||
[self.location])
|
||||
if not self.type.unroll().isExposedInAllOf(self.exposureSet):
|
||||
raise WebIDLError("Attribute returns a type that is not exposed "
|
||||
|
|
@ -5147,7 +5156,7 @@ class Tokenizer(object):
|
|||
"Promise": "PROMISE",
|
||||
"required": "REQUIRED",
|
||||
"sequence": "SEQUENCE",
|
||||
"MozMap": "MOZMAP",
|
||||
"record": "RECORD",
|
||||
"short": "SHORT",
|
||||
"unsigned": "UNSIGNED",
|
||||
"void": "VOID",
|
||||
|
|
@ -6276,7 +6285,7 @@ class Parser(Tokenizer):
|
|||
| OCTET
|
||||
| OPTIONAL
|
||||
| SEQUENCE
|
||||
| MOZMAP
|
||||
| RECORD
|
||||
| SETTER
|
||||
| SHORT
|
||||
| STATIC
|
||||
|
|
@ -6355,7 +6364,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_NonAnyType(self, p):
|
||||
"""
|
||||
NonAnyType : PrimitiveOrStringType Null
|
||||
NonAnyType : PrimitiveType Null
|
||||
| ARRAYBUFFER Null
|
||||
| SHAREDARRAYBUFFER Null
|
||||
| OBJECT Null
|
||||
|
|
@ -6371,6 +6380,12 @@ class Parser(Tokenizer):
|
|||
|
||||
p[0] = self.handleNullable(type, p[2])
|
||||
|
||||
def p_NonAnyTypeStringType(self, p):
|
||||
"""
|
||||
NonAnyType : StringType Null
|
||||
"""
|
||||
p[0] = self.handleNullable(p[1], p[2])
|
||||
|
||||
def p_NonAnyTypeSequenceType(self, p):
|
||||
"""
|
||||
NonAnyType : SEQUENCE LT Type GT Null
|
||||
|
|
@ -6391,13 +6406,14 @@ class Parser(Tokenizer):
|
|||
type = IDLUnresolvedType(self.getLocation(p, 1), promiseIdent, p[3])
|
||||
p[0] = self.handleNullable(type, p[5])
|
||||
|
||||
def p_NonAnyTypeMozMapType(self, p):
|
||||
def p_NonAnyTypeRecordType(self, p):
|
||||
"""
|
||||
NonAnyType : MOZMAP LT Type GT Null
|
||||
NonAnyType : RECORD LT StringType COMMA Type GT Null
|
||||
"""
|
||||
innerType = p[3]
|
||||
type = IDLMozMapType(self.getLocation(p, 1), innerType)
|
||||
p[0] = self.handleNullable(type, p[5])
|
||||
keyType = p[3]
|
||||
valueType = p[5]
|
||||
type = IDLRecordType(self.getLocation(p, 1), keyType, valueType)
|
||||
p[0] = self.handleNullable(type, p[7])
|
||||
|
||||
def p_NonAnyTypeScopedName(self, p):
|
||||
"""
|
||||
|
|
@ -6440,7 +6456,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_ConstType(self, p):
|
||||
"""
|
||||
ConstType : PrimitiveOrStringType Null
|
||||
ConstType : PrimitiveType Null
|
||||
"""
|
||||
type = BuiltinTypes[p[1]]
|
||||
p[0] = self.handleNullable(type, p[2])
|
||||
|
|
@ -6454,69 +6470,75 @@ class Parser(Tokenizer):
|
|||
type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
|
||||
p[0] = self.handleNullable(type, p[2])
|
||||
|
||||
def p_PrimitiveOrStringTypeUint(self, p):
|
||||
def p_PrimitiveTypeUint(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : UnsignedIntegerType
|
||||
PrimitiveType : UnsignedIntegerType
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
def p_PrimitiveOrStringTypeBoolean(self, p):
|
||||
def p_PrimitiveTypeBoolean(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : BOOLEAN
|
||||
PrimitiveType : BOOLEAN
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.boolean
|
||||
|
||||
def p_PrimitiveOrStringTypeByte(self, p):
|
||||
def p_PrimitiveTypeByte(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : BYTE
|
||||
PrimitiveType : BYTE
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.byte
|
||||
|
||||
def p_PrimitiveOrStringTypeOctet(self, p):
|
||||
def p_PrimitiveTypeOctet(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : OCTET
|
||||
PrimitiveType : OCTET
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.octet
|
||||
|
||||
def p_PrimitiveOrStringTypeFloat(self, p):
|
||||
def p_PrimitiveTypeFloat(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : FLOAT
|
||||
PrimitiveType : FLOAT
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.float
|
||||
|
||||
def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
|
||||
def p_PrimitiveTypeUnrestictedFloat(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : UNRESTRICTED FLOAT
|
||||
PrimitiveType : UNRESTRICTED FLOAT
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.unrestricted_float
|
||||
|
||||
def p_PrimitiveOrStringTypeDouble(self, p):
|
||||
def p_PrimitiveTypeDouble(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : DOUBLE
|
||||
PrimitiveType : DOUBLE
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.double
|
||||
|
||||
def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
|
||||
def p_PrimitiveTypeUnrestictedDouble(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : UNRESTRICTED DOUBLE
|
||||
PrimitiveType : UNRESTRICTED DOUBLE
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.unrestricted_double
|
||||
|
||||
def p_PrimitiveOrStringTypeDOMString(self, p):
|
||||
def p_StringType(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : DOMSTRING
|
||||
StringType : BuiltinStringType
|
||||
"""
|
||||
p[0] = BuiltinTypes[p[1]]
|
||||
|
||||
def p_BuiltinStringTypeDOMString(self, p):
|
||||
"""
|
||||
BuiltinStringType : DOMSTRING
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.domstring
|
||||
|
||||
def p_PrimitiveOrStringTypeBytestring(self, p):
|
||||
def p_BuiltinStringTypeBytestring(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : BYTESTRING
|
||||
BuiltinStringType : BYTESTRING
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.bytestring
|
||||
|
||||
def p_PrimitiveOrStringTypeUSVString(self, p):
|
||||
def p_BuiltinStringTypeUSVString(self, p):
|
||||
"""
|
||||
PrimitiveOrStringType : USVSTRING
|
||||
BuiltinStringType : USVSTRING
|
||||
"""
|
||||
p[0] = IDLBuiltinType.Types.usvstring
|
||||
|
||||
|
|
|
|||
|
|
@ -903,11 +903,7 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const
|
|||
|
||||
AutoTArray<InternalHeaders::Entry, 5> headers;
|
||||
mRequest->Headers()->GetEntries(headers);
|
||||
bool hasAccept = false;
|
||||
for (uint32_t i = 0; i < headers.Length(); ++i) {
|
||||
if (!hasAccept && headers[i].mName.EqualsLiteral("accept")) {
|
||||
hasAccept = true;
|
||||
}
|
||||
if (headers[i].mValue.IsEmpty()) {
|
||||
aChannel->SetEmptyRequestHeader(headers[i].mName);
|
||||
} else {
|
||||
|
|
@ -915,12 +911,6 @@ FetchDriver::SetRequestHeaders(nsIHttpChannel* aChannel) const
|
|||
}
|
||||
}
|
||||
|
||||
if (!hasAccept) {
|
||||
aChannel->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
|
||||
NS_LITERAL_CSTRING("*/*"),
|
||||
false /* merge */);
|
||||
}
|
||||
|
||||
if (mRequest->ForceOriginHeader()) {
|
||||
nsAutoString origin;
|
||||
if (NS_SUCCEEDED(nsContentUtils::GetUTFOrigin(mPrincipal, origin))) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ NS_INTERFACE_MAP_END
|
|||
// static
|
||||
already_AddRefed<Headers>
|
||||
Headers::Constructor(const GlobalObject& aGlobal,
|
||||
const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit,
|
||||
const Optional<HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord>& aInit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<InternalHeaders> ih = new InternalHeaders();
|
||||
|
|
@ -39,8 +39,8 @@ Headers::Constructor(const GlobalObject& aGlobal,
|
|||
ih->Fill(*aInit.Value().GetAsHeaders().mInternalHeaders, aRv);
|
||||
} else if (aInit.Value().IsByteStringSequenceSequence()) {
|
||||
ih->Fill(aInit.Value().GetAsByteStringSequenceSequence(), aRv);
|
||||
} else if (aInit.Value().IsByteStringMozMap()) {
|
||||
ih->Fill(aInit.Value().GetAsByteStringMozMap(), aRv);
|
||||
} else if (aInit.Value().IsByteStringByteStringRecord()) {
|
||||
ih->Fill(aInit.Value().GetAsByteStringByteStringRecord(), aRv);
|
||||
}
|
||||
|
||||
if (aRv.Failed()) {
|
||||
|
|
@ -53,7 +53,7 @@ Headers::Constructor(const GlobalObject& aGlobal,
|
|||
// static
|
||||
already_AddRefed<Headers>
|
||||
Headers::Constructor(const GlobalObject& aGlobal,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
|
@ -62,7 +62,7 @@ Headers::Constructor(const GlobalObject& aGlobal,
|
|||
|
||||
/* static */ already_AddRefed<Headers>
|
||||
Headers::Create(nsIGlobalObject* aGlobal,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<InternalHeaders> ih = new InternalHeaders();
|
||||
|
|
@ -72,8 +72,8 @@ Headers::Create(nsIGlobalObject* aGlobal,
|
|||
ih->Fill(*(aInit.GetAsHeaders().get()->mInternalHeaders), aRv);
|
||||
} else if (aInit.IsByteStringSequenceSequence()) {
|
||||
ih->Fill(aInit.GetAsByteStringSequenceSequence(), aRv);
|
||||
} else if (aInit.IsByteStringMozMap()) {
|
||||
ih->Fill(aInit.GetAsByteStringMozMap(), aRv);
|
||||
} else if (aInit.IsByteStringByteStringRecord()) {
|
||||
ih->Fill(aInit.GetAsByteStringByteStringRecord(), aRv);
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ class ErrorResult;
|
|||
|
||||
namespace dom {
|
||||
|
||||
template<typename T> class MozMap;
|
||||
class HeadersOrByteStringSequenceSequenceOrByteStringMozMap;
|
||||
class OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap;
|
||||
template<typename K, typename V> class Record;
|
||||
class HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord;
|
||||
class OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord;
|
||||
|
||||
/**
|
||||
* This Headers class is only used to represent the content facing Headers
|
||||
|
|
@ -57,17 +57,17 @@ public:
|
|||
|
||||
static already_AddRefed<Headers>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit,
|
||||
const Optional<HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord>& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Headers>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Headers>
|
||||
Create(nsIGlobalObject* aGlobalObject,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
|
||||
const OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void Append(const nsACString& aName, const nsACString& aValue,
|
||||
|
|
|
|||
|
|
@ -314,12 +314,13 @@ InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& a
|
|||
}
|
||||
|
||||
void
|
||||
InternalHeaders::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv)
|
||||
InternalHeaders::Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv)
|
||||
{
|
||||
nsTArray<nsString> keys;
|
||||
aInit.GetKeys(keys);
|
||||
for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) {
|
||||
Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv);
|
||||
for (auto& entry : aInit.Entries()) {
|
||||
Append(entry.mKey, entry.mValue, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class ErrorResult;
|
|||
|
||||
namespace dom {
|
||||
|
||||
template<typename T> class MozMap;
|
||||
template<typename K, typename V> class Record;
|
||||
class HeadersEntry;
|
||||
|
||||
class InternalHeaders final
|
||||
|
|
@ -113,7 +113,7 @@ public:
|
|||
|
||||
void Fill(const InternalHeaders& aInit, ErrorResult& aRv);
|
||||
void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
|
||||
void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv);
|
||||
void Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv);
|
||||
|
||||
bool HasOnlySimpleHeaders() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -152,13 +152,13 @@ public:
|
|||
RecvInitRendering(
|
||||
Endpoint<PCompositorBridgeChild>&& aCompositor,
|
||||
Endpoint<PImageBridgeChild>&& aImageBridge,
|
||||
Endpoint<PVideoDecoderManagerChild>&& aVideoManager);
|
||||
Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override;
|
||||
|
||||
bool
|
||||
RecvReinitRendering(
|
||||
Endpoint<PCompositorBridgeChild>&& aCompositor,
|
||||
Endpoint<PImageBridgeChild>&& aImageBridge,
|
||||
Endpoint<PVideoDecoderManagerChild>&& aVideoManager);
|
||||
Endpoint<PVideoDecoderManagerChild>&& aVideoManager) override;
|
||||
|
||||
PProcessHangMonitorChild*
|
||||
AllocPProcessHangMonitorChild(Transport* aTransport,
|
||||
|
|
|
|||
|
|
@ -85,3 +85,5 @@ BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a dis
|
|||
|
||||
# LOCALIZATION NOTE: Do not translate "data: URI".
|
||||
BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
|
||||
BlockSubresourceFTP=Loading FTP subresource within http(s) page not allowed (Blocked loading of: “%1$S”)
|
||||
|
|
|
|||
|
|
@ -92,6 +92,55 @@ nsContentSecurityManager::AllowTopLevelNavigationToDataURI(nsIChannel* aChannel)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsContentSecurityManager::CheckFTPSubresourceLoad(nsIChannel* aChannel)
|
||||
{
|
||||
// We dissallow using FTP resources as a subresource everywhere.
|
||||
// The only valid way to use FTP resources is loading it as
|
||||
// a top level document.
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
if (!loadInfo) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsContentPolicyType type = loadInfo->GetExternalContentPolicyType();
|
||||
if (type == nsIContentPolicy::TYPE_DOCUMENT) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!uri) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isFtpURI = (NS_SUCCEEDED(uri->SchemeIs("ftp", &isFtpURI)) && isFtpURI);
|
||||
if (!isFtpURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
if (nsINode* node = loadInfo->LoadingNode()) {
|
||||
doc = node->OwnerDoc();
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(spec));
|
||||
const char16_t* params[] = { specUTF16.get() };
|
||||
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("FTP_URI_BLOCKED"),
|
||||
doc,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"BlockSubresourceFTP",
|
||||
params, ArrayLength(params));
|
||||
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
|
|
@ -574,6 +623,10 @@ nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
|
|||
rv = DoContentSecurityChecks(aChannel, loadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Apply this after CSP checks to allow CSP reporting.
|
||||
rv = CheckFTPSubresourceLoad(aChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// now lets set the initalSecurityFlag for subsequent calls
|
||||
loadInfo->SetInitialSecurityCheckDone(true);
|
||||
|
||||
|
|
@ -591,6 +644,9 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
// Are we enforcing security using LoadInfo?
|
||||
if (loadInfo && loadInfo->GetEnforceSecurity()) {
|
||||
nsresult rv = CheckChannel(aNewChannel);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = CheckFTPSubresourceLoad(aNewChannel);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
aOldChannel->Cancel(rv);
|
||||
return rv;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
|
||||
private:
|
||||
static nsresult CheckChannel(nsIChannel* aChannel);
|
||||
static nsresult CheckFTPSubresourceLoad(nsIChannel* aChannel);
|
||||
|
||||
virtual ~nsContentSecurityManager() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -314,14 +314,6 @@ URLSearchParams::URLSearchParams(nsISupports* aParent,
|
|||
{
|
||||
}
|
||||
|
||||
URLSearchParams::URLSearchParams(nsISupports* aParent,
|
||||
const URLSearchParams& aOther)
|
||||
: mParams(new URLParams(*aOther.mParams.get()))
|
||||
, mParent(aParent)
|
||||
, mObserver(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
URLSearchParams::~URLSearchParams()
|
||||
{
|
||||
DeleteAll();
|
||||
|
|
@ -335,34 +327,43 @@ URLSearchParams::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
|
||||
/* static */ already_AddRefed<URLSearchParams>
|
||||
URLSearchParams::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aInit,
|
||||
const USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString& aInit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<URLSearchParams> sp =
|
||||
new URLSearchParams(aGlobal.GetAsSupports(), nullptr);
|
||||
|
||||
NS_ConvertUTF16toUTF8 input(aInit);
|
||||
|
||||
if (StringBeginsWith(input, NS_LITERAL_CSTRING("?"))) {
|
||||
sp->ParseInput(Substring(input, 1, input.Length() - 1));
|
||||
if (aInit.IsUSVString()) {
|
||||
NS_ConvertUTF16toUTF8 input(aInit.GetAsUSVString());
|
||||
if (StringBeginsWith(input, NS_LITERAL_CSTRING("?"))) {
|
||||
sp->ParseInput(Substring(input, 1, input.Length() - 1));
|
||||
} else {
|
||||
sp->ParseInput(input);
|
||||
}
|
||||
} else if (aInit.IsUSVStringSequenceSequence()) {
|
||||
const Sequence<Sequence<nsString>>& list =
|
||||
aInit.GetAsUSVStringSequenceSequence();
|
||||
for (uint32_t i = 0; i < list.Length(); ++i) {
|
||||
const Sequence<nsString>& item = list[i];
|
||||
if (item.Length() != 2) {
|
||||
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
sp->Append(item[0], item[1]);
|
||||
}
|
||||
} else if (aInit.IsUSVStringUSVStringRecord()) {
|
||||
const Record<nsString, nsString>& record =
|
||||
aInit.GetAsUSVStringUSVStringRecord();
|
||||
for (auto& entry : record.Entries()) {
|
||||
sp->Append(entry.mKey, entry.mValue);
|
||||
}
|
||||
} else {
|
||||
sp->ParseInput(input);
|
||||
MOZ_CRASH("URLSearchParams: Invalid string");
|
||||
}
|
||||
|
||||
return sp.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<URLSearchParams>
|
||||
URLSearchParams::Constructor(const GlobalObject& aGlobal,
|
||||
URLSearchParams& aInit,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<URLSearchParams> sp =
|
||||
new URLSearchParams(aGlobal.GetAsSupports(), aInit);
|
||||
|
||||
return sp.forget();
|
||||
}
|
||||
|
||||
void
|
||||
URLSearchParams::ParseInput(const nsACString& aInput)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
|
||||
class URLSearchParams;
|
||||
class USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString;
|
||||
|
||||
class URLSearchParamsObserver : public nsISupports
|
||||
{
|
||||
|
|
@ -43,14 +44,6 @@ public:
|
|||
DeleteAll();
|
||||
}
|
||||
|
||||
explicit URLParams(const URLParams& aOther)
|
||||
: mParams(aOther.mParams)
|
||||
{}
|
||||
|
||||
URLParams(const URLParams&& aOther)
|
||||
: mParams(Move(aOther.mParams))
|
||||
{}
|
||||
|
||||
class ForEachIterator
|
||||
{
|
||||
public:
|
||||
|
|
@ -144,9 +137,6 @@ public:
|
|||
explicit URLSearchParams(nsISupports* aParent,
|
||||
URLSearchParamsObserver* aObserver=nullptr);
|
||||
|
||||
URLSearchParams(nsISupports* aParent,
|
||||
const URLSearchParams& aOther);
|
||||
|
||||
// WebIDL methods
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
|
|
@ -157,11 +147,8 @@ public:
|
|||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<URLSearchParams>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<URLSearchParams>
|
||||
Constructor(const GlobalObject& aGlobal, URLSearchParams& aInit,
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const USVStringSequenceSequenceOrUSVStringUSVStringRecordOrUSVString& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void ParseInput(const nsACString& aInput);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* http://fetch.spec.whatwg.org/#headers-class
|
||||
*/
|
||||
|
||||
typedef (Headers or sequence<sequence<ByteString>> or MozMap<ByteString>) HeadersInit;
|
||||
typedef (Headers or sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;
|
||||
|
||||
enum HeadersGuardEnum {
|
||||
"none",
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ interface InstallTriggerImpl {
|
|||
* A callback to call as each installation succeeds or fails
|
||||
* @return true if the installations were successfully started
|
||||
*/
|
||||
boolean install(MozMap<(DOMString or InstallTriggerData)> installs,
|
||||
boolean install(record<DOMString, (DOMString or InstallTriggerData)> installs,
|
||||
optional InstallTriggerCallback callback);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ interface TestInterfaceJS : EventTarget {
|
|||
any pingPongObjectOrString((object or DOMString) objOrString);
|
||||
TestInterfaceJSDictionary pingPongDictionary(optional TestInterfaceJSDictionary dict);
|
||||
long pingPongDictionaryOrLong(optional (TestInterfaceJSUnionableDictionary or long) dictOrLong);
|
||||
DOMString pingPongMap(MozMap<any> map);
|
||||
DOMString pingPongMap(record<DOMString, any> map);
|
||||
long objectSequenceLength(sequence<object> seq);
|
||||
long anySequenceLength(sequence<any> seq);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
* http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
|
||||
*/
|
||||
|
||||
[Constructor(optional USVString init = ""),
|
||||
Constructor(URLSearchParams init),
|
||||
[Constructor(optional (sequence<sequence<USVString>> or record<USVString, USVString> or USVString) init = ""),
|
||||
Exposed=(Window,Worker,WorkerDebugger,System)]
|
||||
interface URLSearchParams {
|
||||
void append(USVString name, USVString value);
|
||||
|
|
|
|||
|
|
@ -462,10 +462,6 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
|||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
||||
NS_LITERAL_CSTRING("*/*"),
|
||||
false);
|
||||
|
||||
nsCOMPtr<nsIURI> referrerURI;
|
||||
aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI));
|
||||
if (referrerURI) {
|
||||
|
|
|
|||
|
|
@ -161,13 +161,13 @@ imgFrame::imgFrame()
|
|||
: mMonitor("imgFrame")
|
||||
, mDecoded(0, 0, 0, 0)
|
||||
, mLockCount(0)
|
||||
, mHasNoAlpha(false)
|
||||
, mAborted(false)
|
||||
, mFinished(false)
|
||||
, mOptimizable(false)
|
||||
, mTimeout(FrameTimeout::FromRawMilliseconds(100))
|
||||
, mDisposalMethod(DisposalMethod::NOT_SPECIFIED)
|
||||
, mBlendMethod(BlendMethod::OVER)
|
||||
, mHasNoAlpha(false)
|
||||
, mPalettedImageData(nullptr)
|
||||
, mPaletteDepth(0)
|
||||
, mNonPremult(false)
|
||||
|
|
|
|||
|
|
@ -407,7 +407,6 @@ StupidAllocator::allocateForDefinition(LInstruction* ins, LDefinition* def)
|
|||
{
|
||||
uint32_t vreg = def->virtualRegister();
|
||||
|
||||
CodePosition from;
|
||||
if ((def->output()->isRegister() && def->policy() == LDefinition::FIXED) ||
|
||||
def->policy() == LDefinition::MUST_REUSE_INPUT)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -495,7 +495,6 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
|
|||
if (associated->is<JSFunction>()) {
|
||||
|
||||
// Canonicalize new functions to use the original one associated with its script.
|
||||
JSFunction* fun = &associated->as<JSFunction>();
|
||||
associated = associated->as<JSFunction>().maybeCanonicalFunction();
|
||||
|
||||
// If we have previously cleared the 'new' script information for this
|
||||
|
|
|
|||
|
|
@ -409,14 +409,30 @@ OffsetToAlignedStaticPos(const ReflowInput& aKidReflowInput,
|
|||
? GetOrthogonalAxis(aAbsPosCBAxis)
|
||||
: aAbsPosCBAxis);
|
||||
|
||||
const bool placeholderContainerIsContainingBlock =
|
||||
aPlaceholderContainer == aKidReflowInput.mCBReflowInput->mFrame;
|
||||
|
||||
nsIAtom* parentType = aPlaceholderContainer->GetType();
|
||||
LogicalSize alignAreaSize(pcWM);
|
||||
if (parentType == nsGkAtoms::flexContainerFrame) {
|
||||
// The alignment container is the flex container's content box:
|
||||
alignAreaSize = aPlaceholderContainer->GetLogicalSize(pcWM);
|
||||
LogicalMargin pcBorderPadding =
|
||||
aPlaceholderContainer->GetLogicalUsedBorderAndPadding(pcWM);
|
||||
alignAreaSize -= pcBorderPadding.Size(pcWM);
|
||||
// We store the frame rect in FinishAndStoreOverflow, which runs _after_
|
||||
// reflowing the absolute frames, so handle the special case of the frame
|
||||
// being the actual containing block here, by getting the size from
|
||||
// aAbsPosCBSize.
|
||||
//
|
||||
// The alignment container is the flex container's content box.
|
||||
if (placeholderContainerIsContainingBlock) {
|
||||
alignAreaSize = aAbsPosCBSize.ConvertTo(pcWM, aAbsPosCBWM);
|
||||
// aAbsPosCBSize is the padding-box, so substract the padding to get the
|
||||
// content box.
|
||||
alignAreaSize -=
|
||||
aPlaceholderContainer->GetLogicalUsedPadding(pcWM).Size(pcWM);
|
||||
} else {
|
||||
alignAreaSize = aPlaceholderContainer->GetLogicalSize(pcWM);
|
||||
LogicalMargin pcBorderPadding =
|
||||
aPlaceholderContainer->GetLogicalUsedBorderAndPadding(pcWM);
|
||||
alignAreaSize -= pcBorderPadding.Size(pcWM);
|
||||
}
|
||||
} else if (parentType == nsGkAtoms::gridContainerFrame) {
|
||||
// This abspos elem's parent is a grid container. Per CSS Grid 10.1 & 10.2:
|
||||
// - If the grid container *also* generates the abspos containing block (a
|
||||
|
|
@ -424,7 +440,7 @@ OffsetToAlignedStaticPos(const ReflowInput& aKidReflowInput,
|
|||
// the alignment container, too. (And its size is aAbsPosCBSize.)
|
||||
// - Otherwise, we use the grid's padding box as the alignment container.
|
||||
// https://drafts.csswg.org/css-grid/#static-position
|
||||
if (aPlaceholderContainer == aKidReflowInput.mCBReflowInput->mFrame) {
|
||||
if (placeholderContainerIsContainingBlock) {
|
||||
// The alignment container is the grid area that we're using as the
|
||||
// absolute containing block.
|
||||
alignAreaSize = aAbsPosCBSize.ConvertTo(pcWM, aAbsPosCBWM);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test Reference</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<style>
|
||||
.parent {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.child {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
top: 50px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head><body><div class="parent"><div class="child"></div></div>
|
||||
</body></html>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test: Absolutely positioned children of flex container with CSS align</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#abspos-items">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1386654">
|
||||
<link rel="match" href="https://hg.mozilla.org/mozilla-central/raw-file/6538de3b6137/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001-ref.html">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<style>
|
||||
.parent {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.child {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head><body><div class="parent"><div class="child"></div></div>
|
||||
</body></html>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test Reference</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<style>
|
||||
.parent {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.child {
|
||||
position: absolute;
|
||||
left: 60px;
|
||||
top: 60px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head><body><div class="parent"><div class="child"></div></div>
|
||||
</body></html>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test: Absolutely positioned children of flex container with CSS align</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#abspos-items">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1386654">
|
||||
<link rel="match" href="https://hg.mozilla.org/mozilla-central/raw-file/6538de3b6137/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002-ref.html">
|
||||
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||
<style>
|
||||
.parent {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
|
||||
/* Expand the background area to 200px, without touching the content-box,
|
||||
which is what flex absolute children should be aligned relative to. */
|
||||
border-top: 5px solid yellow;
|
||||
padding-top: 15px;
|
||||
border-left: 5px solid yellow;
|
||||
padding-left: 15px;
|
||||
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.child {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head><body><div class="parent"><div class="child"></div></div>
|
||||
</body></html>
|
||||
|
|
@ -211,3 +211,7 @@ fails == flexbox-min-height-auto-002b.html flexbox-min-height-auto-002-ref.html
|
|||
== flexbox-single-line-clamp-1.html flexbox-single-line-clamp-1-ref.html
|
||||
== flexbox-single-line-clamp-2.html flexbox-single-line-clamp-2-ref.html
|
||||
== flexbox-single-line-clamp-3.html flexbox-single-line-clamp-3-ref.html
|
||||
|
||||
# Flexbox as an absolute containing block.
|
||||
== position-absolute-containing-block-001.html position-absolute-containing-block-001-ref.html
|
||||
== position-absolute-containing-block-002.html position-absolute-containing-block-002-ref.html
|
||||
|
|
|
|||
|
|
@ -1677,10 +1677,6 @@ Loader::LoadSheet(SheetLoadData* aLoadData,
|
|||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
// Send a minimal Accept header for text/css
|
||||
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
||||
NS_LITERAL_CSTRING("text/css,*/*;q=0.1"),
|
||||
false);
|
||||
nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI();
|
||||
if (referrerURI)
|
||||
httpChannel->SetReferrerWithPolicy(referrerURI,
|
||||
|
|
|
|||
|
|
@ -562,7 +562,7 @@ int cubeb_set_log_callback(cubeb_log_level log_level,
|
|||
void
|
||||
cubeb_crash()
|
||||
{
|
||||
abort();
|
||||
*((volatile int *) NULL) = 0;
|
||||
abort();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1443,12 +1443,12 @@ audiounit_set_buffer_size(cubeb_stream * stm, uint32_t new_size_frames, set_buff
|
|||
buffer_size_changed_callback,
|
||||
stm);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
if (set_side == INPUT) {
|
||||
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/input/kAudioDevicePropertyBufferFrameSize", r);
|
||||
} else {
|
||||
PRINT_ERROR_CODE("AudioUnitAddPropertyListener/output/kAudioDevicePropertyBufferFrameSize", r);
|
||||
}
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
if (!stm->buffer_size_change_state && count >= 30) {
|
||||
|
|
|
|||
|
|
@ -1474,7 +1474,10 @@ pref("network.http.request.max-start-delay", 10);
|
|||
pref("network.http.request.max-attempts", 10);
|
||||
|
||||
// Headers
|
||||
pref("network.http.accept.default", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
pref("network.http.accept.default", "*/*");
|
||||
pref("network.http.accept.navigation", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
pref("network.http.accept.image", "image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5");
|
||||
pref("network.http.accept.style", "text/css,*/*;q=0.1");
|
||||
|
||||
// Prefs allowing granular control of referers
|
||||
// 0=don't send any, 1=send only on clicks, 2=send on image requests as well
|
||||
|
|
|
|||
|
|
@ -117,10 +117,6 @@ pref("security.webauth.u2f", false);
|
|||
pref("security.webauth.u2f_enable_softtoken", false);
|
||||
pref("security.webauth.u2f_enable_usbtoken", false);
|
||||
|
||||
pref("security.ssl.errorReporting.enabled", true);
|
||||
pref("security.ssl.errorReporting.url", "https://incoming.telemetry.mozilla.org/submit/sslreports/");
|
||||
pref("security.ssl.errorReporting.automatic", false);
|
||||
|
||||
// OCSP must-staple
|
||||
pref("security.ssl.enable_ocsp_must_staple", true);
|
||||
|
||||
|
|
|
|||
|
|
@ -654,8 +654,13 @@ private:
|
|||
{
|
||||
nsID channelId;
|
||||
nsLoadFlags flags;
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
loadInfo ? loadInfo->GetExternalContentPolicyType()
|
||||
: nsIContentPolicy::TYPE_OTHER;
|
||||
|
||||
if (NS_FAILED(gHttpHandler->NewChannelId(&channelId)) ||
|
||||
NS_FAILED(chan->Init(uri, caps, nullptr, 0, nullptr, channelId)) ||
|
||||
NS_FAILED(chan->Init(uri, caps, nullptr, 0, nullptr, channelId, contentPolicyType)) ||
|
||||
NS_FAILED(chan->SetAllowAltSvc(false)) ||
|
||||
NS_FAILED(chan->SetRedirectMode(nsIHttpChannelInternal::REDIRECT_MODE_ERROR)) ||
|
||||
NS_FAILED(chan->SetLoadInfo(loadInfo)) ||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI,
|
||||
const nsID& aChannelId)
|
||||
const nsID& aChannelId,
|
||||
nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
|
||||
|
||||
|
|
@ -200,7 +201,7 @@ HttpBaseChannel::Init(nsIURI *aURI,
|
|||
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, isHTTPS);
|
||||
rv = gHttpHandler->AddStandardRequestHeaders(&mRequestHead, isHTTPS, aContentPolicyType);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoCString type;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ public:
|
|||
virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI,
|
||||
const nsID& aChannelId);
|
||||
const nsID& aChannelId,
|
||||
nsContentPolicyType aContentPolicyType);
|
||||
|
||||
// nsIRequest
|
||||
NS_IMETHOD GetName(nsACString& aName) override;
|
||||
|
|
|
|||
|
|
@ -324,10 +324,16 @@ nsHttpChannel::Init(nsIURI *uri,
|
|||
nsProxyInfo *proxyInfo,
|
||||
uint32_t proxyResolveFlags,
|
||||
nsIURI *proxyURI,
|
||||
const nsID& channelId)
|
||||
const nsID& channelId,
|
||||
nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo,
|
||||
proxyResolveFlags, proxyURI, channelId);
|
||||
nsresult rv = HttpBaseChannel::Init(uri,
|
||||
caps,
|
||||
proxyInfo,
|
||||
proxyResolveFlags,
|
||||
proxyURI,
|
||||
channelId,
|
||||
aContentPolicyType);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ public:
|
|||
virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
|
||||
uint32_t aProxyResolveFlags,
|
||||
nsIURI *aProxyURI,
|
||||
const nsID& aChannelId) override;
|
||||
const nsID& aChannelId,
|
||||
nsContentPolicyType aContentPolicyType) override;
|
||||
|
||||
nsresult OnPush(const nsACString &uri, Http2PushedStream *pushedStream);
|
||||
|
||||
|
|
|
|||
|
|
@ -468,7 +468,9 @@ nsHttpHandler::InitConnectionMgr()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecure)
|
||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request,
|
||||
bool isSecure,
|
||||
nsContentPolicyType aContentPolicyType)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
|
@ -481,7 +483,20 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecu
|
|||
// Add the "Accept" header. Note, this is set as an override because the
|
||||
// service worker expects to see it. The other "default" headers are
|
||||
// hidden from service worker interception.
|
||||
rv = request->SetHeader(nsHttp::Accept, mAccept,
|
||||
nsAutoCString accept;
|
||||
if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
|
||||
aContentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
accept.Assign(mAcceptNavigation);
|
||||
} else if (aContentPolicyType == nsIContentPolicy::TYPE_IMAGE ||
|
||||
aContentPolicyType == nsIContentPolicy::TYPE_IMAGESET) {
|
||||
accept.Assign(mAcceptImage);
|
||||
} else if (aContentPolicyType == nsIContentPolicy::TYPE_STYLESHEET) {
|
||||
accept.Assign(mAcceptStyle);
|
||||
} else {
|
||||
accept.Assign(mAcceptDefault);
|
||||
}
|
||||
|
||||
rv = request->SetHeader(nsHttp::Accept, accept,
|
||||
false, nsHttpHeaderArray::eVarietyRequestOverride);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
|
@ -1268,12 +1283,36 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|||
mQoSBits = (uint8_t) clamped(val, 0, 0xff);
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("accept.navigation"))) {
|
||||
nsXPIDLCString accept;
|
||||
rv = prefs->GetCharPref(HTTP_PREF("accept.navigation"),
|
||||
getter_Copies(accept));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
SetAccept(accept, ACCEPT_NAVIGATION);
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("accept.image"))) {
|
||||
nsXPIDLCString accept;
|
||||
rv = prefs->GetCharPref(HTTP_PREF("accept.image"),
|
||||
getter_Copies(accept));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
SetAccept(accept, ACCEPT_IMAGE);
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("accept.style"))) {
|
||||
nsXPIDLCString accept;
|
||||
rv = prefs->GetCharPref(HTTP_PREF("accept.style"),
|
||||
getter_Copies(accept));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
SetAccept(accept, ACCEPT_STYLE);
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
|
||||
nsXPIDLCString accept;
|
||||
rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
|
||||
getter_Copies(accept));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
SetAccept(accept);
|
||||
SetAccept(accept, ACCEPT_DEFAULT);
|
||||
}
|
||||
|
||||
if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
|
||||
|
|
@ -1897,9 +1936,21 @@ nsHttpHandler::SetAcceptLanguages()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsHttpHandler::SetAccept(const char *aAccept)
|
||||
nsHttpHandler::SetAccept(const char *aAccept, AcceptType aType)
|
||||
{
|
||||
mAccept = aAccept;
|
||||
switch (aType) {
|
||||
case ACCEPT_NAVIGATION:
|
||||
mAcceptNavigation = aAccept;
|
||||
break;
|
||||
case ACCEPT_IMAGE:
|
||||
mAcceptImage = aAccept;
|
||||
break;
|
||||
case ACCEPT_STYLE:
|
||||
mAcceptStyle = aAccept;
|
||||
break;
|
||||
case ACCEPT_DEFAULT:
|
||||
mAcceptDefault = aAccept;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2057,7 +2108,11 @@ nsHttpHandler::NewProxiedChannel2(nsIURI *uri,
|
|||
rv = NewChannelId(&channelId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId);
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aLoadInfo ? aLoadInfo->GetExternalContentPolicyType()
|
||||
: nsIContentPolicy::TYPE_OTHER;
|
||||
|
||||
rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId, contentPolicyType);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIHttpProtocolHandler.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
|
|
@ -50,6 +51,14 @@ enum FrameCheckLevel {
|
|||
FRAMECHECK_STRICT
|
||||
};
|
||||
|
||||
// Fetch spec different http Accept types
|
||||
enum AcceptType {
|
||||
ACCEPT_NAVIGATION,
|
||||
ACCEPT_IMAGE,
|
||||
ACCEPT_STYLE,
|
||||
ACCEPT_DEFAULT,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpHandler - protocol handler for HTTP and HTTPS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -70,7 +79,7 @@ public:
|
|||
nsHttpHandler();
|
||||
|
||||
nsresult Init();
|
||||
nsresult AddStandardRequestHeaders(nsHttpRequestHead *, bool isSecure);
|
||||
nsresult AddStandardRequestHeaders(nsHttpRequestHead *, bool isSecure, nsContentPolicyType aContentPolicyType);
|
||||
nsresult AddConnectionHeader(nsHttpRequestHead *,
|
||||
uint32_t capabilities);
|
||||
bool IsAcceptableEncoding(const char *encoding, bool isSecure);
|
||||
|
|
@ -385,7 +394,7 @@ private:
|
|||
void InitUserAgentComponents();
|
||||
void PrefsChanged(nsIPrefBranch *prefs, const char *pref);
|
||||
|
||||
nsresult SetAccept(const char *);
|
||||
nsresult SetAccept(const char *, AcceptType aType);
|
||||
nsresult SetAcceptLanguages();
|
||||
nsresult SetAcceptEncodings(const char *, bool mIsSecure);
|
||||
|
||||
|
|
@ -394,8 +403,8 @@ private:
|
|||
void NotifyObservers(nsIHttpChannel *chan, const char *event);
|
||||
|
||||
static void TimerCallback(nsITimer * aTimer, void * aClosure);
|
||||
|
||||
private:
|
||||
|
||||
// cached services
|
||||
nsMainThreadPtrHandle<nsIIOService> mIOService;
|
||||
nsMainThreadPtrHandle<nsIStreamConverterService> mStreamConvSvc;
|
||||
|
|
@ -460,7 +469,10 @@ private:
|
|||
bool mPipeliningOverSSL;
|
||||
bool mEnforceAssocReq;
|
||||
|
||||
nsCString mAccept;
|
||||
nsCString mAcceptNavigation;
|
||||
nsCString mAcceptImage;
|
||||
nsCString mAcceptStyle;
|
||||
nsCString mAcceptDefault;
|
||||
nsCString mAcceptLanguages;
|
||||
nsCString mHttpAcceptEncodings;
|
||||
nsCString mHttpsAcceptEncodings;
|
||||
|
|
|
|||
|
|
@ -25,3 +25,5 @@ support-files =
|
|||
[test_viewsource_unlinkable.html]
|
||||
[test_xhr_method_case.html]
|
||||
[test_1396395.html]
|
||||
[test_accept_header.html]
|
||||
support-files = test_accept_header.sjs
|
||||
|
|
|
|||
106
netwerk/test/mochitests/test_accept_header.html
Normal file
106
netwerk/test/mochitests/test_accept_header.html
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Accept header</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
// All the requests are sent to test_accept_header.sjs which will return
|
||||
// different content based on the queryString. When the queryString is 'get',
|
||||
// test_accept_header.sjs returns a JSON object with the latest request and its
|
||||
// accept header value.
|
||||
|
||||
function test_last_request_and_continue(query, expected) {
|
||||
fetch("test_accept_header.sjs?get").then(r => r.json()).then(json => {
|
||||
is(json.type, query, "Expected: " + query);
|
||||
is(json.accept, expected, "Accept header: " + expected);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function test_iframe() {
|
||||
let observer = new PerformanceObserver(function(list, obj) {
|
||||
obj.disconnect();
|
||||
|
||||
list.getEntries().forEach(entry => {
|
||||
if (entry.name.endsWith("test_accept_header.sjs?iframe")) {
|
||||
obj.disconnect();
|
||||
test_last_request_and_continue("iframe", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ["resource"]});
|
||||
|
||||
let ifr = document.createElement("iframe");
|
||||
ifr.src = "test_accept_header.sjs?iframe";
|
||||
document.body.appendChild(ifr);
|
||||
}
|
||||
|
||||
function test_image() {
|
||||
let i = new Image();
|
||||
i.src = "test_accept_header.sjs?image";
|
||||
i.onload = function() {
|
||||
// Fetch spec says we should have: "image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"
|
||||
test_last_request_and_continue("image", "image/webp,image/png,image/*;q=0.8,*/*;q=0.5");
|
||||
}
|
||||
}
|
||||
|
||||
function test_style() {
|
||||
let observer = new PerformanceObserver(function(list, obj) {
|
||||
obj.disconnect();
|
||||
|
||||
list.getEntries().forEach(entry => {
|
||||
if (entry.name.endsWith("test_accept_header.sjs?style")) {
|
||||
obj.disconnect();
|
||||
test_last_request_and_continue("style", "text/css,*/*;q=0.1");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe({entryTypes: ["resource"]});
|
||||
|
||||
let head = document.getElementsByTagName("head")[0];
|
||||
let link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.type = "text/css";
|
||||
link.href = "test_accept_header.sjs?style";
|
||||
head.appendChild(link);
|
||||
}
|
||||
|
||||
function test_worker() {
|
||||
let w = new Worker("test_accept_header.sjs?worker");
|
||||
w.onmessage = function() {
|
||||
test_last_request_and_continue("worker", "*/*");
|
||||
}
|
||||
}
|
||||
|
||||
let tests = [
|
||||
test_iframe,
|
||||
test_image,
|
||||
test_style,
|
||||
test_worker,
|
||||
];
|
||||
|
||||
function next() {
|
||||
if (tests.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
let test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SpecialPowers.pushPrefEnv({ "set": [
|
||||
[ "dom.enable_performance_observer", true ]
|
||||
]}, next);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
48
netwerk/test/mochitests/test_accept_header.sjs
Normal file
48
netwerk/test/mochitests/test_accept_header.sjs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
function handleRequest(request, response) {
|
||||
response.setStatusLine(request.httpVersion, "200", "OK");
|
||||
|
||||
if (request.queryString == "worker") {
|
||||
response.setHeader("Content-Type", "application/json", false);
|
||||
response.write("postMessage(42)");
|
||||
|
||||
setState("data", JSON.stringify({type: "worker", accept: request.getHeader("Accept") }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString == "image") {
|
||||
// A 1x1 PNG image.
|
||||
// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
|
||||
const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
|
||||
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
|
||||
|
||||
response.setHeader("Content-Type", "image/png", false);
|
||||
response.write(IMAGE);
|
||||
|
||||
setState("data", JSON.stringify({type: "image", accept: request.getHeader("Accept") }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString == "style") {
|
||||
response.setHeader("Content-Type", "text/css", false);
|
||||
response.write("");
|
||||
|
||||
setState("data", JSON.stringify({type: "style", accept: request.getHeader("Accept") }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString == "iframe") {
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write("<h1>Hello world!</h1>");
|
||||
|
||||
setState("data", JSON.stringify({type: "iframe", accept: request.getHeader("Accept") }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString == "get") {
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
response.write(getState("data"));
|
||||
|
||||
setState("data", "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -210,8 +210,8 @@ const uint64_t kSixtyDaysInSeconds = 60 * 24 * 60 * 60;
|
|||
nsSiteSecurityService::nsSiteSecurityService()
|
||||
: mMaxMaxAge(kSixtyDaysInSeconds)
|
||||
, mUsePreloadList(true)
|
||||
, mPreloadListTimeOffset(0)
|
||||
, mUseStsService(true)
|
||||
, mPreloadListTimeOffset(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1503,6 +1503,24 @@ public:
|
|||
mozilla::Forward<Item>(aItem));
|
||||
}
|
||||
|
||||
// Reconstruct the element at the given index, and return a pointer to the
|
||||
// reconstructed element. This will destroy the existing element and
|
||||
// default-construct a new one, giving you a state much like what single-arg
|
||||
// InsertElementAt(), or no-arg AppendElement() does, but without changing the
|
||||
// length of the array.
|
||||
//
|
||||
// array[idx] = T()
|
||||
//
|
||||
// would accomplish the same thing as long as T has the appropriate moving
|
||||
// operator=, but some types don't for various reasons.
|
||||
elem_type* ReconstructElementAt(index_type aIndex)
|
||||
{
|
||||
elem_type* elem = &ElementAt(aIndex);
|
||||
elem_traits::Destruct(elem);
|
||||
elem_traits::Construct(elem);
|
||||
return elem;
|
||||
}
|
||||
|
||||
// This method searches for the smallest index of an element that is strictly
|
||||
// greater than |aItem|. If |aItem| is inserted at this index, the array will
|
||||
// remain sorted and |aItem| would come after all elements that are equal to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue