Compare commits
73
Commits
master
...
RB_20230417
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54e3e60796 | ||
|
|
2a05494abe | ||
|
|
bc89e58def | ||
|
|
3a009b97f6 | ||
|
|
a105f6d5e9 | ||
|
|
5db241c0c0 | ||
|
|
d38dca10e5 | ||
|
|
54fc723126 | ||
|
|
9b8ca17ee4 | ||
|
|
cddc95b39b | ||
|
|
5676529793 | ||
|
|
ce68156cf4 | ||
|
|
5032ad9593 | ||
|
|
b55f765f2e | ||
|
|
856078d435 | ||
|
|
c74c262d2f | ||
|
|
787e29e374 | ||
|
|
e439896c9b | ||
|
|
15b508f1fb | ||
|
|
5651ebfc76 | ||
|
|
593bfc1ce8 | ||
|
|
28953cda7a | ||
|
|
516f3f545d | ||
|
|
83aff65a42 | ||
|
|
5bd97df957 | ||
|
|
8772711181 | ||
|
|
dc9526f4c6 | ||
|
|
9ab36e7ae0 | ||
|
|
e8d30841e7 | ||
|
|
9faf29374e | ||
|
|
75e4818d36 | ||
|
|
a65144e9e0 | ||
|
|
4f29548526 | ||
|
|
528db2cbd8 | ||
|
|
84e6bcc1e6 | ||
|
|
0dc9ff518d | ||
|
|
a2e3bd44aa | ||
|
|
163a0e7caf | ||
|
|
49a86db5f3 | ||
|
|
2640953d8b | ||
|
|
7eb7d67f7a | ||
|
|
e28860ba7f | ||
|
|
49a96b1d91 | ||
|
|
3130812693 | ||
|
|
71ae69aea8 | ||
|
|
9e34d697c7 | ||
|
|
8fa9125d02 | ||
|
|
4b4488c3e4 | ||
|
|
248db7d301 | ||
|
|
e199f2949b | ||
|
|
456b5450a4 | ||
|
|
d8e629c4a3 | ||
|
|
4898c4f297 | ||
|
|
7cd578bbc6 | ||
|
|
1e91df628a | ||
|
|
b110549cbd | ||
|
|
971047835a | ||
|
|
dd4d9eb032 | ||
|
|
8b94f1e480 | ||
|
|
c89610a5c7 | ||
|
|
217963cbed | ||
|
|
c4f4e18340 | ||
|
|
8a7c0e7345 | ||
|
|
52e304d450 | ||
|
|
cfc0eeca53 | ||
|
|
ebd3dd9228 | ||
|
|
cb40e4e7ef | ||
|
|
662dba55fd | ||
|
|
8760ce023c | ||
|
|
b86e148bb7 | ||
|
|
9e83721e5e | ||
|
|
dc2d6c2e60 | ||
|
|
4ada6f6762 |
No files matched your search
@@ -274,6 +274,7 @@ def old_configure_options(*options):
|
||||
'--with-ios-sdk',
|
||||
'--with-jitreport-granularity',
|
||||
'--with-macbundlename-prefix',
|
||||
'--with-macbundle-identity',
|
||||
'--with-macos-private-frameworks',
|
||||
'--with-macos-sdk',
|
||||
'--with-nspr-cflags',
|
||||
|
||||
@@ -279,6 +279,13 @@ ShadowRoot::InsertSheet(StyleSheet* aSheet,
|
||||
}
|
||||
|
||||
nsINode* sheetOwningNode = SheetAt(i)->GetOwnerNode();
|
||||
|
||||
if (!sheetOwningNode) {
|
||||
// Keep moving; all sheets with a sheetOwner come after all
|
||||
// sheets without an owning Node
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nsContentUtils::PositionIsBefore(aLinkingContent, sheetOwningNode)) {
|
||||
InsertSheetAt(i, *aSheet);
|
||||
mProtoBinding->InsertStyleSheetAt(i, aSheet);
|
||||
|
||||
@@ -84,8 +84,9 @@ DataAtOffset(DataSourceSurface* aSurface,
|
||||
MOZ_ASSERT(Factory::CheckSurfaceSize(aSurface->GetSize()),
|
||||
"surface size overflows - this should have been prevented when the surface was created");
|
||||
|
||||
uint8_t* data = aMap->mData + aPoint.y * aMap->mStride +
|
||||
aPoint.x * BytesPerPixel(aSurface->GetFormat());
|
||||
uint8_t* data = aMap->mData +
|
||||
size_t(aPoint.y) * size_t(aMap->mStride) +
|
||||
size_t(aPoint.x) * size_t(BytesPerPixel(aSurface->GetFormat()));
|
||||
|
||||
if (data < aMap->mData) {
|
||||
MOZ_CRASH("GFX: out-of-range data access");
|
||||
@@ -124,22 +125,29 @@ void
|
||||
CopySurfaceDataToPackedArray(uint8_t* aSrc, uint8_t* aDst, IntSize aSrcSize,
|
||||
int32_t aSrcStride, int32_t aBytesPerPixel)
|
||||
{
|
||||
MOZ_ASSERT(aBytesPerPixel > 0,
|
||||
"Negative stride for aDst not currently supported");
|
||||
MOZ_ASSERT(BufferSizeFromStrideAndHeight(aSrcStride, aSrcSize.height) > 0,
|
||||
"How did we end up with a surface with such a big buffer?");
|
||||
CheckedInt<size_t> packedStride(aBytesPerPixel);
|
||||
packedStride *= aSrcSize.width;
|
||||
if (!packedStride.isValid()) {
|
||||
MOZ_ASSERT(false, "Invalid stride");
|
||||
return;
|
||||
}
|
||||
|
||||
int packedStride = aSrcSize.width * aBytesPerPixel;
|
||||
CheckedInt<size_t> totalSize(aSrcStride);
|
||||
totalSize *= aSrcSize.height;
|
||||
if (!totalSize.isValid()) {
|
||||
MOZ_ASSERT(false, "Invalid surface size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aSrcStride == packedStride) {
|
||||
if (size_t(aSrcStride) == packedStride.value()) {
|
||||
// aSrc is already packed, so we can copy with a single memcpy.
|
||||
memcpy(aDst, aSrc, packedStride * aSrcSize.height);
|
||||
memcpy(aDst, aSrc, totalSize.value());
|
||||
} else {
|
||||
// memcpy one row at a time.
|
||||
for (int row = 0; row < aSrcSize.height; ++row) {
|
||||
memcpy(aDst, aSrc, packedStride);
|
||||
memcpy(aDst, aSrc, packedStride.value());
|
||||
aSrc += aSrcStride;
|
||||
aDst += packedStride;
|
||||
aDst += packedStride.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,10 +63,11 @@ using namespace js::jit;
|
||||
* The tempN registers are free to use for computations.
|
||||
*/
|
||||
|
||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
JSRuntime* rt, Mode mode, int registers_to_save)
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, registers_to_save),
|
||||
cx(cx), runtime(rt), mode_(mode)
|
||||
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(LifoAlloc* alloc, JSRuntime* rt,
|
||||
Mode mode, int registers_to_save,
|
||||
RegExpShared::JitCodeTables& tables)
|
||||
: RegExpMacroAssembler(*alloc, registers_to_save),
|
||||
tables(tables), runtime(rt), mode_(mode)
|
||||
{
|
||||
// Find physical registers for each compiler register.
|
||||
AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
|
||||
@@ -886,11 +887,11 @@ NativeRegExpMacroAssembler::CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
}
|
||||
|
||||
void
|
||||
NativeRegExpMacroAssembler::CheckBitInTable(uint8_t* table, Label* on_bit_set)
|
||||
NativeRegExpMacroAssembler::CheckBitInTable(RegExpShared::JitCodeTable table, Label* on_bit_set)
|
||||
{
|
||||
JitSpew(SPEW_PREFIX "CheckBitInTable");
|
||||
|
||||
masm.movePtr(ImmPtr(table), temp0);
|
||||
masm.movePtr(ImmPtr(table.get()), temp0);
|
||||
|
||||
// kTableMask is currently 127, so we need to mask even if the input is
|
||||
// Latin1. V8 has the same issue.
|
||||
@@ -901,6 +902,13 @@ NativeRegExpMacroAssembler::CheckBitInTable(uint8_t* table, Label* on_bit_set)
|
||||
|
||||
masm.load8ZeroExtend(BaseIndex(temp0, temp1, TimesOne), temp0);
|
||||
masm.branchTest32(Assembler::NonZero, temp0, temp0, BranchOrBacktrack(on_bit_set));
|
||||
|
||||
// Transfer ownership of |table| to the |tables| Vector.
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
if (!tables.append(Move(table)))
|
||||
oomUnsafe.crash("RegExp table append");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -87,8 +87,8 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
// Type of input string to generate code for.
|
||||
enum Mode { ASCII = 1, CHAR16 = 2 };
|
||||
|
||||
NativeRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
JSRuntime* rt, Mode mode, int registers_to_save);
|
||||
NativeRegExpMacroAssembler(LifoAlloc* alloc, JSRuntime* rt, Mode mode, int registers_to_save,
|
||||
RegExpShared::JitCodeTables& tables);
|
||||
|
||||
// Inherited virtual methods.
|
||||
RegExpCode GenerateCode(JSContext* cx, bool match_only);
|
||||
@@ -116,7 +116,7 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
jit::Label* on_in_range);
|
||||
void CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
jit::Label* on_not_in_range);
|
||||
void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set);
|
||||
void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set);
|
||||
void CheckPosition(int cp_offset, jit::Label* on_outside_input);
|
||||
void JumpOrBacktrack(jit::Label* to);
|
||||
bool CheckSpecialCharacterClass(char16_t type, jit::Label* on_no_match);
|
||||
@@ -173,8 +173,8 @@ class MOZ_STACK_CLASS NativeRegExpMacroAssembler final : public RegExpMacroAssem
|
||||
|
||||
private:
|
||||
jit::MacroAssembler masm;
|
||||
RegExpShared::JitCodeTables& tables;
|
||||
|
||||
JSContext* cx;
|
||||
JSRuntime* runtime;
|
||||
Mode mode_;
|
||||
jit::Label entry_label_;
|
||||
|
||||
@@ -1262,7 +1262,7 @@ RegExpCode
|
||||
irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_ascii, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode)
|
||||
bool unicode, RegExpShared::JitCodeTables& tables)
|
||||
{
|
||||
if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
|
||||
JS_ReportErrorASCII(cx, "regexp too big");
|
||||
@@ -1350,10 +1350,10 @@ irregexp::CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompile
|
||||
: NativeRegExpMacroAssembler::CHAR16;
|
||||
|
||||
ctx.emplace(cx, (jit::TempAllocator*) nullptr);
|
||||
native_assembler.emplace(cx, &alloc, shared, cx->runtime(), mode, (data->capture_count + 1) * 2);
|
||||
native_assembler.emplace(&alloc, cx->runtime(), mode, (data->capture_count + 1) * 2, tables);
|
||||
assembler = native_assembler.ptr();
|
||||
} else {
|
||||
interpreted_assembler.emplace(cx, &alloc, shared, (data->capture_count + 1) * 2);
|
||||
interpreted_assembler.emplace(&alloc, (data->capture_count + 1) * 2);
|
||||
assembler = interpreted_assembler.ptr();
|
||||
}
|
||||
|
||||
@@ -2040,21 +2040,21 @@ BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* boolean_skip_table;
|
||||
RegExpShared::JitCodeTable boolean_skip_table;
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
boolean_skip_table = static_cast<uint8_t*>(js_malloc(kSize));
|
||||
if (!boolean_skip_table || !masm->shared->addTable(boolean_skip_table))
|
||||
boolean_skip_table.reset(static_cast<uint8_t*>(js_malloc(kSize)));
|
||||
if (!boolean_skip_table)
|
||||
oomUnsafe.crash("Table malloc");
|
||||
}
|
||||
|
||||
int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table);
|
||||
int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table.get());
|
||||
MOZ_ASSERT(skip_distance != 0);
|
||||
|
||||
jit::Label cont, again;
|
||||
masm->Bind(&again);
|
||||
masm->LoadCurrentCharacter(max_lookahead, &cont, true);
|
||||
masm->CheckBitInTable(boolean_skip_table, &cont);
|
||||
masm->CheckBitInTable(Move(boolean_skip_table), &cont);
|
||||
masm->AdvanceCurrentPosition(skip_distance);
|
||||
masm->JumpOrBacktrack(&again);
|
||||
masm->Bind(&cont);
|
||||
@@ -2832,18 +2832,18 @@ EmitUseLookupTable(RegExpMacroAssembler* masm,
|
||||
}
|
||||
|
||||
// TODO(erikcorry): Cache these.
|
||||
uint8_t* ba;
|
||||
RegExpShared::JitCodeTable ba;
|
||||
{
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
ba = static_cast<uint8_t*>(js_malloc(kSize));
|
||||
if (!ba || !masm->shared->addTable(ba))
|
||||
ba.reset(static_cast<uint8_t*>(js_malloc(kSize)));
|
||||
if (!ba)
|
||||
oomUnsafe.crash("Table malloc");
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSize; i++)
|
||||
ba[i] = templ[i];
|
||||
|
||||
masm->CheckBitInTable(ba, on_bit_set);
|
||||
masm->CheckBitInTable(Move(ba), on_bit_set);
|
||||
if (on_bit_clear != fall_through)
|
||||
masm->JumpOrBacktrack(on_bit_clear);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ RegExpCode
|
||||
CompilePattern(JSContext* cx, HandleRegExpShared shared, RegExpCompileData* data,
|
||||
HandleLinearString sample, bool is_global, bool ignore_case,
|
||||
bool is_ascii, bool match_only, bool force_bytecode, bool sticky,
|
||||
bool unicode);
|
||||
bool unicode, RegExpShared::JitCodeTables& tables);
|
||||
|
||||
// Note: this may return RegExpRunStatus_Error if an interrupt was requested
|
||||
// while the code was executing.
|
||||
|
||||
@@ -96,10 +96,9 @@ irregexp::CaseInsensitiveCompareUCStrings(const char16_t* substring1,
|
||||
const char16_t* substring2,
|
||||
size_t byteLength);
|
||||
|
||||
InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc,
|
||||
RegExpShared* shared,
|
||||
InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(LifoAlloc* alloc,
|
||||
size_t numSavedRegisters)
|
||||
: RegExpMacroAssembler(cx, *alloc, shared, numSavedRegisters),
|
||||
: RegExpMacroAssembler(*alloc, numSavedRegisters),
|
||||
pc_(0),
|
||||
advance_current_start_(0),
|
||||
advance_current_offset_(0),
|
||||
@@ -317,7 +316,8 @@ InterpretedRegExpMacroAssembler::CheckCharacterNotInRange(char16_t from, char16_
|
||||
}
|
||||
|
||||
void
|
||||
InterpretedRegExpMacroAssembler::CheckBitInTable(uint8_t* table, jit::Label* on_bit_set)
|
||||
InterpretedRegExpMacroAssembler::CheckBitInTable(RegExpShared::JitCodeTable table,
|
||||
jit::Label* on_bit_set)
|
||||
{
|
||||
static const int kBitsPerByte = 8;
|
||||
|
||||
|
||||
@@ -40,14 +40,12 @@ namespace irregexp {
|
||||
class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
RegExpMacroAssembler(JSContext* cx, LifoAlloc& alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters)
|
||||
RegExpMacroAssembler(LifoAlloc& alloc, size_t numSavedRegisters)
|
||||
: slow_safe_compiler_(false),
|
||||
global_mode_(NOT_GLOBAL),
|
||||
alloc_(alloc),
|
||||
num_registers_(numSavedRegisters),
|
||||
num_saved_registers_(numSavedRegisters),
|
||||
shared(cx, shared)
|
||||
num_saved_registers_(numSavedRegisters)
|
||||
{}
|
||||
|
||||
enum StackCheckFlag {
|
||||
@@ -137,7 +135,7 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
|
||||
// The current character (modulus the kTableSize) is looked up in the byte
|
||||
// array, and if the found byte is non-zero, we jump to the on_bit_set label.
|
||||
virtual void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set) = 0;
|
||||
virtual void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set) = 0;
|
||||
|
||||
// Checks whether the given offset from the current position is before
|
||||
// the end of the string. May overwrite the current character.
|
||||
@@ -213,9 +211,6 @@ class MOZ_STACK_CLASS RegExpMacroAssembler
|
||||
if (num_registers_ <= reg)
|
||||
num_registers_ = reg + 1;
|
||||
}
|
||||
|
||||
public:
|
||||
RootedRegExpShared shared;
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
@@ -230,8 +225,7 @@ CaseInsensitiveCompareUCStrings(const CharT* substring1, const CharT* substring2
|
||||
class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacroAssembler
|
||||
{
|
||||
public:
|
||||
InterpretedRegExpMacroAssembler(JSContext* cx, LifoAlloc* alloc, RegExpShared* shared,
|
||||
size_t numSavedRegisters);
|
||||
InterpretedRegExpMacroAssembler(LifoAlloc* alloc, size_t numSavedRegisters);
|
||||
~InterpretedRegExpMacroAssembler();
|
||||
|
||||
// Inherited virtual methods.
|
||||
@@ -258,7 +252,7 @@ class MOZ_STACK_CLASS InterpretedRegExpMacroAssembler final : public RegExpMacro
|
||||
jit::Label* on_in_range);
|
||||
void CheckCharacterNotInRange(char16_t from, char16_t to,
|
||||
jit::Label* on_not_in_range);
|
||||
void CheckBitInTable(uint8_t* table, jit::Label* on_bit_set);
|
||||
void CheckBitInTable(RegExpShared::JitCodeTable table, jit::Label* on_bit_set);
|
||||
void JumpOrBacktrack(jit::Label* to);
|
||||
void Fail();
|
||||
void IfRegisterGE(int reg, int comparand, jit::Label* if_ge);
|
||||
|
||||
@@ -3757,6 +3757,7 @@ CodeGenerator::visitCallNative(LCallNative* call)
|
||||
if (jitInfo && jitInfo->type() == JSJitInfo::IgnoresReturnValueNative)
|
||||
native = jitInfo->ignoresReturnValueMethod;
|
||||
}
|
||||
ensureOsiSpace();
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, native));
|
||||
|
||||
emitTracelogStopEvent(TraceLogger_Call);
|
||||
@@ -3881,6 +3882,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
|
||||
masm.passABIArg(argObj);
|
||||
masm.passABIArg(argPrivate);
|
||||
masm.passABIArg(argArgs);
|
||||
ensureOsiSpace();
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, target->jitInfo()->method));
|
||||
|
||||
if (target->jitInfo()->isInfallible) {
|
||||
@@ -4006,6 +4008,7 @@ CodeGenerator::visitCallGeneric(LCallGeneric* call)
|
||||
|
||||
// Finally call the function in objreg.
|
||||
masm.bind(&makeCall);
|
||||
ensureOsiSpace();
|
||||
uint32_t callOffset = masm.callJit(objreg);
|
||||
markSafepointAt(callOffset, call);
|
||||
|
||||
@@ -4104,6 +4107,7 @@ CodeGenerator::visitCallKnown(LCallKnown* call)
|
||||
masm.Push(Imm32(descriptor));
|
||||
|
||||
// Finally call the function in objreg.
|
||||
ensureOsiSpace();
|
||||
uint32_t callOffset = masm.callJit(objreg);
|
||||
markSafepointAt(callOffset, call);
|
||||
|
||||
@@ -4436,6 +4440,7 @@ CodeGenerator::emitApplyGeneric(T* apply)
|
||||
masm.bind(&rejoin);
|
||||
|
||||
// Finally call the function in objreg, as assigned by one of the paths above.
|
||||
ensureOsiSpace();
|
||||
uint32_t callOffset = masm.callJit(objreg);
|
||||
markSafepointAt(callOffset, apply);
|
||||
|
||||
@@ -11244,6 +11249,7 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
|
||||
masm.passABIArg(ObjectReg);
|
||||
masm.passABIArg(PrivateReg);
|
||||
masm.passABIArg(ValueReg);
|
||||
ensureOsiSpace();
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ins->mir()->fun()));
|
||||
|
||||
if (ins->mir()->isInfallible()) {
|
||||
|
||||
@@ -46,7 +46,8 @@ struct LoopIterationBound : public TempObject
|
||||
// of the loop header. This will use loop invariant terms and header phis.
|
||||
LinearSum currentSum;
|
||||
|
||||
LoopIterationBound(MBasicBlock* header, MTest* test, LinearSum boundSum, LinearSum currentSum)
|
||||
LoopIterationBound(MBasicBlock* header, MTest* test,
|
||||
const LinearSum& boundSum, const LinearSum& currentSum)
|
||||
: header(header), test(test),
|
||||
boundSum(boundSum), currentSum(currentSum)
|
||||
{
|
||||
@@ -59,7 +60,7 @@ typedef Vector<LoopIterationBound*, 0, SystemAllocPolicy> LoopIterationBoundVect
|
||||
struct SymbolicBound : public TempObject
|
||||
{
|
||||
private:
|
||||
SymbolicBound(LoopIterationBound* loop, LinearSum sum)
|
||||
SymbolicBound(LoopIterationBound* loop, const LinearSum& sum)
|
||||
: loop(loop), sum(sum)
|
||||
{
|
||||
}
|
||||
@@ -73,7 +74,8 @@ struct SymbolicBound : public TempObject
|
||||
// If nullptr, then 'sum' is always valid.
|
||||
LoopIterationBound* loop;
|
||||
|
||||
static SymbolicBound* New(TempAllocator& alloc, LoopIterationBound* loop, LinearSum sum) {
|
||||
static SymbolicBound*
|
||||
New(TempAllocator& alloc, LoopIterationBound* loop, const LinearSum& sum) {
|
||||
return new(alloc) SymbolicBound(loop, sum);
|
||||
}
|
||||
|
||||
|
||||
@@ -1112,7 +1112,6 @@ CodeGeneratorShared::ensureOsiSpace()
|
||||
}
|
||||
MOZ_ASSERT_IF(!masm.oom(),
|
||||
masm.currentOffset() - lastOsiPointOffset_ >= Assembler::PatchWrite_NearCallSize());
|
||||
lastOsiPointOffset_ = masm.currentOffset();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -1124,6 +1123,7 @@ CodeGeneratorShared::markOsiPoint(LOsiPoint* ins)
|
||||
uint32_t offset = masm.currentOffset();
|
||||
SnapshotOffset so = ins->snapshot()->snapshotOffset();
|
||||
masm.propagateOOM(osiIndices_.append(OsiIndex(offset, so)));
|
||||
lastOsiPointOffset_ = offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
/* Note: Aborts on OOM. */
|
||||
class JSAPITestString {
|
||||
js::Vector<char, 0, js::SystemAllocPolicy> chars;
|
||||
|
||||
public:
|
||||
JSAPITestString() {}
|
||||
explicit JSAPITestString(const char* s) { *this += s; }
|
||||
@@ -32,21 +33,34 @@ class JSAPITestString {
|
||||
const char* end() const { return chars.end(); }
|
||||
size_t length() const { return chars.length(); }
|
||||
|
||||
JSAPITestString & operator +=(const char* s) {
|
||||
JSAPITestString& operator +=(const char* s) {
|
||||
if (!chars.append(s, strlen(s)))
|
||||
abort();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSAPITestString & operator +=(const JSAPITestString& s) {
|
||||
JSAPITestString& operator +=(const JSAPITestString& s) {
|
||||
if (!chars.append(s.begin(), s.length()))
|
||||
abort();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
inline JSAPITestString operator+(JSAPITestString a, const char* b) { return a += b; }
|
||||
inline JSAPITestString operator+(JSAPITestString a, const JSAPITestString& b) { return a += b; }
|
||||
inline JSAPITestString
|
||||
operator+(const JSAPITestString& a, const char* b)
|
||||
{
|
||||
JSAPITestString result = a;
|
||||
result += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline JSAPITestString
|
||||
operator+(const JSAPITestString& a, const JSAPITestString& b)
|
||||
{
|
||||
JSAPITestString result = a;
|
||||
result += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
class JSAPITest
|
||||
{
|
||||
@@ -205,7 +219,11 @@ class JSAPITest
|
||||
return fail(JSAPITestString("CHECK failed: " #expr), __FILE__, __LINE__); \
|
||||
} while (false)
|
||||
|
||||
bool fail(JSAPITestString msg = JSAPITestString(), const char* filename = "-", int lineno = 0) {
|
||||
bool fail(const JSAPITestString& msg = JSAPITestString(),
|
||||
const char* filename = "-",
|
||||
int lineno = 0)
|
||||
{
|
||||
JSAPITestString message = msg;
|
||||
if (JS_IsExceptionPending(cx)) {
|
||||
js::gc::AutoSuppressGC gcoff(cx);
|
||||
JS::RootedValue v(cx);
|
||||
@@ -215,11 +233,12 @@ class JSAPITest
|
||||
if (s) {
|
||||
JSAutoByteString bytes(cx, s);
|
||||
if (!!bytes)
|
||||
msg += bytes.ptr();
|
||||
message += bytes.ptr();
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "%s:%d:%.*s\n", filename, lineno, (int) msg.length(), msg.begin());
|
||||
msgs += msg;
|
||||
fprintf(stderr, "%s:%d:%.*s\n",
|
||||
filename, lineno, int(message.length()), message.begin());
|
||||
msgs += message;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+19
-11
@@ -187,11 +187,6 @@ IsMarkingTrace(JSTracer* trc)
|
||||
void
|
||||
RegExpObject::trace(JSTracer* trc)
|
||||
{
|
||||
// When marking the object normally we have the option of unlinking the
|
||||
// object from its RegExpShared so that the RegExpShared may be collected.
|
||||
if (IsMarkingTrace(trc) && !zone()->isPreservingCode())
|
||||
sharedRef() = nullptr;
|
||||
|
||||
TraceNullableEdge(trc, &sharedRef(), "RegExpObject shared");
|
||||
}
|
||||
|
||||
@@ -970,6 +965,9 @@ RegExpShared::discardJitCode()
|
||||
{
|
||||
for (auto& comp : compilationArray)
|
||||
comp.jitCode = nullptr;
|
||||
|
||||
// We can also purge the tables used by JIT code.
|
||||
tables.clearAndFree();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -977,8 +975,6 @@ RegExpShared::finalize(FreeOp* fop)
|
||||
{
|
||||
for (auto& comp : compilationArray)
|
||||
js_free(comp.byteCode);
|
||||
for (size_t i = 0; i < tables.length(); i++)
|
||||
js_free(tables[i]);
|
||||
tables.~JitCodeTables();
|
||||
}
|
||||
|
||||
@@ -1075,6 +1071,7 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
}
|
||||
}
|
||||
|
||||
JitCodeTables tables;
|
||||
irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
|
||||
false /* global() */,
|
||||
re->ignoreCase(),
|
||||
@@ -1082,7 +1079,8 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
mode == MatchOnly,
|
||||
force == ForceByteCode,
|
||||
re->sticky(),
|
||||
re->unicode());
|
||||
re->unicode(),
|
||||
tables);
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
@@ -1090,10 +1088,20 @@ RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pa
|
||||
MOZ_ASSERT_IF(force == ForceByteCode, code.byteCode);
|
||||
|
||||
RegExpCompilation& compilation = re->compilation(mode, input->hasLatin1Chars());
|
||||
if (code.jitCode)
|
||||
if (code.jitCode) {
|
||||
// First copy the tables. GC can purge the tables if the RegExpShared
|
||||
// has no JIT code, so it's important to do this right before setting
|
||||
// compilation.jitCode (to ensure no purging happens between adding the
|
||||
// tables and setting the JIT code).
|
||||
for (size_t i = 0; i < tables.length(); i++) {
|
||||
if (!re->addTable(Move(tables[i])))
|
||||
return false;
|
||||
}
|
||||
compilation.jitCode = code.jitCode;
|
||||
else if (code.byteCode)
|
||||
} else if (code.byteCode) {
|
||||
MOZ_ASSERT(tables.empty(), "RegExpInterpreter does not use data tables");
|
||||
compilation.byteCode = code.byteCode;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1249,7 +1257,7 @@ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
|
||||
n += tables.sizeOfExcludingThis(mallocSizeOf);
|
||||
for (size_t i = 0; i < tables.length(); i++)
|
||||
n += mallocSizeOf(tables[i]);
|
||||
n += mallocSizeOf(tables[i].get());
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -109,6 +109,9 @@ class RegExpShared : public gc::TenuredCell
|
||||
ForceByteCode
|
||||
};
|
||||
|
||||
using JitCodeTable = UniquePtr<uint8_t[], JS::FreePolicy>;
|
||||
using JitCodeTables = Vector<JitCodeTable, 0, SystemAllocPolicy>;
|
||||
|
||||
private:
|
||||
friend class RegExpCompartment;
|
||||
friend class RegExpStatics;
|
||||
@@ -148,7 +151,6 @@ class RegExpShared : public gc::TenuredCell
|
||||
}
|
||||
|
||||
// Tables referenced by JIT code.
|
||||
using JitCodeTables = Vector<uint8_t*, 0, SystemAllocPolicy>;
|
||||
JitCodeTables tables;
|
||||
|
||||
/* Internal functions. */
|
||||
@@ -181,8 +183,8 @@ class RegExpShared : public gc::TenuredCell
|
||||
MatchPairs* matches, size_t* endIndex);
|
||||
|
||||
// Register a table with this RegExpShared, and take ownership.
|
||||
bool addTable(uint8_t* table) {
|
||||
return tables.append(table);
|
||||
bool addTable(JitCodeTable table) {
|
||||
return tables.append(Move(table));
|
||||
}
|
||||
|
||||
/* Accessors */
|
||||
@@ -464,7 +466,7 @@ class RegExpObject : public NativeObject
|
||||
|
||||
void setShared(RegExpShared& shared) {
|
||||
MOZ_ASSERT(!hasShared());
|
||||
sharedRef() = &shared;
|
||||
sharedRef().init(&shared);
|
||||
}
|
||||
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
@@ -490,9 +492,9 @@ class RegExpObject : public NativeObject
|
||||
static MOZ_MUST_USE bool createShared(JSContext* cx, Handle<RegExpObject*> regexp,
|
||||
MutableHandleRegExpShared shared);
|
||||
|
||||
ReadBarriered<RegExpShared*>& sharedRef() {
|
||||
PreBarriered<RegExpShared*>& sharedRef() {
|
||||
auto& ref = NativeObject::privateRef(PRIVATE_SLOT);
|
||||
return reinterpret_cast<ReadBarriered<RegExpShared*>&>(ref);
|
||||
return reinterpret_cast<PreBarriered<RegExpShared*>&>(ref);
|
||||
}
|
||||
|
||||
/* Call setShared in preference to setPrivate. */
|
||||
|
||||
@@ -8137,26 +8137,10 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
|
||||
MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
|
||||
"display:contents nodes shouldn't have a frame");
|
||||
if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
|
||||
nsIContent* ancestor = aChild->GetFlattenedTreeParent();
|
||||
MOZ_ASSERT(ancestor, "display: contents on the root?");
|
||||
while (!ancestor->GetPrimaryFrame()) {
|
||||
ancestor = ancestor->GetFlattenedTreeParent();
|
||||
MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
|
||||
}
|
||||
|
||||
nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
|
||||
if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
|
||||
*aDidReconstruct = true;
|
||||
|
||||
// XXXmats Can we recreate frames only for the ::after/::before content?
|
||||
// XXX Perhaps even only those that belong to the aChild sub-tree?
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
RecreateFramesForContent(ancestor, insertionKind, aFlags);
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
return;
|
||||
}
|
||||
|
||||
FlattenedChildIterator iter(aChild);
|
||||
// NOTE(emilio): We may iterate through ::before and ::after here and they
|
||||
// may be gone after the respective ContentRemoved call. Right now
|
||||
// StyleChildrenIterator handles that properly, so it's not an issue.
|
||||
StyleChildrenIterator iter(aChild);
|
||||
for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
|
||||
if (c->GetPrimaryFrame() || GetDisplayContentsStyleFor(c)) {
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
@@ -8333,8 +8317,13 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
|
||||
NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
|
||||
parentFrame = childFrame->GetParent();
|
||||
}
|
||||
|
||||
RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame), childFrame);
|
||||
|
||||
// NOTE(emilio): aChild could be dead here already if it is a ::before or
|
||||
// ::after pseudo-element (since in that case it was owned by childFrame,
|
||||
// which we just destroyed).
|
||||
|
||||
if (isRoot) {
|
||||
mRootElementFrame = nullptr;
|
||||
mRootElementStyleFrame = nullptr;
|
||||
@@ -8354,8 +8343,7 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
|
||||
// to do this if the table parent type of our parent type is not
|
||||
// eTypeBlock, though, because in that case the whitespace isn't
|
||||
// being suppressed due to us anyway.
|
||||
if (aContainer && !aChild->IsRootOfAnonymousSubtree() &&
|
||||
aFlags == REMOVE_CONTENT &&
|
||||
if (aContainer && aOldNextSibling && aFlags == REMOVE_CONTENT &&
|
||||
GetParentType(parentType) == eTypeBlock) {
|
||||
// Adjacent whitespace-only text nodes might have been suppressed if
|
||||
// this node does not have inline ends. Create frames for them now
|
||||
@@ -8370,17 +8358,15 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
|
||||
//
|
||||
// FIXME(emilio): This should probably use the lazy frame construction
|
||||
// bits if possible instead of reframing it in place.
|
||||
if (aOldNextSibling) {
|
||||
nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
|
||||
if (prevSibling && prevSibling->GetPreviousSibling()) {
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
ReframeTextIfNeeded(aContainer, prevSibling);
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
}
|
||||
nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
|
||||
if (prevSibling && prevSibling->GetPreviousSibling()) {
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
ReframeTextIfNeeded(aContainer, prevSibling);
|
||||
LAYOUT_PHASE_TEMP_REENTER();
|
||||
}
|
||||
// Reframe any text node just after the node being removed, if there is
|
||||
// one, and if it's not the last child or the first child.
|
||||
if (aOldNextSibling && aOldNextSibling->GetNextSibling() &&
|
||||
if (aOldNextSibling->GetNextSibling() &&
|
||||
aOldNextSibling->GetPreviousSibling()) {
|
||||
LAYOUT_PHASE_TEMP_EXIT();
|
||||
ReframeTextIfNeeded(aContainer, aOldNextSibling);
|
||||
|
||||
+175
-103
@@ -146,7 +146,7 @@ struct VectorImpl
|
||||
aV.free_(aV.mBegin);
|
||||
aV.mBegin = newbuf;
|
||||
/* aV.mLength is unchanged. */
|
||||
aV.mCapacity = aNewCap;
|
||||
aV.mTail.mCapacity = aNewCap;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -225,28 +225,30 @@ struct VectorImpl<T, N, AP, true>
|
||||
{
|
||||
MOZ_ASSERT(!aV.usingInlineStorage());
|
||||
MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
|
||||
T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aNewCap);
|
||||
T* newbuf =
|
||||
aV.template pod_realloc<T>(aV.mBegin, aV.mTail.mCapacity, aNewCap);
|
||||
if (MOZ_UNLIKELY(!newbuf)) {
|
||||
return false;
|
||||
}
|
||||
aV.mBegin = newbuf;
|
||||
/* aV.mLength is unchanged. */
|
||||
aV.mCapacity = aNewCap;
|
||||
aV.mTail.mCapacity = aNewCap;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
podResizeToFit(Vector<T, N, AP>& aV)
|
||||
{
|
||||
if (aV.usingInlineStorage() || aV.mLength == aV.mCapacity) {
|
||||
if (aV.usingInlineStorage() || aV.mLength == aV.mTail.mCapacity) {
|
||||
return;
|
||||
}
|
||||
T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aV.mLength);
|
||||
T* newbuf =
|
||||
aV.template pod_realloc<T>(aV.mBegin, aV.mTail.mCapacity, aV.mLength);
|
||||
if (MOZ_UNLIKELY(!newbuf)) {
|
||||
return;
|
||||
}
|
||||
aV.mBegin = newbuf;
|
||||
aV.mCapacity = aV.mLength;
|
||||
aV.mTail.mCapacity = aV.mLength;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -277,7 +279,7 @@ struct VectorTesting;
|
||||
template<typename T,
|
||||
size_t MinInlineCapacity = 0,
|
||||
class AllocPolicy = MallocAllocPolicy>
|
||||
class Vector final : private AllocPolicy
|
||||
class MOZ_NON_PARAM Vector final : private AllocPolicy
|
||||
{
|
||||
/* utilities */
|
||||
|
||||
@@ -293,36 +295,39 @@ class Vector final : private AllocPolicy
|
||||
|
||||
/* magic constants */
|
||||
|
||||
static const int kMaxInlineBytes = 1024;
|
||||
|
||||
/* compute constants */
|
||||
|
||||
/*
|
||||
* Consider element size to be 1 for buffer sizing if there are 0 inline
|
||||
* elements. This allows us to compile when the definition of the element
|
||||
* type is not visible here.
|
||||
/**
|
||||
* The maximum space allocated for inline element storage.
|
||||
*
|
||||
* Explicit specialization is only allowed at namespace scope, so in order
|
||||
* to keep everything here, we use a dummy template parameter with partial
|
||||
* specialization.
|
||||
* We reduce space by what the AllocPolicy base class and prior Vector member
|
||||
* fields likely consume to attempt to play well with binary size classes.
|
||||
*/
|
||||
template<int M, int Dummy>
|
||||
struct ElemSize
|
||||
{
|
||||
static const size_t value = sizeof(T);
|
||||
};
|
||||
template<int Dummy>
|
||||
struct ElemSize<0, Dummy>
|
||||
{
|
||||
static const size_t value = 1;
|
||||
static constexpr size_t kMaxInlineBytes =
|
||||
1024 -
|
||||
(sizeof(AllocPolicy) + sizeof(T*) + sizeof(size_t) + sizeof(size_t));
|
||||
|
||||
/**
|
||||
* The number of T elements of inline capacity built into this Vector. This
|
||||
* is usually |MinInlineCapacity|, but it may be less (or zero!) for large T.
|
||||
*
|
||||
* We use a partially-specialized template (not explicit specialization, which
|
||||
* is only allowed at namespace scope) to compute this value. The benefit is
|
||||
* that |sizeof(T)| need not be computed, and |T| doesn't have to be fully
|
||||
* defined at the time |Vector<T>| appears, if no inline storage is requested.
|
||||
*/
|
||||
template <size_t MinimumInlineCapacity, size_t Dummy>
|
||||
struct ComputeCapacity {
|
||||
static constexpr size_t value =
|
||||
tl::Min<MinimumInlineCapacity, kMaxInlineBytes / sizeof(T)>::value;
|
||||
};
|
||||
|
||||
static const size_t kInlineCapacity =
|
||||
tl::Min<MinInlineCapacity, kMaxInlineBytes / ElemSize<MinInlineCapacity, 0>::value>::value;
|
||||
template <size_t Dummy>
|
||||
struct ComputeCapacity<0, Dummy> {
|
||||
static constexpr size_t value = 0;
|
||||
};
|
||||
|
||||
/* Calculate inline buffer size; avoid 0-sized array. */
|
||||
static const size_t kInlineBytes =
|
||||
tl::Max<1, kInlineCapacity * ElemSize<MinInlineCapacity, 0>::value>::value;
|
||||
/** The actual inline capacity in number of elements T. This may be zero! */
|
||||
static constexpr size_t kInlineCapacity =
|
||||
ComputeCapacity<MinInlineCapacity, 0>::value;
|
||||
|
||||
/* member data */
|
||||
|
||||
@@ -338,16 +343,84 @@ class Vector final : private AllocPolicy
|
||||
/* Number of elements in the vector. */
|
||||
size_t mLength;
|
||||
|
||||
/* Max number of elements storable in the vector without resizing. */
|
||||
size_t mCapacity;
|
||||
/*
|
||||
* Memory used to store capacity, reserved element count (debug builds only),
|
||||
* and inline storage. The simple "answer" is:
|
||||
*
|
||||
* size_t mCapacity;
|
||||
* #ifdef DEBUG
|
||||
* size_t mReserved;
|
||||
* #endif
|
||||
* alignas(T) unsigned char mBytes[kInlineCapacity * sizeof(T)];
|
||||
*
|
||||
* but there are complications. First, C++ forbids zero-sized arrays that
|
||||
* might result. Second, we don't want zero capacity to affect Vector's size
|
||||
* (even empty classes take up a byte, unless they're base classes).
|
||||
*
|
||||
* Yet again, we eliminate the zero-sized array using partial specialization.
|
||||
* And we eliminate potential size hit by putting capacity/reserved in one
|
||||
* struct, then putting the array (if any) in a derived struct. If no array
|
||||
* is needed, the derived struct won't consume extra space.
|
||||
*/
|
||||
struct CapacityAndReserved
|
||||
{
|
||||
explicit CapacityAndReserved(size_t aCapacity, size_t aReserved)
|
||||
: mCapacity(aCapacity)
|
||||
#ifdef DEBUG
|
||||
, mReserved(aReserved)
|
||||
#endif
|
||||
{}
|
||||
CapacityAndReserved() = default;
|
||||
|
||||
/* Max number of elements storable in the vector without resizing. */
|
||||
size_t mCapacity;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Max elements of reserved or used space in this vector. */
|
||||
size_t mReserved;
|
||||
/* Max elements of reserved or used space in this vector. */
|
||||
size_t mReserved;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Memory used for inline storage. */
|
||||
AlignedStorage<kInlineBytes> mStorage;
|
||||
// Silence warnings about this struct possibly being padded dued to the
|
||||
// alignas() in it -- there's nothing we can do to avoid it.
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4324)
|
||||
#endif // _MSC_VER
|
||||
|
||||
template<size_t Capacity, size_t Dummy>
|
||||
struct CRAndStorage : CapacityAndReserved
|
||||
{
|
||||
explicit CRAndStorage(size_t aCapacity, size_t aReserved)
|
||||
: CapacityAndReserved(aCapacity, aReserved)
|
||||
{}
|
||||
CRAndStorage() = default;
|
||||
|
||||
alignas(T) unsigned char mBytes[Capacity * sizeof(T)];
|
||||
|
||||
// GCC fails due to -Werror=strict-aliasing if |mBytes| is directly cast to
|
||||
// T*. Indirecting through this function addresses the problem.
|
||||
void* data() { return mBytes; }
|
||||
|
||||
T* storage() { return static_cast<T*>(data()); }
|
||||
};
|
||||
|
||||
template<size_t Dummy>
|
||||
struct CRAndStorage<0, Dummy> : CapacityAndReserved
|
||||
{
|
||||
explicit CRAndStorage(size_t aCapacity, size_t aReserved)
|
||||
: CapacityAndReserved(aCapacity, aReserved)
|
||||
{}
|
||||
CRAndStorage() = default;
|
||||
|
||||
T* storage() { return nullptr; }
|
||||
};
|
||||
|
||||
CRAndStorage<kInlineCapacity, 0> mTail;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef DEBUG
|
||||
friend class ReentrancyGuard;
|
||||
@@ -363,7 +436,7 @@ class Vector final : private AllocPolicy
|
||||
|
||||
T* inlineStorage()
|
||||
{
|
||||
return static_cast<T*>(mStorage.addr());
|
||||
return mTail.storage();
|
||||
}
|
||||
|
||||
T* beginNoCheck() const
|
||||
@@ -391,9 +464,9 @@ class Vector final : private AllocPolicy
|
||||
*/
|
||||
size_t reserved() const
|
||||
{
|
||||
MOZ_ASSERT(mLength <= mReserved);
|
||||
MOZ_ASSERT(mReserved <= mCapacity);
|
||||
return mReserved;
|
||||
MOZ_ASSERT(mLength <= mTail.mReserved);
|
||||
MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
|
||||
return mTail.mReserved;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -426,7 +499,7 @@ public:
|
||||
|
||||
bool empty() const { return mLength == 0; }
|
||||
|
||||
size_t capacity() const { return mCapacity; }
|
||||
size_t capacity() const { return mTail.mCapacity; }
|
||||
|
||||
T* begin()
|
||||
{
|
||||
@@ -753,10 +826,10 @@ private:
|
||||
/* This does the re-entrancy check plus several other sanity checks. */
|
||||
#define MOZ_REENTRANCY_GUARD_ET_AL \
|
||||
ReentrancyGuard g(*this); \
|
||||
MOZ_ASSERT_IF(usingInlineStorage(), mCapacity == kInlineCapacity); \
|
||||
MOZ_ASSERT(reserved() <= mCapacity); \
|
||||
MOZ_ASSERT_IF(usingInlineStorage(), mTail.mCapacity == kInlineCapacity); \
|
||||
MOZ_ASSERT(reserved() <= mTail.mCapacity); \
|
||||
MOZ_ASSERT(mLength <= reserved()); \
|
||||
MOZ_ASSERT(mLength <= mCapacity)
|
||||
MOZ_ASSERT(mLength <= mTail.mCapacity)
|
||||
|
||||
/* Vector Implementation */
|
||||
|
||||
@@ -765,13 +838,12 @@ MOZ_ALWAYS_INLINE
|
||||
Vector<T, N, AP>::Vector(AP aAP)
|
||||
: AP(aAP)
|
||||
, mLength(0)
|
||||
, mCapacity(kInlineCapacity)
|
||||
, mTail(kInlineCapacity, 0)
|
||||
#ifdef DEBUG
|
||||
, mReserved(0)
|
||||
, mEntered(false)
|
||||
#endif
|
||||
{
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mBegin = inlineStorage();
|
||||
}
|
||||
|
||||
/* Move constructor. */
|
||||
@@ -784,14 +856,14 @@ Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
|
||||
#endif
|
||||
{
|
||||
mLength = aRhs.mLength;
|
||||
mCapacity = aRhs.mCapacity;
|
||||
mTail.mCapacity = aRhs.mTail.mCapacity;
|
||||
#ifdef DEBUG
|
||||
mReserved = aRhs.mReserved;
|
||||
mTail.mReserved = aRhs.mTail.mReserved;
|
||||
#endif
|
||||
|
||||
if (aRhs.usingInlineStorage()) {
|
||||
/* We can't move the buffer over in this case, so copy elements. */
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mBegin = inlineStorage();
|
||||
Impl::moveConstruct(mBegin, aRhs.beginNoCheck(), aRhs.endNoCheck());
|
||||
/*
|
||||
* Leave aRhs's mLength, mBegin, mCapacity, and mReserved as they are.
|
||||
@@ -803,11 +875,11 @@ Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
|
||||
* in-line storage.
|
||||
*/
|
||||
mBegin = aRhs.mBegin;
|
||||
aRhs.mBegin = static_cast<T*>(aRhs.mStorage.addr());
|
||||
aRhs.mCapacity = kInlineCapacity;
|
||||
aRhs.mBegin = aRhs.inlineStorage();
|
||||
aRhs.mTail.mCapacity = kInlineCapacity;
|
||||
aRhs.mLength = 0;
|
||||
#ifdef DEBUG
|
||||
aRhs.mReserved = 0;
|
||||
aRhs.mTail.mReserved = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -871,7 +943,7 @@ Vector<T, N, AP>::convertToHeapStorage(size_t aNewCap)
|
||||
/* Switch in heap buffer. */
|
||||
mBegin = newBuf;
|
||||
/* mLength is unchanged. */
|
||||
mCapacity = aNewCap;
|
||||
mTail.mCapacity = aNewCap;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -879,7 +951,7 @@ template<typename T, size_t N, class AP>
|
||||
MOZ_NEVER_INLINE bool
|
||||
Vector<T, N, AP>::growStorageBy(size_t aIncr)
|
||||
{
|
||||
MOZ_ASSERT(mLength + aIncr > mCapacity);
|
||||
MOZ_ASSERT(mLength + aIncr > mTail.mCapacity);
|
||||
|
||||
/*
|
||||
* When choosing a new capacity, its size should is as close to 2**N bytes
|
||||
@@ -971,9 +1043,9 @@ Vector<T, N, AP>::initCapacity(size_t aRequest)
|
||||
return false;
|
||||
}
|
||||
mBegin = newbuf;
|
||||
mCapacity = aRequest;
|
||||
mTail.mCapacity = aRequest;
|
||||
#ifdef DEBUG
|
||||
mReserved = aRequest;
|
||||
mTail.mReserved = aRequest;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -998,7 +1070,7 @@ Vector<T, N, AP>::maybeCheckSimulatedOOM(size_t aRequestedSize)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (aRequestedSize <= mReserved) {
|
||||
if (aRequestedSize <= mTail.mReserved) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -1011,7 +1083,7 @@ inline bool
|
||||
Vector<T, N, AP>::reserve(size_t aRequest)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
if (aRequest > mCapacity) {
|
||||
if (aRequest > mTail.mCapacity) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(aRequest - mLength))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1019,11 +1091,11 @@ Vector<T, N, AP>::reserve(size_t aRequest)
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (aRequest > mReserved) {
|
||||
mReserved = aRequest;
|
||||
if (aRequest > mTail.mReserved) {
|
||||
mTail.mReserved = aRequest;
|
||||
}
|
||||
MOZ_ASSERT(mLength <= mReserved);
|
||||
MOZ_ASSERT(mReserved <= mCapacity);
|
||||
MOZ_ASSERT(mLength <= mTail.mReserved);
|
||||
MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -1051,20 +1123,20 @@ MOZ_ALWAYS_INLINE bool
|
||||
Vector<T, N, AP>::growBy(size_t aIncr)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
if (aIncr > mCapacity - mLength) {
|
||||
if (aIncr > mTail.mCapacity - mLength) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
|
||||
return false;
|
||||
}
|
||||
} else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(mLength + aIncr <= mCapacity);
|
||||
MOZ_ASSERT(mLength + aIncr <= mTail.mCapacity);
|
||||
T* newend = endNoCheck() + aIncr;
|
||||
Impl::initialize(endNoCheck(), newend);
|
||||
mLength += aIncr;
|
||||
#ifdef DEBUG
|
||||
if (mLength > mReserved) {
|
||||
mReserved = mLength;
|
||||
if (mLength > mTail.mReserved) {
|
||||
mTail.mReserved = mLength;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
@@ -1075,7 +1147,7 @@ MOZ_ALWAYS_INLINE bool
|
||||
Vector<T, N, AP>::growByUninitialized(size_t aIncr)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
if (aIncr > mCapacity - mLength) {
|
||||
if (aIncr > mTail.mCapacity - mLength) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1083,8 +1155,8 @@ Vector<T, N, AP>::growByUninitialized(size_t aIncr)
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (mLength + aIncr > mReserved) {
|
||||
mReserved = mLength + aIncr;
|
||||
if (mLength + aIncr > mTail.mReserved) {
|
||||
mTail.mReserved = mLength + aIncr;
|
||||
}
|
||||
#endif
|
||||
infallibleGrowByUninitialized(aIncr);
|
||||
@@ -1142,10 +1214,10 @@ Vector<T, N, AP>::clearAndFree()
|
||||
return;
|
||||
}
|
||||
this->free_(beginNoCheck());
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mCapacity = kInlineCapacity;
|
||||
mBegin = inlineStorage();
|
||||
mTail.mCapacity = kInlineCapacity;
|
||||
#ifdef DEBUG
|
||||
mReserved = 0;
|
||||
mTail.mReserved = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1162,7 +1234,7 @@ template<typename T, size_t N, class AP>
|
||||
inline bool
|
||||
Vector<T, N, AP>::canAppendWithoutRealloc(size_t aNeeded) const
|
||||
{
|
||||
return mLength + aNeeded <= mCapacity;
|
||||
return mLength + aNeeded <= mTail.mCapacity;
|
||||
}
|
||||
|
||||
template<typename T, size_t N, class AP>
|
||||
@@ -1178,8 +1250,8 @@ template<typename U>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
Vector<T, N, AP>::internalAppend(U&& aU)
|
||||
{
|
||||
MOZ_ASSERT(mLength + 1 <= mReserved);
|
||||
MOZ_ASSERT(mReserved <= mCapacity);
|
||||
MOZ_ASSERT(mLength + 1 <= mTail.mReserved);
|
||||
MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
|
||||
Impl::new_(endNoCheck(), Forward<U>(aU));
|
||||
++mLength;
|
||||
}
|
||||
@@ -1189,7 +1261,7 @@ MOZ_ALWAYS_INLINE bool
|
||||
Vector<T, N, AP>::appendN(const T& aT, size_t aNeeded)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
if (mLength + aNeeded > mCapacity) {
|
||||
if (mLength + aNeeded > mTail.mCapacity) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1197,8 +1269,8 @@ Vector<T, N, AP>::appendN(const T& aT, size_t aNeeded)
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (mLength + aNeeded > mReserved) {
|
||||
mReserved = mLength + aNeeded;
|
||||
if (mLength + aNeeded > mTail.mReserved) {
|
||||
mTail.mReserved = mLength + aNeeded;
|
||||
}
|
||||
#endif
|
||||
internalAppendN(aT, aNeeded);
|
||||
@@ -1209,8 +1281,8 @@ template<typename T, size_t N, class AP>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
Vector<T, N, AP>::internalAppendN(const T& aT, size_t aNeeded)
|
||||
{
|
||||
MOZ_ASSERT(mLength + aNeeded <= mReserved);
|
||||
MOZ_ASSERT(mReserved <= mCapacity);
|
||||
MOZ_ASSERT(mLength + aNeeded <= mTail.mReserved);
|
||||
MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
|
||||
Impl::copyConstructN(endNoCheck(), aNeeded, aT);
|
||||
mLength += aNeeded;
|
||||
}
|
||||
@@ -1275,7 +1347,7 @@ Vector<T, N, AP>::append(const U* aInsBegin, const U* aInsEnd)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
size_t aNeeded = PointerRangeSize(aInsBegin, aInsEnd);
|
||||
if (mLength + aNeeded > mCapacity) {
|
||||
if (mLength + aNeeded > mTail.mCapacity) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1283,8 +1355,8 @@ Vector<T, N, AP>::append(const U* aInsBegin, const U* aInsEnd)
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (mLength + aNeeded > mReserved) {
|
||||
mReserved = mLength + aNeeded;
|
||||
if (mLength + aNeeded > mTail.mReserved) {
|
||||
mTail.mReserved = mLength + aNeeded;
|
||||
}
|
||||
#endif
|
||||
internalAppend(aInsBegin, aNeeded);
|
||||
@@ -1296,8 +1368,8 @@ template<typename U>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
Vector<T, N, AP>::internalAppend(const U* aInsBegin, size_t aInsLength)
|
||||
{
|
||||
MOZ_ASSERT(mLength + aInsLength <= mReserved);
|
||||
MOZ_ASSERT(mReserved <= mCapacity);
|
||||
MOZ_ASSERT(mLength + aInsLength <= mTail.mReserved);
|
||||
MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
|
||||
Impl::copyConstruct(endNoCheck(), aInsBegin, aInsBegin + aInsLength);
|
||||
mLength += aInsLength;
|
||||
}
|
||||
@@ -1308,7 +1380,7 @@ MOZ_ALWAYS_INLINE bool
|
||||
Vector<T, N, AP>::append(U&& aU)
|
||||
{
|
||||
MOZ_REENTRANCY_GUARD_ET_AL;
|
||||
if (mLength == mCapacity) {
|
||||
if (mLength == mTail.mCapacity) {
|
||||
if (MOZ_UNLIKELY(!growStorageBy(1))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1316,8 +1388,8 @@ Vector<T, N, AP>::append(U&& aU)
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (mLength + 1 > mReserved) {
|
||||
mReserved = mLength + 1;
|
||||
if (mLength + 1 > mTail.mReserved) {
|
||||
mTail.mReserved = mLength + 1;
|
||||
}
|
||||
#endif
|
||||
internalAppend(Forward<U>(aU));
|
||||
@@ -1370,11 +1442,11 @@ Vector<T, N, AP>::extractRawBuffer()
|
||||
}
|
||||
|
||||
T* ret = mBegin;
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mBegin = inlineStorage();
|
||||
mLength = 0;
|
||||
mCapacity = kInlineCapacity;
|
||||
mTail.mCapacity = kInlineCapacity;
|
||||
#ifdef DEBUG
|
||||
mReserved = 0;
|
||||
mTail.mReserved = 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -1396,11 +1468,11 @@ Vector<T, N, AP>::extractOrCopyRawBuffer()
|
||||
|
||||
Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
|
||||
Impl::destroy(beginNoCheck(), endNoCheck());
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mBegin = inlineStorage();
|
||||
mLength = 0;
|
||||
mCapacity = kInlineCapacity;
|
||||
mTail.mCapacity = kInlineCapacity;
|
||||
#ifdef DEBUG
|
||||
mReserved = 0;
|
||||
mTail.mReserved = 0;
|
||||
#endif
|
||||
return copy;
|
||||
}
|
||||
@@ -1424,19 +1496,19 @@ Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
|
||||
* otherwise be acceptable. Maybe this behaviour should be
|
||||
* specifiable with an argument to this function.
|
||||
*/
|
||||
mBegin = static_cast<T*>(mStorage.addr());
|
||||
mBegin = inlineStorage();
|
||||
mLength = aLength;
|
||||
mCapacity = kInlineCapacity;
|
||||
mTail.mCapacity = kInlineCapacity;
|
||||
Impl::moveConstruct(mBegin, aP, aP + aLength);
|
||||
Impl::destroy(aP, aP + aLength);
|
||||
this->free_(aP);
|
||||
} else {
|
||||
mBegin = aP;
|
||||
mLength = aLength;
|
||||
mCapacity = aLength;
|
||||
mTail.mCapacity = aLength;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
mReserved = aLength;
|
||||
mTail.mReserved = aLength;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1475,9 +1547,9 @@ Vector<T, N, AP>::swap(Vector& aOther)
|
||||
}
|
||||
|
||||
Swap(mLength, aOther.mLength);
|
||||
Swap(mCapacity, aOther.mCapacity);
|
||||
Swap(mTail.mCapacity, aOther.mTail.mCapacity);
|
||||
#ifdef DEBUG
|
||||
Swap(mReserved, aOther.mReserved);
|
||||
Swap(mTail.mReserved, aOther.mTail.mReserved);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -396,6 +396,49 @@ mozilla::detail::VectorTesting::testInsert()
|
||||
MOZ_RELEASE_ASSERT(S::destructCount == 1);
|
||||
}
|
||||
|
||||
// Declare but leave (permanently) incomplete.
|
||||
struct Incomplete;
|
||||
|
||||
// We could even *construct* a Vector<Incomplete, 0> if we wanted. But we can't
|
||||
// destruct it, so it's not worth the trouble.
|
||||
static_assert(sizeof(Vector<Incomplete, 0>) > 0,
|
||||
"Vector of an incomplete type will compile");
|
||||
|
||||
// Vector with no inline storage should occupy the absolute minimum space in
|
||||
// non-debug builds. (Debug adds a laundry list of other constraints, none
|
||||
// directly relevant to shipping builds, that aren't worth precisely modeling.)
|
||||
#ifndef DEBUG
|
||||
|
||||
template<typename T>
|
||||
struct NoInlineStorageLayout
|
||||
{
|
||||
T* mBegin;
|
||||
size_t mLength;
|
||||
struct CRAndStorage {
|
||||
size_t mCapacity;
|
||||
} mTail;
|
||||
};
|
||||
|
||||
// Only one of these should be necessary, but test a few of them for good
|
||||
// measure.
|
||||
static_assert(sizeof(Vector<int, 0>) == sizeof(NoInlineStorageLayout<int>),
|
||||
"Vector of int without inline storage shouldn't occupy dead "
|
||||
"space for that absence of storage");
|
||||
|
||||
static_assert(sizeof(Vector<bool, 0>) == sizeof(NoInlineStorageLayout<bool>),
|
||||
"Vector of bool without inline storage shouldn't occupy dead "
|
||||
"space for that absence of storage");
|
||||
|
||||
static_assert(sizeof(Vector<S, 0>) == sizeof(NoInlineStorageLayout<S>),
|
||||
"Vector of S without inline storage shouldn't occupy dead "
|
||||
"space for that absence of storage");
|
||||
|
||||
static_assert(sizeof(Vector<Incomplete, 0>) == sizeof(NoInlineStorageLayout<Incomplete>),
|
||||
"Vector of an incomplete class without inline storage shouldn't "
|
||||
"occupy dead space for that absence of storage");
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
@@ -118,6 +118,15 @@ pref("security.ssl.enable_ocsp_must_staple", true);
|
||||
// Restart required.
|
||||
pref("security.ssl.enable_tls13_compat_mode", false);
|
||||
|
||||
// Enable TLS 1.3 hello downgrade sentinel?
|
||||
// One of the key protections offered by TLS 1.3 is preventing protocol downgrades
|
||||
// as part of the initial handshake.
|
||||
// Some domains, middleware and transparent routers may try to downgrade connections
|
||||
// this way (which is a bad thing!). To allow users to connect anyway this
|
||||
// check can be disabled here. Default is for the sentinel to be enabled, preventing
|
||||
// bad downgrades of the protocol version.
|
||||
pref("security.tls.hello_downgrade_check", true);
|
||||
|
||||
// If a request is mixed-content, send an HSTS priming request to attempt to
|
||||
// see if it is available over HTTPS.
|
||||
pref("security.mixed_content.send_hsts_priming", true);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9c9252a1-fdaf-40a2-9c2b-a3dc45e28dde)]
|
||||
[scriptable, uuid(6e8476d5-ba95-4fee-85d9-f96729b387d8)]
|
||||
interface nsIMIMEHeaderParam : nsISupports {
|
||||
|
||||
/**
|
||||
@@ -132,7 +132,7 @@ interface nsIMIMEHeaderParam : nsISupports {
|
||||
*/
|
||||
|
||||
[noscript]
|
||||
string getParameterInternal(in string aHeaderVal,
|
||||
string getParameterInternal(in ACString aHeaderVal,
|
||||
in string aParamName,
|
||||
out string aCharset,
|
||||
out string aLang);
|
||||
|
||||
@@ -65,6 +65,28 @@ nsMIMEHeaderParamImpl::GetParameterHTTP(const nsACString& aHeaderVal,
|
||||
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
// Detects the presence of any non-null characters past null in a header.
|
||||
bool
|
||||
nsMIMEHeaderParamImpl::ContainsTrailingCharPastNull(const nsACString& aVal) {
|
||||
nsACString::const_iterator first;
|
||||
aVal.BeginReading(first);
|
||||
nsACString::const_iterator end;
|
||||
aVal.EndReading(end);
|
||||
|
||||
if (FindCharInReadable(L'\0', first, end)) {
|
||||
while (first != end) {
|
||||
if (*first != '\0') {
|
||||
// Header contains trailing characters past the null character
|
||||
return true;
|
||||
}
|
||||
++first;
|
||||
}
|
||||
}
|
||||
// No stray non-null characters found.
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX : aTryLocaleCharset is not yet effective.
|
||||
nsresult
|
||||
nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal,
|
||||
@@ -81,9 +103,8 @@ nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal,
|
||||
// aDecoding (5987 being a subset of 2231) and return charset.)
|
||||
nsXPIDLCString med;
|
||||
nsXPIDLCString charset;
|
||||
rv = DoParameterInternal(PromiseFlatCString(aHeaderVal).get(), aParamName,
|
||||
aDecoding, getter_Copies(charset), aLang,
|
||||
getter_Copies(med));
|
||||
rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding,
|
||||
getter_Copies(charset), aLang, getter_Copies(med));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@@ -346,11 +367,11 @@ bool IsValidOctetSequenceForCharset(nsACString& aCharset, const char *aOctets)
|
||||
// The format of these header lines is
|
||||
// <token> [ ';' <token> '=' <token-or-quoted-string> ]*
|
||||
NS_IMETHODIMP
|
||||
nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
|
||||
const char *aParamName,
|
||||
char **aCharset,
|
||||
char **aLang,
|
||||
char **aResult)
|
||||
nsMIMEHeaderParamImpl::GetParameterInternal(const nsACString& aHeaderValue,
|
||||
const char* aParamName,
|
||||
char** aCharset,
|
||||
char** aLang,
|
||||
char** aResult)
|
||||
{
|
||||
return DoParameterInternal(aHeaderValue, aParamName, MIME_FIELD_ENCODING,
|
||||
aCharset, aLang, aResult);
|
||||
@@ -358,16 +379,29 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const char *aHeaderValue,
|
||||
|
||||
|
||||
nsresult
|
||||
nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
||||
const char *aParamName,
|
||||
nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
||||
const char* aParamName,
|
||||
ParamDecoding aDecoding,
|
||||
char **aCharset,
|
||||
char **aLang,
|
||||
char **aResult)
|
||||
char** aCharset,
|
||||
char** aLang,
|
||||
char** aResult)
|
||||
{
|
||||
|
||||
if (!aHeaderValue || !*aHeaderValue || !aResult)
|
||||
if (aHeaderValue.IsEmpty() || !aResult) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (ContainsTrailingCharPastNull(aHeaderValue)) {
|
||||
// See Bug 1784348
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const nsCString& flat = PromiseFlatCString(aHeaderValue);
|
||||
const char* str = flat.get();
|
||||
|
||||
if (!*str) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
|
||||
@@ -380,8 +414,6 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const char *aHeaderValue,
|
||||
// them for HTTP header fields later on, see bug 776324
|
||||
bool acceptContinuations = true;
|
||||
|
||||
const char *str = aHeaderValue;
|
||||
|
||||
// skip leading white space.
|
||||
for (; *str && nsCRT::IsAsciiSpace(*str); ++str)
|
||||
;
|
||||
|
||||
@@ -29,13 +29,14 @@ private:
|
||||
char **aLang,
|
||||
nsAString& aResult);
|
||||
|
||||
nsresult DoParameterInternal(const char *aHeaderValue,
|
||||
const char *aParamName,
|
||||
nsresult DoParameterInternal(const nsACString& aHeaderValue,
|
||||
const char* aParamName,
|
||||
ParamDecoding aDecoding,
|
||||
char **aCharset,
|
||||
char **aLang,
|
||||
char **aResult);
|
||||
|
||||
char** aCharset,
|
||||
char** aLang,
|
||||
char** aResult);
|
||||
|
||||
static bool ContainsTrailingCharPastNull(const nsACString& aVal);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -432,6 +432,16 @@ var tests = [
|
||||
// Bug 783502 - xpcshell test netwerk/test/unit/test_MIME_params.js fails on AddressSanitizer
|
||||
['attachment; filename="\\b\\a\\',
|
||||
"attachment", "ba\\"],
|
||||
|
||||
// Bug 1784348
|
||||
["attachment; filename=foo.exe\0.pdf",
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE,
|
||||
Cr.NS_ERROR_INVALID_ARG],
|
||||
["attachment; filename=\0\0foo\0",
|
||||
Cr.NS_ERROR_ILLEGAL_VALUE,
|
||||
Cr.NS_ERROR_INVALID_ARG],
|
||||
["attachment; filename=foo\0\0\0", "attachment", "foo"],
|
||||
["attachment; filename=\0\0\0", "attachment", ""],
|
||||
];
|
||||
|
||||
var rfc5987paramtests = [
|
||||
|
||||
@@ -4742,6 +4742,16 @@ fi
|
||||
AC_DEFINE_UNQUOTED(MOZ_MACBUNDLE_ID,$MOZ_MACBUNDLE_ID)
|
||||
AC_SUBST(MOZ_MACBUNDLE_ID)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Mac bundle codesign identity
|
||||
dnl ========================================================
|
||||
MOZ_ARG_WITH_STRING(macbundle-identity,
|
||||
[ --with-macbundle-identity=identity
|
||||
Identity to codesign the Mac application bundle],
|
||||
[ MOZ_MACBUNDLE_IDENTITY="$withval"])
|
||||
|
||||
AC_SUBST(MOZ_MACBUNDLE_IDENTITY)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Child Process Name for IPC
|
||||
dnl ========================================================
|
||||
|
||||
@@ -102,6 +102,7 @@ def create_dmg(source_directory, output_dmg, volume_name, extra_files):
|
||||
if is_linux:
|
||||
check_tools('DMG_TOOL', 'GENISOIMAGE')
|
||||
with mozfile.TemporaryDirectory() as tmpdir:
|
||||
import buildconfig
|
||||
stagedir = os.path.join(tmpdir, 'stage')
|
||||
os.mkdir(stagedir)
|
||||
# Copy the app bundle over using rsync
|
||||
@@ -118,4 +119,9 @@ def create_dmg(source_directory, output_dmg, volume_name, extra_files):
|
||||
# Set the folder attributes to use a custom icon
|
||||
set_folder_icon(stagedir)
|
||||
chmod(stagedir)
|
||||
if not is_linux:
|
||||
identity = buildconfig.substs['MOZ_MACBUNDLE_IDENTITY']
|
||||
if identity != '':
|
||||
appbundle = os.path.join(stagedir, buildconfig.substs['MOZ_MACBUNDLE_NAME'])
|
||||
subprocess.check_call(['codesign', '--deep', '-s', identity, appbundle])
|
||||
create_dmg_from_staged(stagedir, output_dmg, tmpdir, volume_name)
|
||||
@@ -172,10 +172,17 @@ CTLogVerifier::Verify(const LogEntry& entry,
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// sct.extensions may be empty. If it is, sctExtensionsInput will remain in
|
||||
// its default state, which is valid but of length 0.
|
||||
Input sctExtensionsInput;
|
||||
rv = BufferToInput(sct.extensions, sctExtensionsInput);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
if (sct.extensions.length() > 0) {
|
||||
rv = sctExtensionsInput.Init(sct.extensions.begin(),
|
||||
sct.extensions.length());
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer serializedData;
|
||||
|
||||
@@ -115,6 +115,9 @@ struct SignedCertificateTimestamp
|
||||
|
||||
inline pkix::Result BufferToInput(const Buffer& buffer, pkix::Input& input)
|
||||
{
|
||||
if (buffer.length() == 0) {
|
||||
return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||
}
|
||||
return input.Init(buffer.begin(), buffer.length());
|
||||
}
|
||||
|
||||
|
||||
@@ -1440,6 +1440,7 @@ static const bool NPN_ENABLED_DEFAULT = true;
|
||||
static const bool ALPN_ENABLED_DEFAULT = false;
|
||||
static const bool ENABLED_0RTT_DATA_DEFAULT = false;
|
||||
static const bool TLS13_COMPAT_MODE_DEFAULT = false;
|
||||
static const bool HELLO_DOWNGRADE_CHECK_DEFAULT = true;
|
||||
|
||||
static void
|
||||
ConfigureTLSSessionIdentifiers()
|
||||
@@ -1854,6 +1855,12 @@ nsNSSComponent::InitializeNSS()
|
||||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_EXTENDED_MASTER_SECRET, true);
|
||||
|
||||
// Set TLS 1.3 hello downgrade sentinel?
|
||||
bool enableDowngradeCheck =
|
||||
Preferences::GetBool("security.tls.hello_downgrade_check",
|
||||
HELLO_DOWNGRADE_CHECK_DEFAULT);
|
||||
SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, enableDowngradeCheck);
|
||||
|
||||
SSL_OptionSetDefault(SSL_ENABLE_FALSE_START,
|
||||
Preferences::GetBool("security.ssl.enable_false_start",
|
||||
FALSE_START_ENABLED_DEFAULT));
|
||||
@@ -1877,6 +1884,7 @@ nsNSSComponent::InitializeNSS()
|
||||
SSL_OptionSetDefault(SSL_ENABLE_TLS13_COMPAT_MODE,
|
||||
Preferences::GetBool("security.ssl.enable_tls13_compat_mode",
|
||||
TLS13_COMPAT_MODE_DEFAULT));
|
||||
|
||||
|
||||
if (NS_FAILED(InitializeCipherSuite())) {
|
||||
|
||||
@@ -2040,6 +2048,11 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
if (prefName.EqualsLiteral("security.tls.version.min") ||
|
||||
prefName.EqualsLiteral("security.tls.version.max")) {
|
||||
(void) setEnabledTLSVersions();
|
||||
} else if (prefName.EqualsLiteral("security.tls.hello_downgrade_check")) {
|
||||
bool enableDowngradeCheck =
|
||||
Preferences::GetBool("security.tls.hello_downgrade_check",
|
||||
HELLO_DOWNGRADE_CHECK_DEFAULT);
|
||||
SSL_OptionSetDefault(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, enableDowngradeCheck);
|
||||
} else if (prefName.EqualsLiteral("security.ssl.require_safe_negotiation")) {
|
||||
bool requireSafeNegotiation =
|
||||
Preferences::GetBool("security.ssl.require_safe_negotiation",
|
||||
|
||||
@@ -15,7 +15,6 @@ ifeq (,$(filter SunOS Linux WINNT,$(OS_ARCH)))
|
||||
else
|
||||
$(MAKE) stage-package make-buildinfo-file
|
||||
@echo 'Compressing...'
|
||||
cd $(DIST)/$(MOZ_PKG_DIR); $(CREATE_PRECOMPLETE_CMD)
|
||||
ifeq (WINNT,$(OS_ARCH))
|
||||
cd $(DIST); $(CYGWIN_WRAPPER) 7z a -t7z -m0=lzma2 -mx=9 -aoa -bb3 $(PKG_BASENAME).7z $(MOZ_PKG_DIR)
|
||||
else
|
||||
|
||||
@@ -55,6 +55,10 @@ stage-package: $(MOZ_PKG_MANIFEST) $(MOZ_PKG_MANIFEST_DEPS)
|
||||
$(MOZ_PKG_MANIFEST) '$(DIST)' '$(DIST)'/$(STAGEPATH)$(MOZ_PKG_DIR)$(if $(MOZ_PKG_MANIFEST),,$(_BINPATH)) \
|
||||
$(if $(filter omni,$(MOZ_PACKAGER_FORMAT)),$(if $(NON_OMNIJAR_FILES),--non-resource $(NON_OMNIJAR_FILES)))
|
||||
$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/find-dupes.py $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)
|
||||
ifneq (Darwin, $(OS_ARCH))
|
||||
# We don't want to do this on Mac as it will end up in the package root which is not how Mac packages things
|
||||
cd $(DIST)/$(MOZ_PKG_DIR) && $(CREATE_PRECOMPLETE_CMD)
|
||||
endif
|
||||
ifdef MOZ_PACKAGE_JSSHELL
|
||||
# Package JavaScript Shell
|
||||
@echo 'Packaging JavaScript Shell...'
|
||||
|
||||
@@ -150,12 +150,6 @@ interface nsITransferable : nsISupports
|
||||
void getAnyTransferData ( out ACString aFlavor, out nsISupports aData,
|
||||
out unsigned long aDataLen ) ;
|
||||
|
||||
/**
|
||||
* Returns true if the data is large.
|
||||
*/
|
||||
boolean isLargeDataSet ( ) ;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Setter part of interface
|
||||
///////////////////////////////
|
||||
|
||||
+65
-117
@@ -14,6 +14,7 @@ Notes to self:
|
||||
|
||||
|
||||
#include "nsTransferable.h"
|
||||
#include "nsAnonymousTemporaryFile.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsString.h"
|
||||
@@ -27,7 +28,6 @@ Notes to self:
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsPrimitiveHelpers.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsCRT.h"
|
||||
@@ -36,7 +36,6 @@ Notes to self:
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
@@ -56,164 +55,126 @@ size_t GetDataForFlavor (const nsTArray<DataStruct>& aArray,
|
||||
//-------------------------------------------------------------------------
|
||||
DataStruct::~DataStruct()
|
||||
{
|
||||
if (mCacheFileName) free(mCacheFileName);
|
||||
if (mCacheFD) {
|
||||
PR_Close(mCacheFD);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
DataStruct::SetData ( nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData )
|
||||
DataStruct::SetData(nsISupports* aData, uint32_t aDataLen, bool aIsPrivateData)
|
||||
{
|
||||
// Now, check to see if we consider the data to be "too large"
|
||||
// as well as ensuring that private browsing mode is disabled
|
||||
if (aDataLen > kLargeDatasetSize && !aIsPrivateData) {
|
||||
// if so, cache it to disk instead of memory
|
||||
if ( NS_SUCCEEDED(WriteCache(aData, aDataLen)) )
|
||||
if (NS_SUCCEEDED(WriteCache(aData, aDataLen))) {
|
||||
// Clear previously set small data.
|
||||
mData = nullptr;
|
||||
mDataLen = 0;
|
||||
return;
|
||||
else
|
||||
NS_WARNING("Oh no, couldn't write data to the cache file");
|
||||
}
|
||||
NS_WARNING("Oh no, couldn't write data to the cache file");
|
||||
}
|
||||
|
||||
if (mCacheFD) {
|
||||
// Clear previously set big data.
|
||||
PR_Close(mCacheFD);
|
||||
mCacheFD = nullptr;
|
||||
}
|
||||
|
||||
mData = aData;
|
||||
mDataLen = aDataLen;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void
|
||||
DataStruct::GetData ( nsISupports** aData, uint32_t *aDataLen )
|
||||
DataStruct::GetData(nsISupports** aData, uint32_t* aDataLen)
|
||||
{
|
||||
// check here to see if the data is cached on disk
|
||||
if ( !mData && mCacheFileName ) {
|
||||
if (mCacheFD) {
|
||||
// if so, read it in and pass it back
|
||||
// ReadCache creates memory and copies the data into it.
|
||||
if ( NS_SUCCEEDED(ReadCache(aData, aDataLen)) )
|
||||
if (NS_SUCCEEDED(ReadCache(aData, aDataLen)))
|
||||
return;
|
||||
else {
|
||||
// oh shit, something went horribly wrong here.
|
||||
NS_WARNING("Oh no, couldn't read data in from the cache file");
|
||||
*aData = nullptr;
|
||||
*aDataLen = 0;
|
||||
PR_Close(mCacheFD);
|
||||
mCacheFD = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*aData = mData;
|
||||
if ( mData )
|
||||
if (mData)
|
||||
NS_ADDREF(*aData);
|
||||
*aDataLen = mDataLen;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
already_AddRefed<nsIFile>
|
||||
DataStruct::GetFileSpec(const char* aFileName)
|
||||
{
|
||||
nsCOMPtr<nsIFile> cacheFile;
|
||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(cacheFile));
|
||||
|
||||
if (!cacheFile)
|
||||
return nullptr;
|
||||
|
||||
// if the param aFileName contains a name we should use that
|
||||
// because the file probably already exists
|
||||
// otherwise create a unique name
|
||||
if (!aFileName) {
|
||||
cacheFile->AppendNative(NS_LITERAL_CSTRING("clipboardcache"));
|
||||
nsresult rv = cacheFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
if (NS_FAILED(rv))
|
||||
return nullptr;
|
||||
} else {
|
||||
cacheFile->AppendNative(nsDependentCString(aFileName));
|
||||
}
|
||||
|
||||
return cacheFile.forget();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsresult
|
||||
DataStruct::WriteCache(nsISupports* aData, uint32_t aDataLen)
|
||||
{
|
||||
// Get a new path and file to the temp directory
|
||||
nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName);
|
||||
if (cacheFile) {
|
||||
// remember the file name
|
||||
if (!mCacheFileName) {
|
||||
nsXPIDLCString fName;
|
||||
cacheFile->GetNativeLeafName(fName);
|
||||
mCacheFileName = strdup(fName);
|
||||
nsresult rv;
|
||||
if (!mCacheFD) {
|
||||
rv = NS_OpenAnonymousTemporaryFile(&mCacheFD);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else if (PR_Seek64(mCacheFD, 0, PR_SEEK_SET) == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// write out the contents of the clipboard
|
||||
// to the file
|
||||
//uint32_t bytes;
|
||||
nsCOMPtr<nsIOutputStream> outStr;
|
||||
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(outStr),
|
||||
cacheFile);
|
||||
|
||||
if (!outStr) return NS_ERROR_FAILURE;
|
||||
|
||||
// write out the contents of the clipboard to the file
|
||||
void* buff = nullptr;
|
||||
nsPrimitiveHelpers::CreateDataFromPrimitive ( mFlavor.get(), aData, &buff, aDataLen );
|
||||
nsPrimitiveHelpers::CreateDataFromPrimitive(mFlavor.get(), aData, &buff, aDataLen);
|
||||
if ( buff ) {
|
||||
uint32_t ignored;
|
||||
outStr->Write(reinterpret_cast<char*>(buff), aDataLen, &ignored);
|
||||
free(buff);
|
||||
int32_t written = PR_Write(mCacheFD, buff, aDataLen);
|
||||
free(buff);
|
||||
if (written) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
PR_Close(mCacheFD);
|
||||
mCacheFD = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsresult
|
||||
DataStruct::ReadCache(nsISupports** aData, uint32_t* aDataLen)
|
||||
{
|
||||
// if we don't have a cache filename we are out of luck
|
||||
if (!mCacheFileName)
|
||||
if (!mCacheFD) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// get the path and file name
|
||||
nsCOMPtr<nsIFile> cacheFile = GetFileSpec(mCacheFileName);
|
||||
bool exists;
|
||||
if ( cacheFile && NS_SUCCEEDED(cacheFile->Exists(&exists)) && exists ) {
|
||||
// get the size of the file
|
||||
int64_t fileSize;
|
||||
int64_t max32 = 0xFFFFFFFF;
|
||||
cacheFile->GetFileSize(&fileSize);
|
||||
if (fileSize > max32)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
uint32_t size = uint32_t(fileSize);
|
||||
// create new memory for the large clipboard data
|
||||
auto data = mozilla::MakeUnique<char[]>(size);
|
||||
if ( !data )
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// now read it all in
|
||||
nsCOMPtr<nsIInputStream> inStr;
|
||||
NS_NewLocalFileInputStream( getter_AddRefs(inStr),
|
||||
cacheFile);
|
||||
|
||||
if (!cacheFile) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = inStr->Read(data.get(), fileSize, aDataLen);
|
||||
|
||||
// make sure we got all the data ok
|
||||
if (NS_SUCCEEDED(rv) && *aDataLen == size) {
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor.get(), data.get(),
|
||||
fileSize, aData);
|
||||
return *aData ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// zero the return params
|
||||
*aData = nullptr;
|
||||
*aDataLen = 0;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
PRFileInfo fileInfo;
|
||||
if (PR_GetOpenFileInfo(mCacheFD, &fileInfo) != PR_SUCCESS) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (PR_Seek64(mCacheFD, 0, PR_SEEK_SET) == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
uint32_t fileSize = fileInfo.size;
|
||||
|
||||
auto data = mozilla::MakeUnique<char[]>(fileSize);
|
||||
if (!data) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
uint32_t actual = PR_Read(mCacheFD, data.get(), fileSize);
|
||||
if (actual != fileSize) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsPrimitiveHelpers::CreatePrimitiveForData(mFlavor.get(), data.get(), fileSize, aData);
|
||||
*aDataLen = fileSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -484,22 +445,9 @@ nsTransferable::RemoveDataFlavor(const char *aDataFlavor)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTransferable::IsLargeDataSet(bool *_retval)
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter)
|
||||
nsTransferable::SetConverter(nsIFormatConverter * aConverter)
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
@@ -512,7 +460,8 @@ NS_IMETHODIMP nsTransferable::SetConverter(nsIFormatConverter * aConverter)
|
||||
*
|
||||
*
|
||||
*/
|
||||
NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
|
||||
NS_IMETHODIMP
|
||||
nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
|
||||
{
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
||||
@@ -522,7 +471,6 @@ NS_IMETHODIMP nsTransferable::GetConverter(nsIFormatConverter * *aConverter)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// FlavorsTransferableCanImport
|
||||
//
|
||||
|
||||
@@ -6,16 +6,15 @@
|
||||
#ifndef nsTransferable_h__
|
||||
#define nsTransferable_h__
|
||||
|
||||
#include "nsIContentPolicyBase.h"
|
||||
#include "nsIFormatConverter.h"
|
||||
#include "nsITransferable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "prio.h"
|
||||
|
||||
class nsIMutableArray;
|
||||
class nsString;
|
||||
|
||||
//
|
||||
// DataStruct
|
||||
@@ -25,21 +24,20 @@ class nsString;
|
||||
struct DataStruct
|
||||
{
|
||||
explicit DataStruct ( const char* aFlavor )
|
||||
: mDataLen(0), mFlavor(aFlavor), mCacheFileName(nullptr) { }
|
||||
: mDataLen(0), mFlavor(aFlavor), mCacheFD(nullptr) { }
|
||||
~DataStruct();
|
||||
|
||||
const nsCString& GetFlavor() const { return mFlavor; }
|
||||
void SetData( nsISupports* inData, uint32_t inDataLen, bool aIsPrivateData );
|
||||
void GetData( nsISupports** outData, uint32_t *outDataLen );
|
||||
already_AddRefed<nsIFile> GetFileSpec(const char* aFileName);
|
||||
bool IsDataAvailable() const { return (mData && mDataLen > 0) || (!mData && mCacheFileName); }
|
||||
bool IsDataAvailable() const { return mData ? mDataLen > 0 : mCacheFD != nullptr; }
|
||||
|
||||
protected:
|
||||
|
||||
enum {
|
||||
// The size of data over which we write the data to disk rather than
|
||||
// keep it around in memory.
|
||||
kLargeDatasetSize = 1000000 // 1 million bytes
|
||||
kLargeDatasetSize = 4194304 // 4 Megabytes
|
||||
};
|
||||
|
||||
nsresult WriteCache(nsISupports* aData, uint32_t aDataLen );
|
||||
@@ -47,8 +45,8 @@ protected:
|
||||
|
||||
nsCOMPtr<nsISupports> mData; // OWNER - some varient of primitive wrapper
|
||||
uint32_t mDataLen;
|
||||
PRFileDesc* mCacheFD;
|
||||
const nsCString mFlavor;
|
||||
char * mCacheFileName;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -355,7 +355,11 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir)
|
||||
|
||||
// default extension to append to new files
|
||||
if (!mDefaultExtension.IsEmpty()) {
|
||||
hr = dialog->SetDefaultExtension(mDefaultExtension.get());
|
||||
// We don't want environment variables expanded in the extension either.
|
||||
nsAutoString sanitizedExtension(mDefaultExtension);
|
||||
sanitizedExtension.ReplaceChar('%', '_');
|
||||
|
||||
hr = dialog->SetDefaultExtension(sanitizedExtension.get());
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
@@ -640,7 +644,9 @@ nsFilePicker::InitNative(nsIWidget *aParent,
|
||||
NS_IMETHODIMP
|
||||
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
|
||||
{
|
||||
mComFilterList.Append(aTitle, aFilter);
|
||||
nsAutoString sanitizedFilter(aFilter);
|
||||
sanitizedFilter.ReplaceChar('%', '_');
|
||||
mComFilterList.Append(aTitle, sanitizedFilter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user