mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
b95ba78360
@ -213,6 +213,14 @@
|
||||
%include ../shared/toolbarbutton-icons.inc.css
|
||||
%include ../shared/menupanel.inc.css
|
||||
|
||||
/* Override OSX-specific toolkit findbar button styles */
|
||||
.findbar-button {
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* On Mac, native buttons keep their full opacity when they become disabled
|
||||
* and only the glyph or text on top of them becomes less opaque. */
|
||||
:root:not([customizing]) #back-button[disabled="true"] {
|
||||
|
@ -91,6 +91,12 @@ toolbar[brighttext] {
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
.findbar-button {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
toolbar .toolbarbutton-1 {
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
|
@ -17,7 +17,6 @@
|
||||
"r318309.patch",
|
||||
"r320462.patch",
|
||||
"loosen-msvc-detection.patch",
|
||||
"hide-gcda-profiling-symbols.patch",
|
||||
"fflush-before-unlocking.patch"
|
||||
]
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c
|
||||
index 138af6ec4..f0c05075a 100644
|
||||
--- a/compiler-rt/lib/profile/GCDAProfiling.c
|
||||
+++ b/compiler-rt/lib/profile/GCDAProfiling.c
|
||||
@@ -231,6 +231,7 @@ static void unmap_file() {
|
||||
* profiling enabled will emit to a different file. Only one file may be
|
||||
* started at a time.
|
||||
*/
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_start_file(const char *orig_filename, const char version[4],
|
||||
uint32_t checksum) {
|
||||
const char *mode = "r+b";
|
||||
@@ -298,6 +299,7 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4],
|
||||
/* Given an array of pointers to counters (counters), increment the n-th one,
|
||||
* where we're also given a pointer to n (predecessor).
|
||||
*/
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_increment_indirect_counter(uint32_t *predecessor,
|
||||
uint64_t **counters) {
|
||||
uint64_t *counter;
|
||||
@@ -320,6 +322,7 @@ void llvm_gcda_increment_indirect_counter(uint32_t *predecessor,
|
||||
#endif
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_emit_function(uint32_t ident, const char *function_name,
|
||||
uint32_t func_checksum, uint8_t use_extra_checksum,
|
||||
uint32_t cfg_checksum) {
|
||||
@@ -346,6 +349,7 @@ void llvm_gcda_emit_function(uint32_t ident, const char *function_name,
|
||||
write_string(function_name);
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
|
||||
uint32_t i;
|
||||
uint64_t *old_ctrs = NULL;
|
||||
@@ -397,6 +401,7 @@ void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
|
||||
#endif
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_summary_info() {
|
||||
const uint32_t obj_summary_len = 9; /* Length for gcov compatibility. */
|
||||
uint32_t i;
|
||||
@@ -450,6 +455,7 @@ void llvm_gcda_summary_info() {
|
||||
#endif
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcda_end_file() {
|
||||
/* Write out EOF record. */
|
||||
if (output_file) {
|
||||
@@ -474,6 +480,7 @@ void llvm_gcda_end_file() {
|
||||
#endif
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_register_writeout_function(writeout_fn fn) {
|
||||
struct writeout_fn_node *new_node = malloc(sizeof(struct writeout_fn_node));
|
||||
new_node->fn = fn;
|
||||
@@ -487,6 +494,7 @@ void llvm_register_writeout_function(writeout_fn fn) {
|
||||
}
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_writeout_files(void) {
|
||||
struct writeout_fn_node *curr = writeout_fn_head;
|
||||
|
||||
@@ -496,6 +504,7 @@ void llvm_writeout_files(void) {
|
||||
}
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_delete_writeout_function_list(void) {
|
||||
while (writeout_fn_head) {
|
||||
struct writeout_fn_node *node = writeout_fn_head;
|
||||
@@ -506,6 +515,7 @@ void llvm_delete_writeout_function_list(void) {
|
||||
writeout_fn_head = writeout_fn_tail = NULL;
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_register_flush_function(flush_fn fn) {
|
||||
struct flush_fn_node *new_node = malloc(sizeof(struct flush_fn_node));
|
||||
new_node->fn = fn;
|
||||
@@ -519,6 +529,7 @@ void llvm_register_flush_function(flush_fn fn) {
|
||||
}
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void __gcov_flush() {
|
||||
struct flush_fn_node *curr = flush_fn_head;
|
||||
|
||||
@@ -528,6 +539,7 @@ void __gcov_flush() {
|
||||
}
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_delete_flush_function_list(void) {
|
||||
while (flush_fn_head) {
|
||||
struct flush_fn_node *node = flush_fn_head;
|
||||
@@ -538,6 +550,7 @@ void llvm_delete_flush_function_list(void) {
|
||||
flush_fn_head = flush_fn_tail = NULL;
|
||||
}
|
||||
|
||||
+COMPILER_RT_VISIBILITY
|
||||
void llvm_gcov_init(writeout_fn wfn, flush_fn ffn) {
|
||||
static int atexit_ran = 0;
|
||||
|
@ -1,19 +0,0 @@
|
||||
Author: Michael Wu <mwu@mozilla.com>
|
||||
Date: Thu Sep 24 11:36:08 2015 -0400
|
||||
|
||||
Return an empty string when a symbol isn't mangled
|
||||
|
||||
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
|
||||
--- a/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/clang/tools/libclang/CIndex.cpp
|
||||
@@ -3990,6 +3990,10 @@
|
||||
ASTContext &Ctx = ND->getASTContext();
|
||||
std::unique_ptr<MangleContext> MC(Ctx.createMangleContext());
|
||||
|
||||
+ // Don't mangle if we don't need to.
|
||||
+ if (!MC->shouldMangleCXXName(ND))
|
||||
+ return cxstring::createEmpty();
|
||||
+
|
||||
std::string FrontendBuf;
|
||||
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
|
||||
if (MC->shouldMangleDeclName(ND)) {
|
@ -818,7 +818,7 @@ void
|
||||
DumpAnimationProperties(nsTArray<AnimationProperty>& aAnimationProperties)
|
||||
{
|
||||
for (auto& p : aAnimationProperties) {
|
||||
printf("%s\n", nsCSSProps::GetStringValue(p.mProperty).get());
|
||||
printf("%s\n", nsCString(nsCSSProps::GetStringValue(p.mProperty)).get());
|
||||
for (auto& s : p.mSegments) {
|
||||
nsString fromValue, toValue;
|
||||
s.mFromValue.SerializeSpecifiedValue(p.mProperty, fromValue);
|
||||
|
@ -2707,10 +2707,8 @@ nsDOMWindowUtils::ComputeAnimationDistance(Element* aElement,
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aElement);
|
||||
|
||||
nsCSSPropertyID property =
|
||||
nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eIgnoreEnabledState);
|
||||
if (property == eCSSProperty_UNKNOWN ||
|
||||
nsCSSProps::IsShorthand(property)) {
|
||||
nsCSSPropertyID property = nsCSSProps::LookupProperty(aProperty);
|
||||
if (property == eCSSProperty_UNKNOWN || nsCSSProps::IsShorthand(property)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@ -2737,8 +2735,7 @@ nsDOMWindowUtils::GetUnanimatedComputedStyle(Element* aElement,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCSSPropertyID propertyID =
|
||||
nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
|
||||
nsCSSPropertyID propertyID = nsCSSProps::LookupProperty(aProperty);
|
||||
if (propertyID == eCSSProperty_UNKNOWN ||
|
||||
nsCSSProps::IsShorthand(propertyID)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -1941,10 +1941,16 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
||||
// Figure out indexes and the index values to update here.
|
||||
const nsTArray<IndexMetadata>& indexes = mSpec->indexes();
|
||||
|
||||
const uint32_t idxCount = indexes.Length();
|
||||
uint32_t idxCount = indexes.Length();
|
||||
|
||||
if (idxCount && !aValueWrapper.Clone(aCx)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
if (idxCount) {
|
||||
if (!aValueWrapper.Clone(aCx)) {
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
// Update idxCount, the structured clone process may trigger content code
|
||||
// via getters/other which can potentially call CreateIndex/DeleteIndex.
|
||||
idxCount = indexes.Length();
|
||||
}
|
||||
|
||||
aUpdateInfoArray.SetCapacity(idxCount); // Pretty good estimate
|
||||
|
@ -155,8 +155,7 @@ nsSMILCompositor::GetCSSPropertyToAnimate() const
|
||||
}
|
||||
|
||||
nsCSSPropertyID propID =
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName),
|
||||
CSSEnabledState::eForAllContent);
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName));
|
||||
|
||||
if (!nsSMILCSSProperty::IsPropertyAnimatable(propID)) {
|
||||
return eCSSProperty_UNKNOWN;
|
||||
|
@ -1192,8 +1192,7 @@ MappedAttrParser::ParseMappedAttrValue(nsAtom* aMappedAttrName,
|
||||
|
||||
// Get the nsCSSPropertyID ID for our mapped attribute.
|
||||
nsCSSPropertyID propertyID =
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
|
||||
CSSEnabledState::eForAllContent);
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName));
|
||||
if (propertyID != eCSSProperty_UNKNOWN) {
|
||||
bool changed = false; // outparam for ParseProperty.
|
||||
NS_ConvertUTF16toUTF8 value(aMappedAttrValue);
|
||||
|
@ -538,8 +538,7 @@ CSSEditUtils::GetCSSInlinePropertyBase(nsINode* aNode,
|
||||
}
|
||||
|
||||
nsCSSPropertyID prop =
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(aProperty),
|
||||
CSSEnabledState::eForAllContent);
|
||||
nsCSSProps::LookupProperty(nsDependentAtomString(aProperty));
|
||||
MOZ_ASSERT(prop != eCSSProperty_UNKNOWN);
|
||||
|
||||
decl->GetPropertyValueByID(prop, aValue);
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "vm/ProxyObject.h"
|
||||
|
||||
#include "gc/WeakMap-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
static bool
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define builtin_WeakMapObject_h
|
||||
|
||||
#include "gc/WeakMap.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "ds/InlineTable.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSAtom.h"
|
||||
|
272
js/src/gc/WeakMap-inl.h
Normal file
272
js/src/gc/WeakMap-inl.h
Normal file
@ -0,0 +1,272 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef gc_WeakMap_inl_h
|
||||
#define gc_WeakMap_inl_h
|
||||
|
||||
#include "gc/WeakMap.h"
|
||||
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
template <typename T>
|
||||
static T extractUnbarriered(const WriteBarrieredBase<T>& v)
|
||||
{
|
||||
return v.get();
|
||||
}
|
||||
template <typename T>
|
||||
static T* extractUnbarriered(T* v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
WeakMap<K, V, HP>::WeakMap(JSContext* cx, JSObject* memOf)
|
||||
: Base(cx->zone()), WeakMapBase(memOf, cx->zone())
|
||||
{}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
bool
|
||||
WeakMap<K, V, HP>::init(uint32_t len)
|
||||
{
|
||||
if (!Base::init(len))
|
||||
return false;
|
||||
zone()->gcWeakMapList().insertFront(this);
|
||||
marked = JS::IsIncrementalGCInProgress(TlsContext.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trace a WeakMap entry based on 'markedCell' getting marked, where 'origKey'
|
||||
// is the key in the weakmap. These will probably be the same, but can be
|
||||
// different eg when markedCell is a delegate for origKey.
|
||||
//
|
||||
// This implementation does not use 'markedCell'; it looks up origKey and checks
|
||||
// the mark bits on everything it cares about, one of which will be
|
||||
// markedCell. But a subclass might use it to optimize the liveness check.
|
||||
template <class K, class V, class HP>
|
||||
void
|
||||
WeakMap<K, V, HP>::markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey)
|
||||
{
|
||||
MOZ_ASSERT(marked);
|
||||
|
||||
// If this cast fails, then you're instantiating the WeakMap with a
|
||||
// Lookup that can't be constructed from a Cell*. The WeakKeyTable
|
||||
// mechanism is indexed with a GCCellPtr, so that won't work.
|
||||
Ptr p = Base::lookup(static_cast<Lookup>(origKey.asCell()));
|
||||
MOZ_ASSERT(p.found());
|
||||
|
||||
K key(p->key());
|
||||
MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key)));
|
||||
if (gc::IsMarked(marker->runtime(), &key)) {
|
||||
TraceEdge(marker, &p->value(), "ephemeron value");
|
||||
} else if (keyNeedsMark(key)) {
|
||||
TraceEdge(marker, &p->value(), "WeakMap ephemeron value");
|
||||
TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key");
|
||||
MOZ_ASSERT(key == p->key()); // No moving
|
||||
}
|
||||
key.unsafeSet(nullptr); // Prevent destructor from running barriers.
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
void
|
||||
WeakMap<K, V, HP>::trace(JSTracer* trc)
|
||||
{
|
||||
MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList());
|
||||
|
||||
TraceNullableEdge(trc, &memberOf, "WeakMap owner");
|
||||
|
||||
if (!Base::initialized())
|
||||
return;
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps);
|
||||
marked = true;
|
||||
(void) markIteratively(GCMarker::fromTracer(trc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (trc->weakMapAction() == DoNotTraceWeakMaps)
|
||||
return;
|
||||
|
||||
// Trace keys only if weakMapAction() says to.
|
||||
if (trc->weakMapAction() == TraceWeakMapKeysValues) {
|
||||
for (Enum e(*this); !e.empty(); e.popFront())
|
||||
TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key");
|
||||
}
|
||||
|
||||
// Always trace all values (unless weakMapAction() is
|
||||
// DoNotTraceWeakMaps).
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront())
|
||||
TraceEdge(trc, &r.front().value(), "WeakMap entry value");
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
/* static */ void
|
||||
WeakMap<K, V, HP>::addWeakEntry(GCMarker* marker, JS::GCCellPtr key,
|
||||
const gc::WeakMarkable& markable)
|
||||
{
|
||||
Zone* zone = key.asCell()->asTenured().zone();
|
||||
|
||||
auto p = zone->gcWeakKeys().get(key);
|
||||
if (p) {
|
||||
gc::WeakEntryVector& weakEntries = p->value;
|
||||
if (!weakEntries.append(markable))
|
||||
marker->abortLinearWeakMarking();
|
||||
} else {
|
||||
gc::WeakEntryVector weakEntries;
|
||||
MOZ_ALWAYS_TRUE(weakEntries.append(markable));
|
||||
if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries)))
|
||||
marker->abortLinearWeakMarking();
|
||||
}
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
bool
|
||||
WeakMap<K, V, HP>::markIteratively(GCMarker* marker)
|
||||
{
|
||||
MOZ_ASSERT(marked);
|
||||
|
||||
bool markedAny = false;
|
||||
|
||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||
// If the entry is live, ensure its key and value are marked.
|
||||
bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey());
|
||||
if (!keyIsMarked && keyNeedsMark(e.front().key())) {
|
||||
TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key");
|
||||
keyIsMarked = true;
|
||||
markedAny = true;
|
||||
}
|
||||
|
||||
if (keyIsMarked) {
|
||||
if (!gc::IsMarked(marker->runtime(), &e.front().value())) {
|
||||
TraceEdge(marker, &e.front().value(), "WeakMap entry value");
|
||||
markedAny = true;
|
||||
}
|
||||
} else if (marker->isWeakMarkingTracer()) {
|
||||
// Entry is not yet known to be live. Record this weakmap and
|
||||
// the lookup key in the list of weak keys. Also record the
|
||||
// delegate, if any, because marking the delegate also marks
|
||||
// the entry.
|
||||
JS::GCCellPtr weakKey(extractUnbarriered(e.front().key()));
|
||||
gc::WeakMarkable markable(this, weakKey);
|
||||
addWeakEntry(marker, weakKey, markable);
|
||||
if (JSObject* delegate = getDelegate(e.front().key()))
|
||||
addWeakEntry(marker, JS::GCCellPtr(delegate), markable);
|
||||
}
|
||||
}
|
||||
|
||||
return markedAny;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline JSObject*
|
||||
WeakMap<K, V, HP>::getDelegate(JSObject* key) const
|
||||
{
|
||||
JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp();
|
||||
if (!op)
|
||||
return nullptr;
|
||||
|
||||
JSObject* obj = op(key);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread());
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline JSObject*
|
||||
WeakMap<K, V, HP>::getDelegate(JSScript* script) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline JSObject*
|
||||
WeakMap<K, V, HP>::getDelegate(LazyScript* script) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline bool
|
||||
WeakMap<K, V, HP>::keyNeedsMark(JSObject* key) const
|
||||
{
|
||||
JSObject* delegate = getDelegate(key);
|
||||
/*
|
||||
* Check if the delegate is marked with any color to properly handle
|
||||
* gray marking when the key's delegate is black and the map is gray.
|
||||
*/
|
||||
return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate);
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline bool
|
||||
WeakMap<K, V, HP>::keyNeedsMark(JSScript* script) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class K, class V, class HP>
|
||||
inline bool
|
||||
WeakMap<K, V, HP>::keyNeedsMark(LazyScript* script) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <class K, class V, class HP>
|
||||
void
|
||||
WeakMap<K, V, HP>::sweep()
|
||||
{
|
||||
/* Remove all entries whose keys remain unmarked. */
|
||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||
if (gc::IsAboutToBeFinalized(&e.front().mutableKey()))
|
||||
e.removeFront();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
// Once we've swept, all remaining edges should stay within the known-live
|
||||
// part of the graph.
|
||||
assertEntriesNotAboutToBeFinalized();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* memberOf can be nullptr, which means that the map is not part of a JSObject. */
|
||||
template <class K, class V, class HP>
|
||||
void
|
||||
WeakMap<K, V, HP>::traceMappings(WeakMapTracer* tracer)
|
||||
{
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
gc::Cell* key = gc::ToMarkable(r.front().key());
|
||||
gc::Cell* value = gc::ToMarkable(r.front().value());
|
||||
if (key && value) {
|
||||
tracer->trace(memberOf,
|
||||
JS::GCCellPtr(r.front().key().get()),
|
||||
JS::GCCellPtr(r.front().value().get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
template <class K, class V, class HP>
|
||||
void
|
||||
WeakMap<K, V, HP>::assertEntriesNotAboutToBeFinalized()
|
||||
{
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
K k(r.front().key());
|
||||
MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k));
|
||||
MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value()));
|
||||
MOZ_ASSERT(k == r.front().key());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* gc_WeakMap_inl_h */
|
@ -4,7 +4,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gc/WeakMap.h"
|
||||
#include "gc/WeakMap-inl.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -8,20 +8,24 @@
|
||||
#define gc_WeakMap_h
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Move.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/DeletePolicy.h"
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/Realm.h"
|
||||
|
||||
namespace JS {
|
||||
class Zone;
|
||||
} // namespace JS
|
||||
|
||||
namespace js {
|
||||
|
||||
class GCMarker;
|
||||
class WeakMapBase;
|
||||
struct WeakMapTracer;
|
||||
|
||||
namespace gc {
|
||||
struct WeakMarkable;
|
||||
} // namespace gc
|
||||
|
||||
// A subclass template of js::HashMap whose keys and values may be garbage-collected. When
|
||||
// a key is collected, the table entry disappears, dropping its reference to the value.
|
||||
@ -49,7 +53,7 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase>
|
||||
WeakMapBase(JSObject* memOf, JS::Zone* zone);
|
||||
virtual ~WeakMapBase();
|
||||
|
||||
Zone* zone() const { return zone_; }
|
||||
JS::Zone* zone() const { return zone_; }
|
||||
|
||||
// Garbage collector entry points.
|
||||
|
||||
@ -107,17 +111,6 @@ class WeakMapBase : public mozilla::LinkedListElement<WeakMapBase>
|
||||
bool marked;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static T extractUnbarriered(const WriteBarrieredBase<T>& v)
|
||||
{
|
||||
return v.get();
|
||||
}
|
||||
template <typename T>
|
||||
static T* extractUnbarriered(T* v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template <class Key, class Value,
|
||||
class HashPolicy = DefaultHasher<Key> >
|
||||
class WeakMap : public HashMap<Key, Value, HashPolicy, ZoneAllocPolicy>,
|
||||
@ -132,16 +125,9 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, ZoneAllocPolicy>,
|
||||
typedef typename Base::Ptr Ptr;
|
||||
typedef typename Base::AddPtr AddPtr;
|
||||
|
||||
explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr)
|
||||
: Base(cx->zone()), WeakMapBase(memOf, cx->zone()) { }
|
||||
explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr);
|
||||
|
||||
bool init(uint32_t len = 16) {
|
||||
if (!Base::init(len))
|
||||
return false;
|
||||
zone()->gcWeakMapList().insertFront(this);
|
||||
marked = JS::IsIncrementalGCInProgress(TlsContext.get());
|
||||
return true;
|
||||
}
|
||||
bool init(uint32_t len = 16);
|
||||
|
||||
// Overwritten to add a read barrier to prevent an incorrectly gray value
|
||||
// from escaping the weak map. See the UnmarkGrayTracer::onChild comment in
|
||||
@ -170,204 +156,46 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, ZoneAllocPolicy>,
|
||||
// Resolve ambiguity with LinkedListElement<>::remove.
|
||||
using Base::remove;
|
||||
|
||||
// Trace a WeakMap entry based on 'markedCell' getting marked, where
|
||||
// 'origKey' is the key in the weakmap. These will probably be the same,
|
||||
// but can be different eg when markedCell is a delegate for origKey.
|
||||
//
|
||||
// This implementation does not use 'markedCell'; it looks up origKey and
|
||||
// checks the mark bits on everything it cares about, one of which will be
|
||||
// markedCell. But a subclass might use it to optimize the liveness check.
|
||||
void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override
|
||||
{
|
||||
MOZ_ASSERT(marked);
|
||||
void markEntry(GCMarker* marker, gc::Cell* markedCell, JS::GCCellPtr origKey) override;
|
||||
|
||||
// If this cast fails, then you're instantiating the WeakMap with a
|
||||
// Lookup that can't be constructed from a Cell*. The WeakKeyTable
|
||||
// mechanism is indexed with a GCCellPtr, so that won't work.
|
||||
Ptr p = Base::lookup(static_cast<Lookup>(origKey.asCell()));
|
||||
MOZ_ASSERT(p.found());
|
||||
|
||||
Key key(p->key());
|
||||
MOZ_ASSERT((markedCell == extractUnbarriered(key)) || (markedCell == getDelegate(key)));
|
||||
if (gc::IsMarked(marker->runtime(), &key)) {
|
||||
TraceEdge(marker, &p->value(), "ephemeron value");
|
||||
} else if (keyNeedsMark(key)) {
|
||||
TraceEdge(marker, &p->value(), "WeakMap ephemeron value");
|
||||
TraceEdge(marker, &key, "proxy-preserved WeakMap ephemeron key");
|
||||
MOZ_ASSERT(key == p->key()); // No moving
|
||||
}
|
||||
key.unsafeSet(nullptr); // Prevent destructor from running barriers.
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc) override {
|
||||
MOZ_ASSERT_IF(JS::RuntimeHeapIsBusy(), isInList());
|
||||
|
||||
TraceNullableEdge(trc, &memberOf, "WeakMap owner");
|
||||
|
||||
if (!Base::initialized())
|
||||
return;
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
MOZ_ASSERT(trc->weakMapAction() == ExpandWeakMaps);
|
||||
marked = true;
|
||||
(void) markIteratively(GCMarker::fromTracer(trc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (trc->weakMapAction() == DoNotTraceWeakMaps)
|
||||
return;
|
||||
|
||||
// Trace keys only if weakMapAction() says to.
|
||||
if (trc->weakMapAction() == TraceWeakMapKeysValues) {
|
||||
for (Enum e(*this); !e.empty(); e.popFront())
|
||||
TraceEdge(trc, &e.front().mutableKey(), "WeakMap entry key");
|
||||
}
|
||||
|
||||
// Always trace all values (unless weakMapAction() is
|
||||
// DoNotTraceWeakMaps).
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront())
|
||||
TraceEdge(trc, &r.front().value(), "WeakMap entry value");
|
||||
}
|
||||
void trace(JSTracer* trc) override;
|
||||
|
||||
protected:
|
||||
static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key, gc::WeakMarkable markable)
|
||||
{
|
||||
Zone* zone = key.asCell()->asTenured().zone();
|
||||
static void addWeakEntry(GCMarker* marker, JS::GCCellPtr key,
|
||||
const gc::WeakMarkable& markable);
|
||||
|
||||
auto p = zone->gcWeakKeys().get(key);
|
||||
if (p) {
|
||||
gc::WeakEntryVector& weakEntries = p->value;
|
||||
if (!weakEntries.append(std::move(markable)))
|
||||
marker->abortLinearWeakMarking();
|
||||
} else {
|
||||
gc::WeakEntryVector weakEntries;
|
||||
MOZ_ALWAYS_TRUE(weakEntries.append(std::move(markable)));
|
||||
if (!zone->gcWeakKeys().put(JS::GCCellPtr(key), std::move(weakEntries)))
|
||||
marker->abortLinearWeakMarking();
|
||||
}
|
||||
}
|
||||
bool markIteratively(GCMarker* marker) override;
|
||||
|
||||
bool markIteratively(GCMarker* marker) override {
|
||||
MOZ_ASSERT(marked);
|
||||
|
||||
bool markedAny = false;
|
||||
|
||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||
// If the entry is live, ensure its key and value are marked.
|
||||
bool keyIsMarked = gc::IsMarked(marker->runtime(), &e.front().mutableKey());
|
||||
if (!keyIsMarked && keyNeedsMark(e.front().key())) {
|
||||
TraceEdge(marker, &e.front().mutableKey(), "proxy-preserved WeakMap entry key");
|
||||
keyIsMarked = true;
|
||||
markedAny = true;
|
||||
}
|
||||
|
||||
if (keyIsMarked) {
|
||||
if (!gc::IsMarked(marker->runtime(), &e.front().value())) {
|
||||
TraceEdge(marker, &e.front().value(), "WeakMap entry value");
|
||||
markedAny = true;
|
||||
}
|
||||
} else if (marker->isWeakMarkingTracer()) {
|
||||
// Entry is not yet known to be live. Record this weakmap and
|
||||
// the lookup key in the list of weak keys. Also record the
|
||||
// delegate, if any, because marking the delegate also marks
|
||||
// the entry.
|
||||
JS::GCCellPtr weakKey(extractUnbarriered(e.front().key()));
|
||||
gc::WeakMarkable markable(this, weakKey);
|
||||
addWeakEntry(marker, weakKey, markable);
|
||||
if (JSObject* delegate = getDelegate(e.front().key()))
|
||||
addWeakEntry(marker, JS::GCCellPtr(delegate), markable);
|
||||
}
|
||||
}
|
||||
|
||||
return markedAny;
|
||||
}
|
||||
|
||||
JSObject* getDelegate(JSObject* key) const {
|
||||
JSWeakmapKeyDelegateOp op = key->getClass()->extWeakmapKeyDelegateOp();
|
||||
if (!op)
|
||||
return nullptr;
|
||||
|
||||
JSObject* obj = op(key);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(obj->runtimeFromMainThread() == zone()->runtimeFromMainThread());
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject* getDelegate(JSScript* script) const {
|
||||
return nullptr;
|
||||
}
|
||||
JSObject* getDelegate(LazyScript* script) const {
|
||||
return nullptr;
|
||||
}
|
||||
JSObject* getDelegate(JSObject* key) const;
|
||||
JSObject* getDelegate(JSScript* script) const;
|
||||
JSObject* getDelegate(LazyScript* script) const;
|
||||
|
||||
private:
|
||||
void exposeGCThingToActiveJS(const JS::Value& v) const { JS::ExposeValueToActiveJS(v); }
|
||||
void exposeGCThingToActiveJS(JSObject* obj) const { JS::ExposeObjectToActiveJS(obj); }
|
||||
|
||||
bool keyNeedsMark(JSObject* key) const {
|
||||
JSObject* delegate = getDelegate(key);
|
||||
/*
|
||||
* Check if the delegate is marked with any color to properly handle
|
||||
* gray marking when the key's delegate is black and the map is gray.
|
||||
*/
|
||||
return delegate && gc::IsMarkedUnbarriered(zone()->runtimeFromMainThread(), &delegate);
|
||||
}
|
||||
|
||||
bool keyNeedsMark(JSScript* script) const {
|
||||
return false;
|
||||
}
|
||||
bool keyNeedsMark(LazyScript* script) const {
|
||||
return false;
|
||||
}
|
||||
bool keyNeedsMark(JSObject* key) const;
|
||||
bool keyNeedsMark(JSScript* script) const;
|
||||
bool keyNeedsMark(LazyScript* script) const;
|
||||
|
||||
bool findZoneEdges() override {
|
||||
// This is overridden by ObjectValueMap.
|
||||
return true;
|
||||
}
|
||||
|
||||
void sweep() override {
|
||||
/* Remove all entries whose keys remain unmarked. */
|
||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||
if (gc::IsAboutToBeFinalized(&e.front().mutableKey()))
|
||||
e.removeFront();
|
||||
}
|
||||
/*
|
||||
* Once we've swept, all remaining edges should stay within the
|
||||
* known-live part of the graph.
|
||||
*/
|
||||
assertEntriesNotAboutToBeFinalized();
|
||||
}
|
||||
void sweep() override;
|
||||
|
||||
void finish() override {
|
||||
Base::finish();
|
||||
}
|
||||
|
||||
/* memberOf can be nullptr, which means that the map is not part of a JSObject. */
|
||||
void traceMappings(WeakMapTracer* tracer) override {
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
gc::Cell* key = gc::ToMarkable(r.front().key());
|
||||
gc::Cell* value = gc::ToMarkable(r.front().value());
|
||||
if (key && value) {
|
||||
tracer->trace(memberOf,
|
||||
JS::GCCellPtr(r.front().key().get()),
|
||||
JS::GCCellPtr(r.front().value().get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void traceMappings(WeakMapTracer* tracer) override;
|
||||
|
||||
protected:
|
||||
void assertEntriesNotAboutToBeFinalized() {
|
||||
#if DEBUG
|
||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||
Key k(r.front().key());
|
||||
MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k));
|
||||
MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value()));
|
||||
MOZ_ASSERT(k == r.front().key());
|
||||
}
|
||||
void assertEntriesNotAboutToBeFinalized();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "js/WeakMapPtr.h"
|
||||
|
||||
#include "gc/WeakMap.h"
|
||||
#include "gc/WeakMap-inl.h"
|
||||
|
||||
//
|
||||
// Machinery for the externally-linkable JS::WeakMapPtr, which wraps js::WeakMap
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "vm/Debugger.h"
|
||||
|
||||
#include "gc/WeakMap-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
/* static */ inline bool
|
||||
|
@ -219,7 +219,9 @@ class DebuggerWeakMap : private WeakMap<HeapPtr<UnbarrieredKey>, HeapPtr<JSObjec
|
||||
e.removeFront();
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
Base::assertEntriesNotAboutToBeFinalized();
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool incZoneCount(JS::Zone* zone) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "vm/ArrayBufferObject.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/JSFunction.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
|
@ -49,8 +49,6 @@ using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
extern const char* const kCSSRawProperties[];
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -373,8 +371,8 @@ InspectorUtils::GetCSSPropertyNames(GlobalObject& aGlobalObject,
|
||||
auto appendProperty = [enabledState, &aResult](uint32_t prop) {
|
||||
nsCSSPropertyID cssProp = nsCSSPropertyID(prop);
|
||||
if (nsCSSProps::IsEnabled(cssProp, enabledState)) {
|
||||
nsDependentCString name(kCSSRawProperties[prop]);
|
||||
aResult.AppendElement(NS_ConvertASCIItoUTF16(name));
|
||||
aResult.AppendElement(NS_ConvertASCIItoUTF16(
|
||||
nsCSSProps::GetStringValue(cssProp)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -406,8 +404,7 @@ InspectorUtils::GetCSSPropertyPrefs(GlobalObject& aGlobalObject,
|
||||
for (const auto* src = nsCSSProps::kPropertyPrefTable;
|
||||
src->mPropID != eCSSProperty_UNKNOWN; src++) {
|
||||
PropertyPref& dest = *aResult.AppendElement();
|
||||
const nsCString& name = nsCSSProps::GetStringValue(src->mPropID);
|
||||
dest.mName.Assign(NS_ConvertASCIItoUTF16(name));
|
||||
dest.mName.Assign(NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(src->mPropID)));
|
||||
dest.mPref.AssignASCII(src->mPref);
|
||||
}
|
||||
}
|
||||
@ -418,8 +415,7 @@ InspectorUtils::GetSubpropertiesForCSSProperty(GlobalObject& aGlobal,
|
||||
nsTArray<nsString>& aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCSSPropertyID propertyID =
|
||||
nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
|
||||
nsCSSPropertyID propertyID = nsCSSProps::LookupProperty(aProperty);
|
||||
|
||||
if (propertyID == eCSSProperty_UNKNOWN) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
@ -889,6 +889,13 @@ SERVO_BINDING_FUNC(Servo_ResolveLogicalProperty,
|
||||
nsCSSPropertyID,
|
||||
nsCSSPropertyID,
|
||||
ComputedStyleBorrowed);
|
||||
SERVO_BINDING_FUNC(Servo_Property_LookupEnabledForAllContent,
|
||||
nsCSSPropertyID,
|
||||
const nsACString* name);
|
||||
SERVO_BINDING_FUNC(Servo_Property_GetName,
|
||||
const uint8_t*,
|
||||
nsCSSPropertyID,
|
||||
uint32_t* out_length);
|
||||
SERVO_BINDING_FUNC(Servo_Property_IsShorthand, bool,
|
||||
const nsACString* name, bool* found);
|
||||
SERVO_BINDING_FUNC(Servo_Property_IsInherited, bool,
|
||||
|
@ -34,24 +34,9 @@ using namespace mozilla;
|
||||
|
||||
typedef nsCSSProps::KTableEntry KTableEntry;
|
||||
|
||||
// required to make the symbol external, so that TestCSSPropertyLookup.cpp can link with it
|
||||
extern const char* const kCSSRawProperties[];
|
||||
|
||||
// define an array of all CSS properties
|
||||
const char* const kCSSRawProperties[eCSSProperty_COUNT_with_aliases] = {
|
||||
#define CSS_PROP_LONGHAND(name_, ...) #name_,
|
||||
#define CSS_PROP_SHORTHAND(name_, ...) #name_,
|
||||
#define CSS_PROP_ALIAS(name_, ...) #name_,
|
||||
#include "mozilla/ServoCSSPropList.h"
|
||||
#undef CSS_PROP_ALIAS
|
||||
#undef CSS_PROP_SHORTHAND
|
||||
#undef CSS_PROP_LONGHAND
|
||||
};
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
static int32_t gPropertyTableRefCount;
|
||||
static nsStaticCaseInsensitiveNameTable* gPropertyTable;
|
||||
static nsStaticCaseInsensitiveNameTable* gFontDescTable;
|
||||
static nsStaticCaseInsensitiveNameTable* gCounterDescTable;
|
||||
static nsDataHashtable<nsCStringHashKey,nsCSSPropertyID>* gPropertyIDLNameTable;
|
||||
@ -68,20 +53,6 @@ static const char* const kCSSRawCounterDescs[] = {
|
||||
#undef CSS_COUNTER_DESC
|
||||
};
|
||||
|
||||
// We need eCSSAliasCount so we can make gAliases nonzero size when there
|
||||
// are no aliases.
|
||||
enum {
|
||||
eCSSAliasCount = eCSSProperty_COUNT_with_aliases - eCSSProperty_COUNT
|
||||
};
|
||||
|
||||
// The names are in kCSSRawProperties.
|
||||
static nsCSSPropertyID gAliases[eCSSAliasCount != 0 ? eCSSAliasCount : 1] = {
|
||||
#define CSS_PROP_ALIAS(aliasname_, aliasid_, propid_, aliasmethod_, pref_) \
|
||||
eCSSProperty_##propid_ ,
|
||||
#include "mozilla/ServoCSSPropList.h"
|
||||
#undef CSS_PROP_ALIAS
|
||||
};
|
||||
|
||||
static nsStaticCaseInsensitiveNameTable*
|
||||
CreateStaticTable(const char* const aRawTable[], int32_t aLength)
|
||||
{
|
||||
@ -101,13 +72,10 @@ void
|
||||
nsCSSProps::AddRefTable(void)
|
||||
{
|
||||
if (0 == gPropertyTableRefCount++) {
|
||||
MOZ_ASSERT(!gPropertyTable, "pre existing array!");
|
||||
MOZ_ASSERT(!gFontDescTable, "pre existing array!");
|
||||
MOZ_ASSERT(!gCounterDescTable, "pre existing array!");
|
||||
MOZ_ASSERT(!gPropertyIDLNameTable, "pre existing array!");
|
||||
|
||||
gPropertyTable = CreateStaticTable(
|
||||
kCSSRawProperties, eCSSProperty_COUNT_with_aliases);
|
||||
gFontDescTable = CreateStaticTable(kCSSRawFontDescs, eCSSFontDesc_COUNT);
|
||||
gCounterDescTable = CreateStaticTable(
|
||||
kCSSRawCounterDescs, eCSSCounterDesc_COUNT);
|
||||
@ -141,9 +109,6 @@ void
|
||||
nsCSSProps::ReleaseTable(void)
|
||||
{
|
||||
if (0 == --gPropertyTableRefCount) {
|
||||
delete gPropertyTable;
|
||||
gPropertyTable = nullptr;
|
||||
|
||||
delete gFontDescTable;
|
||||
gFontDescTable = nullptr;
|
||||
|
||||
@ -162,40 +127,6 @@ nsCSSProps::IsCustomPropertyName(const nsAString& aProperty)
|
||||
StringBeginsWith(aProperty, NS_LITERAL_STRING("--"));
|
||||
}
|
||||
|
||||
nsCSSPropertyID
|
||||
nsCSSProps::LookupProperty(const nsAString& aProperty, EnabledState aEnabled)
|
||||
{
|
||||
if (IsCustomPropertyName(aProperty)) {
|
||||
return eCSSPropertyExtra_variable;
|
||||
}
|
||||
|
||||
// This is faster than converting and calling
|
||||
// LookupProperty(nsACString&). The table will do its own
|
||||
// converting and avoid a PromiseFlatCString() call.
|
||||
MOZ_ASSERT(gPropertyTable, "no lookup table, needs addref");
|
||||
nsCSSPropertyID res = nsCSSPropertyID(gPropertyTable->Lookup(aProperty));
|
||||
if (MOZ_LIKELY(res < eCSSProperty_COUNT)) {
|
||||
if (res != eCSSProperty_UNKNOWN && !IsEnabled(res, aEnabled)) {
|
||||
res = eCSSProperty_UNKNOWN;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
MOZ_ASSERT(eCSSAliasCount != 0,
|
||||
"'res' must be an alias at this point so we better have some!");
|
||||
// We intentionally don't support CSSEnabledState::eInUASheets or
|
||||
// CSSEnabledState::eInChrome for aliases yet because it's unlikely
|
||||
// there will be a need for it.
|
||||
if (IsEnabled(res) || aEnabled == CSSEnabledState::eIgnoreEnabledState) {
|
||||
res = gAliases[res - eCSSProperty_COUNT];
|
||||
MOZ_ASSERT(0 <= res && res < eCSSProperty_COUNT,
|
||||
"aliases must not point to other aliases");
|
||||
if (IsEnabled(res) || aEnabled == CSSEnabledState::eIgnoreEnabledState) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return eCSSProperty_UNKNOWN;
|
||||
}
|
||||
|
||||
nsCSSPropertyID
|
||||
nsCSSProps::LookupPropertyByIDLName(const nsACString& aPropertyIDLName,
|
||||
EnabledState aEnabled)
|
||||
@ -233,18 +164,6 @@ nsCSSProps::LookupFontDesc(const nsAString& aFontDesc)
|
||||
return which;
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
nsCSSProps::GetStringValue(nsCSSPropertyID aProperty)
|
||||
{
|
||||
MOZ_ASSERT(gPropertyTable, "no lookup table, needs addref");
|
||||
if (gPropertyTable) {
|
||||
return gPropertyTable->GetStringValue(int32_t(aProperty));
|
||||
} else {
|
||||
static nsDependentCString sNullStr("");
|
||||
return sNullStr;
|
||||
}
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
nsCSSProps::GetStringValue(nsCSSFontDesc aFontDescID)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCSSPropertyID.h"
|
||||
#include "nsStyleStructFwd.h"
|
||||
#include "nsCSSKeywords.h"
|
||||
@ -36,6 +36,8 @@ class ComputedStyle;
|
||||
extern "C" {
|
||||
nsCSSPropertyID Servo_ResolveLogicalProperty(nsCSSPropertyID,
|
||||
const mozilla::ComputedStyle*);
|
||||
nsCSSPropertyID Servo_Property_LookupEnabledForAllContent(const nsACString*);
|
||||
const uint8_t* Servo_Property_GetName(nsCSSPropertyID, uint32_t* aLength);
|
||||
}
|
||||
|
||||
struct nsCSSKTableEntry
|
||||
@ -80,8 +82,20 @@ public:
|
||||
// Looks up the property with name aProperty and returns its corresponding
|
||||
// nsCSSPropertyID value. If aProperty is the name of a custom property,
|
||||
// then eCSSPropertyExtra_variable will be returned.
|
||||
static nsCSSPropertyID LookupProperty(const nsAString& aProperty,
|
||||
EnabledState aEnabled);
|
||||
//
|
||||
// This only returns properties enabled for all content, and resolves aliases
|
||||
// to return the aliased property.
|
||||
static nsCSSPropertyID LookupProperty(const nsACString& aProperty)
|
||||
{
|
||||
return Servo_Property_LookupEnabledForAllContent(&aProperty);
|
||||
}
|
||||
|
||||
static nsCSSPropertyID LookupProperty(const nsAString& aProperty)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 utf8(aProperty);
|
||||
return LookupProperty(utf8);
|
||||
}
|
||||
|
||||
// As above, but looked up using a property's IDL name.
|
||||
// eCSSPropertyExtra_variable won't be returned from these methods.
|
||||
static nsCSSPropertyID LookupPropertyByIDLName(
|
||||
@ -106,7 +120,15 @@ public:
|
||||
static nsCSSFontDesc LookupFontDesc(const nsAString& aProperty);
|
||||
|
||||
// Given a property enum, get the string value
|
||||
static const nsCString& GetStringValue(nsCSSPropertyID aProperty);
|
||||
//
|
||||
// This string is static.
|
||||
static const nsDependentCSubstring GetStringValue(nsCSSPropertyID aProperty)
|
||||
{
|
||||
uint32_t len;
|
||||
const uint8_t* chars = Servo_Property_GetName(aProperty, &len);
|
||||
return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len);
|
||||
}
|
||||
|
||||
static const nsCString& GetStringValue(nsCSSFontDesc aFontDesc);
|
||||
static const nsCString& GetStringValue(nsCSSCounterDesc aCounterDesc);
|
||||
|
||||
|
@ -437,8 +437,7 @@ nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
|
||||
{
|
||||
aReturn.Truncate();
|
||||
|
||||
nsCSSPropertyID prop =
|
||||
nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent);
|
||||
nsCSSPropertyID prop = nsCSSProps::LookupProperty(aPropertyName);
|
||||
|
||||
const ComputedStyleMap::Entry* entry = nullptr;
|
||||
if (prop != eCSSPropertyExtra_variable) {
|
||||
@ -719,7 +718,7 @@ CollectImageURLsForProperty(nsCSSPropertyID aProp,
|
||||
nsTArray<nsString>& aURLs)
|
||||
{
|
||||
if (nsCSSProps::IsShorthand(aProp)) {
|
||||
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProp, CSSEnabledState::eInChrome) {
|
||||
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProp, CSSEnabledState::eForAllContent) {
|
||||
CollectImageURLsForProperty(*p, aStyle, aURLs);
|
||||
}
|
||||
return;
|
||||
@ -761,8 +760,7 @@ nsComputedDOMStyle::GetCSSImageURLs(const nsAString& aPropertyName,
|
||||
nsTArray<nsString>& aImageURLs,
|
||||
mozilla::ErrorResult& aRv)
|
||||
{
|
||||
nsCSSPropertyID prop =
|
||||
nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eInChrome);
|
||||
nsCSSPropertyID prop = nsCSSProps::LookupProperty(aPropertyName);
|
||||
if (prop == eCSSProperty_UNKNOWN) {
|
||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return;
|
||||
|
@ -209,8 +209,7 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName,
|
||||
}
|
||||
|
||||
// In the common (and fast) cases we can use the property id
|
||||
nsCSSPropertyID propID =
|
||||
nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent);
|
||||
nsCSSPropertyID propID = nsCSSProps::LookupProperty(aPropertyName);
|
||||
if (propID == eCSSProperty_UNKNOWN) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -393,8 +393,15 @@ GetTransform3d(nsIDocument* aDocument, const nsMediaFeature*,
|
||||
}
|
||||
|
||||
static bool
|
||||
HasSystemMetric(nsAtom* aMetric)
|
||||
HasSystemMetric(nsIDocument* aDocument,
|
||||
nsAtom* aMetric,
|
||||
bool aIsAccessibleFromContent)
|
||||
{
|
||||
if (aIsAccessibleFromContent &&
|
||||
nsContentUtils::ShouldResistFingerprinting(aDocument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsMediaFeatures::InitSystemMetrics();
|
||||
return sSystemMetrics->IndexOf(aMetric) != sSystemMetrics->NoIndex;
|
||||
}
|
||||
@ -403,27 +410,17 @@ static void
|
||||
GetSystemMetric(nsIDocument* aDocument, const nsMediaFeature* aFeature,
|
||||
nsCSSValue& aResult)
|
||||
{
|
||||
aResult.Reset();
|
||||
|
||||
const bool isAccessibleFromContentPages =
|
||||
!(aFeature->mReqFlags & nsMediaFeature::eUserAgentAndChromeOnly);
|
||||
|
||||
MOZ_ASSERT(!isAccessibleFromContentPages ||
|
||||
*aFeature->mName == nsGkAtoms::_moz_touch_enabled);
|
||||
|
||||
if (isAccessibleFromContentPages &&
|
||||
nsContentUtils::ShouldResistFingerprinting(aDocument)) {
|
||||
// If "privacy.resistFingerprinting" is enabled, then we simply don't
|
||||
// return any system-backed media feature values. (No spoofed values
|
||||
// returned.)
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aFeature->mValueType == nsMediaFeature::eBoolInteger,
|
||||
"unexpected type");
|
||||
|
||||
nsAtom* metricAtom = *aFeature->mData.mMetric;
|
||||
bool hasMetric = HasSystemMetric(metricAtom);
|
||||
bool hasMetric =
|
||||
HasSystemMetric(aDocument, metricAtom, isAccessibleFromContentPages);
|
||||
aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
|
||||
}
|
||||
|
||||
|
@ -21,71 +21,6 @@ static const char* const kJunkNames[] = {
|
||||
"#@$&@#*@*$@$#"
|
||||
};
|
||||
|
||||
static bool
|
||||
TestProps()
|
||||
{
|
||||
bool success = true;
|
||||
nsCSSPropertyID id;
|
||||
nsCSSPropertyID index;
|
||||
|
||||
// Everything appears to assert if we don't do this first...
|
||||
nsCSSProps::AddRefTable();
|
||||
|
||||
// First make sure we can find all of the tags that are supposed to
|
||||
// be in the table. Futz with the case to make sure any case will
|
||||
// work
|
||||
extern const char* const kCSSRawProperties[];
|
||||
const char*const* et = &kCSSRawProperties[0];
|
||||
const char*const* end = &kCSSRawProperties[eCSSProperty_COUNT];
|
||||
index = eCSSProperty_UNKNOWN;
|
||||
while (et < end) {
|
||||
char tagName[100];
|
||||
PL_strcpy(tagName, *et);
|
||||
index = nsCSSPropertyID(int32_t(index) + 1);
|
||||
|
||||
id = nsCSSProps::LookupProperty(nsCString(tagName),
|
||||
CSSEnabledState::eIgnoreEnabledState);
|
||||
if (id == eCSSProperty_UNKNOWN) {
|
||||
printf("bug: can't find '%s'\n", tagName);
|
||||
success = false;
|
||||
}
|
||||
if (id != index) {
|
||||
printf("bug: name='%s' id=%d index=%d\n", tagName, id, index);
|
||||
success = false;
|
||||
}
|
||||
|
||||
// fiddle with the case to make sure we can still find it
|
||||
if (('a' <= tagName[0]) && (tagName[0] <= 'z')) {
|
||||
tagName[0] = tagName[0] - 32;
|
||||
}
|
||||
id = nsCSSProps::LookupProperty(NS_ConvertASCIItoUTF16(tagName),
|
||||
CSSEnabledState::eIgnoreEnabledState);
|
||||
if (id < 0) {
|
||||
printf("bug: can't find '%s'\n", tagName);
|
||||
success = false;
|
||||
}
|
||||
if (index != id) {
|
||||
printf("bug: name='%s' id=%d index=%d\n", tagName, id, index);
|
||||
success = false;
|
||||
}
|
||||
et++;
|
||||
}
|
||||
|
||||
// Now make sure we don't find some garbage
|
||||
for (int i = 0; i < (int) (sizeof(kJunkNames) / sizeof(const char*)); i++) {
|
||||
const char* const tag = kJunkNames[i];
|
||||
id = nsCSSProps::LookupProperty(nsAutoCString(tag),
|
||||
CSSEnabledState::eIgnoreEnabledState);
|
||||
if (id >= 0) {
|
||||
printf("bug: found '%s'\n", tag ? tag : "(null)");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSProps::ReleaseTable();
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
TestKeywords()
|
||||
{
|
||||
|
@ -104,10 +104,13 @@ var testToggles = function (resisting) {
|
||||
suppressed_toggles.forEach(
|
||||
function (key) {
|
||||
var exists = keyValMatches(key, 0) || keyValMatches(key, 1);
|
||||
if (resisting || (!toggles_enabled_in_content.includes(key) && !is_chrome_window)) {
|
||||
if (!toggles_enabled_in_content.includes(key) && !is_chrome_window) {
|
||||
ok(!exists, key + " should not exist.");
|
||||
} else {
|
||||
ok(exists, key + " should exist.");
|
||||
if (resisting) {
|
||||
ok(keyValMatches(key, 0) && !keyValMatches(key, 1), "Should always match as false");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -214,7 +217,7 @@ var generateCSSLines = function (resisting) {
|
||||
if (!toggles_enabled_in_content.includes(key) && !resisting && !is_chrome_window) {
|
||||
lines += "#" + key + " { background-color: green; }\n";
|
||||
} else {
|
||||
lines += suppressedMediaQueryCSSLine(key, resisting ? "red" : "green");
|
||||
lines += suppressedMediaQueryCSSLine(key, "green");
|
||||
}
|
||||
});
|
||||
if (OS === "WINNT") {
|
||||
|
@ -486,17 +486,11 @@ VARCACHE_PREF(
|
||||
|
||||
// Don't create more memory-backed MediaCaches if their combined size would go
|
||||
// above this absolute size limit.
|
||||
#ifdef ANDROID
|
||||
# define PREF_VALUE 32768 // Measured in KiB
|
||||
#else
|
||||
# define PREF_VALUE 524288 // Measured in KiB
|
||||
#endif
|
||||
VARCACHE_PREF(
|
||||
"media.memory_caches_combined_limit_kb",
|
||||
MediaMemoryCachesCombinedLimitKb,
|
||||
uint32_t, PREF_VALUE
|
||||
uint32_t, 524288
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// Don't create more memory-backed MediaCaches if their combined size would go
|
||||
// above this relative size limit (a percentage of physical memory).
|
||||
|
@ -427,9 +427,10 @@ impl NonCustomPropertyId {
|
||||
unsafe { ::std::mem::transmute(self.0 as i32) }
|
||||
}
|
||||
|
||||
/// Convert an `nsCSSPropertyID` into a `NonCustomPropertyId`.
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result<Self, ()> {
|
||||
pub fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result<Self, ()> {
|
||||
let prop = prop as i32;
|
||||
if prop < 0 {
|
||||
return Err(());
|
||||
@ -443,7 +444,7 @@ impl NonCustomPropertyId {
|
||||
|
||||
/// Get the property name.
|
||||
#[inline]
|
||||
fn name(self) -> &'static str {
|
||||
pub fn name(self) -> &'static str {
|
||||
static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [
|
||||
% for property in data.longhands + data.shorthands + data.all_aliases():
|
||||
"${property.name}",
|
||||
@ -1870,6 +1871,18 @@ impl PropertyId {
|
||||
id.enabled_for_all_content()
|
||||
}
|
||||
|
||||
/// Converts this PropertyId in nsCSSPropertyID, resolving aliases to the
|
||||
/// resolved property, and returning eCSSPropertyExtra_variable for custom
|
||||
/// properties.
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
pub fn to_nscsspropertyid_resolving_aliases(&self) -> nsCSSPropertyID {
|
||||
match self.non_custom_non_alias_id() {
|
||||
Some(id) => id.to_nscsspropertyid(),
|
||||
None => nsCSSPropertyID::eCSSPropertyExtra_variable,
|
||||
}
|
||||
}
|
||||
|
||||
fn allowed_in(&self, context: &ParserContext) -> bool {
|
||||
let id = match self.non_custom_id() {
|
||||
// Custom properties are allowed everywhere
|
||||
|
@ -925,6 +925,35 @@ pub extern "C" fn Servo_ResolveLogicalProperty(
|
||||
longhand.to_physical(style.writing_mode).to_nscsspropertyid()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_Property_LookupEnabledForAllContent(
|
||||
prop: *const nsACString,
|
||||
) -> nsCSSPropertyID {
|
||||
match PropertyId::parse_enabled_for_all_content((*prop).as_str_unchecked()) {
|
||||
Ok(p) => p.to_nscsspropertyid_resolving_aliases(),
|
||||
Err(..) => nsCSSPropertyID::eCSSProperty_UNKNOWN,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_Property_GetName(
|
||||
prop: nsCSSPropertyID,
|
||||
out_length: *mut u32,
|
||||
) -> *const u8 {
|
||||
use style::properties::NonCustomPropertyId;
|
||||
|
||||
let (ptr, len) = match NonCustomPropertyId::from_nscsspropertyid(prop) {
|
||||
Ok(p) => {
|
||||
let name = p.name();
|
||||
(name.as_bytes().as_ptr(), name.len())
|
||||
}
|
||||
Err(..) => (ptr::null(), 0),
|
||||
};
|
||||
|
||||
*out_length = len as u32;
|
||||
ptr
|
||||
}
|
||||
|
||||
macro_rules! parse_enabled_property_name {
|
||||
($prop_name:ident, $found:ident, $default:expr) => {{
|
||||
let prop_name = $prop_name.as_ref().unwrap().as_str_unchecked();
|
||||
|
@ -45,10 +45,10 @@ label.findbar-find-fast:-moz-lwtheme {
|
||||
|
||||
.findbar-button {
|
||||
-moz-appearance: none;
|
||||
border-width: @roundButtonBorderWidth@;
|
||||
margin-inline-end: 5px;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
background: none;
|
||||
padding: 2px 9px;
|
||||
border-radius: 10000px;
|
||||
}
|
||||
|
||||
.findbar-find-next:-moz-lwtheme,
|
||||
|
@ -42,12 +42,6 @@ findbar[noanim] {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.findbar-button {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Search field */
|
||||
|
||||
.findbar-textbox {
|
||||
|
Loading…
Reference in New Issue
Block a user