зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c
This commit is contained in:
Коммит
a5452f2660
|
@ -671,6 +671,9 @@ pref("plugin.default.state", 2);
|
||||||
pref("plugin.default.state", 1);
|
pref("plugin.default.state", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Plugins bundled in XPIs are enabled by default.
|
||||||
|
pref("plugin.defaultXpi.state", 2);
|
||||||
|
|
||||||
// Flash is enabled by default, and Java is click-to-activate by default on
|
// Flash is enabled by default, and Java is click-to-activate by default on
|
||||||
// all channels.
|
// all channels.
|
||||||
pref("plugin.state.flash", 2);
|
pref("plugin.state.flash", 2);
|
||||||
|
|
|
@ -11,7 +11,7 @@ interface nsIChannel;
|
||||||
interface nsIDocShell;
|
interface nsIDocShell;
|
||||||
interface nsIDomainPolicy;
|
interface nsIDomainPolicy;
|
||||||
|
|
||||||
[scriptable, uuid(3b6e408b-e774-4612-89e8-3ef303564392)]
|
[scriptable, uuid(4c087cc3-e0cc-4ec3-88df-8d68f3023b45)]
|
||||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -150,11 +150,6 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||||
*/
|
*/
|
||||||
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
|
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the principal of the specified object in the specified context.
|
|
||||||
*/
|
|
||||||
[implicit_jscontext] nsIPrincipal getObjectPrincipal(in jsval aObject);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the principal of the currently running script is the
|
* Returns true if the principal of the currently running script is the
|
||||||
* system principal, false otherwise.
|
* system principal, false otherwise.
|
||||||
|
|
|
@ -1118,18 +1118,6 @@ nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
||||||
return nsJSPrincipals::get(principals);
|
return nsJSPrincipals::get(principals);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsScriptSecurityManager::GetObjectPrincipal(JS::Handle<JS::Value> aObjectVal,
|
|
||||||
JSContext *aCx,
|
|
||||||
nsIPrincipal **result)
|
|
||||||
{
|
|
||||||
NS_ENSURE_TRUE(aObjectVal.isObject(), NS_ERROR_FAILURE);
|
|
||||||
JS::RootedObject obj(aCx, &aObjectVal.toObject());
|
|
||||||
nsCOMPtr<nsIPrincipal> principal = doGetObjectPrincipal(obj);
|
|
||||||
principal.forget(result);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsIPrincipal*
|
nsIPrincipal*
|
||||||
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
||||||
|
|
|
@ -101,7 +101,7 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||||
nsIContent* aOwner,
|
nsIContent* aOwner,
|
||||||
nsFrameMessageManager* aChrome)
|
nsFrameMessageManager* aChrome)
|
||||||
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
|
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
|
||||||
mDelayedDisconnect(false), mOwner(aOwner), mChromeMessageManager(aChrome)
|
mOwner(aOwner), mChromeMessageManager(aChrome)
|
||||||
{
|
{
|
||||||
|
|
||||||
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
||||||
|
@ -234,13 +234,6 @@ nsInProcessTabChildGlobal::DelayedDisconnect()
|
||||||
if (mListenerManager) {
|
if (mListenerManager) {
|
||||||
mListenerManager->Disconnect();
|
mListenerManager->Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mLoadingScript) {
|
|
||||||
ReleaseWrapper(static_cast<EventTarget*>(this));
|
|
||||||
mGlobal = nullptr;
|
|
||||||
} else {
|
|
||||||
mDelayedDisconnect = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(nsIContent *)
|
NS_IMETHODIMP_(nsIContent *)
|
||||||
|
@ -331,8 +324,4 @@ nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL, bool aRunInGlo
|
||||||
mLoadingScript = true;
|
mLoadingScript = true;
|
||||||
LoadFrameScriptInternal(aURL, aRunInGlobalScope);
|
LoadFrameScriptInternal(aURL, aRunInGlobalScope);
|
||||||
mLoadingScript = tmp;
|
mLoadingScript = tmp;
|
||||||
if (!mLoadingScript && mDelayedDisconnect) {
|
|
||||||
mDelayedDisconnect = false;
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,6 @@ protected:
|
||||||
nsCOMPtr<nsIDocShell> mDocShell;
|
nsCOMPtr<nsIDocShell> mDocShell;
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
bool mLoadingScript;
|
bool mLoadingScript;
|
||||||
bool mDelayedDisconnect;
|
|
||||||
|
|
||||||
// Is this the message manager for an in-process <iframe mozbrowser> or
|
// Is this the message manager for an in-process <iframe mozbrowser> or
|
||||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||||
|
|
|
@ -143,8 +143,9 @@ static const char *kPrefJavaMIME = "plugin.java.mime";
|
||||||
// 0.14 force refresh due to locale comparison fix, bug 611296
|
// 0.14 force refresh due to locale comparison fix, bug 611296
|
||||||
// 0.15 force refresh due to bug in reading Java plist MIME data, bug 638171
|
// 0.15 force refresh due to bug in reading Java plist MIME data, bug 638171
|
||||||
// 0.16 version bump to avoid importing the plugin flags in newer versions
|
// 0.16 version bump to avoid importing the plugin flags in newer versions
|
||||||
|
// 0.17 added flag on whether plugin is loaded from an XPI
|
||||||
// The current plugin registry version (and the maximum version we know how to read)
|
// The current plugin registry version (and the maximum version we know how to read)
|
||||||
static const char *kPluginRegistryVersion = "0.16";
|
static const char *kPluginRegistryVersion = "0.17";
|
||||||
// The minimum registry version we know how to read
|
// The minimum registry version we know how to read
|
||||||
static const char *kMinimumRegistryVersion = "0.9";
|
static const char *kMinimumRegistryVersion = "0.9";
|
||||||
|
|
||||||
|
@ -1627,6 +1628,62 @@ int64_t GetPluginLastModifiedTime(const nsCOMPtr<nsIFile>& localfile)
|
||||||
return fileModTime;
|
return fileModTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GetPluginIsFromExtension(const nsCOMPtr<nsIFile>& pluginFile,
|
||||||
|
const nsCOMPtr<nsISimpleEnumerator>& extensionDirs)
|
||||||
|
{
|
||||||
|
if (!extensionDirs) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasMore;
|
||||||
|
while (NS_SUCCEEDED(extensionDirs->HasMoreElements(&hasMore)) && hasMore) {
|
||||||
|
nsCOMPtr<nsISupports> supports;
|
||||||
|
nsresult rv = extensionDirs->GetNext(getter_AddRefs(supports));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> extDir(do_QueryInterface(supports, &rv));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> dir;
|
||||||
|
if (NS_FAILED(extDir->Clone(getter_AddRefs(dir)))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains;
|
||||||
|
if (NS_FAILED(dir->Contains(pluginFile, true, &contains)) || !contains) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsISimpleEnumerator>
|
||||||
|
GetExtensionDirectories()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||||
|
if (!dirService) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> list;
|
||||||
|
nsresult rv = dirService->Get(XRE_EXTENSIONS_DIR_LIST,
|
||||||
|
NS_GET_IID(nsISimpleEnumerator),
|
||||||
|
getter_AddRefs(list));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
struct CompareFilesByTime
|
struct CompareFilesByTime
|
||||||
{
|
{
|
||||||
bool
|
bool
|
||||||
|
@ -1690,6 +1747,11 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||||
|
|
||||||
pluginFiles.Sort(CompareFilesByTime());
|
pluginFiles.Sort(CompareFilesByTime());
|
||||||
|
|
||||||
|
nsCOMPtr<nsISimpleEnumerator> extensionDirs = GetExtensionDirectories();
|
||||||
|
if (!extensionDirs) {
|
||||||
|
PLUGIN_LOG(PLUGIN_LOG_ALWAYS, ("Could not get extension directories."));
|
||||||
|
}
|
||||||
|
|
||||||
bool warnOutdated = false;
|
bool warnOutdated = false;
|
||||||
|
|
||||||
for (int32_t i = (pluginFiles.Length() - 1); i >= 0; i--) {
|
for (int32_t i = (pluginFiles.Length() - 1); i >= 0; i--) {
|
||||||
|
@ -1700,7 +1762,8 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int64_t fileModTime = GetPluginLastModifiedTime(localfile);
|
const int64_t fileModTime = GetPluginLastModifiedTime(localfile);
|
||||||
|
const bool fromExtension = GetPluginIsFromExtension(localfile, extensionDirs);
|
||||||
|
|
||||||
// Look for it in our cache
|
// Look for it in our cache
|
||||||
NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
|
NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
|
||||||
|
@ -1781,7 +1844,7 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginTag = new nsPluginTag(&info, fileModTime);
|
pluginTag = new nsPluginTag(&info, fileModTime, fromExtension);
|
||||||
pluginFile.FreePluginInfo(info);
|
pluginFile.FreePluginInfo(info);
|
||||||
if (!pluginTag)
|
if (!pluginTag)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
@ -2272,14 +2335,16 @@ nsPluginHost::WritePluginInfo()
|
||||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||||
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
||||||
|
|
||||||
// lastModifiedTimeStamp|canUnload|tag->mFlags
|
// lastModifiedTimeStamp|canUnload|tag->mFlags|fromExtension
|
||||||
PR_fprintf(fd, "%lld%c%d%c%lu%c%c\n",
|
PR_fprintf(fd, "%lld%c%d%c%lu%c%d%c%c\n",
|
||||||
tag->mLastModifiedTime,
|
tag->mLastModifiedTime,
|
||||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||||
false, // did store whether or not to unload in-process plugins
|
false, // did store whether or not to unload in-process plugins
|
||||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||||
0, // legacy field for flags
|
0, // legacy field for flags
|
||||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||||
|
tag->IsFromExtension(),
|
||||||
|
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||||
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
||||||
|
|
||||||
//description, name & mtypecount are on separate line
|
//description, name & mtypecount are on separate line
|
||||||
|
@ -2486,20 +2551,23 @@ nsPluginHost::ReadPluginInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registry v0.13 and upwards includes the list of invalid plugins
|
// Registry v0.13 and upwards includes the list of invalid plugins
|
||||||
bool hasInvalidPlugins = (version >= "0.13");
|
const bool hasInvalidPlugins = (version >= "0.13");
|
||||||
|
|
||||||
// Registry v0.16 and upwards always have 0 for their plugin flags, prefs are used instead
|
// Registry v0.16 and upwards always have 0 for their plugin flags, prefs are used instead
|
||||||
const bool hasValidFlags = (version < "0.16");
|
const bool hasValidFlags = (version < "0.16");
|
||||||
|
|
||||||
if (!ReadSectionHeader(reader, "PLUGINS"))
|
// Registry v0.17 and upwards store whether the plugin comes from an XPI.
|
||||||
return rv;
|
const bool hasFromExtension = (version >= "0.17");
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
bool hasFullPathInFileNameField = false;
|
const bool hasFullPathInFileNameField = false;
|
||||||
#else
|
#else
|
||||||
bool hasFullPathInFileNameField = (version < "0.11");
|
const bool hasFullPathInFileNameField = (version < "0.11");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!ReadSectionHeader(reader, "PLUGINS"))
|
||||||
|
return rv;
|
||||||
|
|
||||||
while (reader.NextLine()) {
|
while (reader.NextLine()) {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
const char *fullpath;
|
const char *fullpath;
|
||||||
|
@ -2545,13 +2613,18 @@ nsPluginHost::ReadPluginInfo()
|
||||||
version = "0";
|
version = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
// lastModifiedTimeStamp|canUnload|tag.mFlag
|
// lastModifiedTimeStamp|canUnload|tag.mFlag|fromExtension
|
||||||
if (reader.ParseLine(values, 3) != 3)
|
const int count = hasFromExtension ? 4 : 3;
|
||||||
|
if (reader.ParseLine(values, count) != count)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
// If this is an old plugin registry mark this plugin tag to be refreshed
|
// If this is an old plugin registry mark this plugin tag to be refreshed
|
||||||
int64_t lastmod = (vdiff == 0) ? nsCRT::atoll(values[0]) : -1;
|
int64_t lastmod = (vdiff == 0) ? nsCRT::atoll(values[0]) : -1;
|
||||||
uint32_t tagflag = atoi(values[2]);
|
uint32_t tagflag = atoi(values[2]);
|
||||||
|
bool fromExtension = false;
|
||||||
|
if (hasFromExtension) {
|
||||||
|
fromExtension = atoi(values[3]);
|
||||||
|
}
|
||||||
if (!reader.NextLine())
|
if (!reader.NextLine())
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
|
@ -2622,7 +2695,7 @@ nsPluginHost::ReadPluginInfo()
|
||||||
(const char* const*)mimetypes,
|
(const char* const*)mimetypes,
|
||||||
(const char* const*)mimedescriptions,
|
(const char* const*)mimedescriptions,
|
||||||
(const char* const*)extensions,
|
(const char* const*)extensions,
|
||||||
mimetypecount, lastmod, true);
|
mimetypecount, lastmod, fromExtension, true);
|
||||||
if (heapalloced)
|
if (heapalloced)
|
||||||
delete [] heapalloced;
|
delete [] heapalloced;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ using namespace mozilla;
|
||||||
// no longer used 0x0008 // reuse only if regenerating pluginreg.dat
|
// no longer used 0x0008 // reuse only if regenerating pluginreg.dat
|
||||||
#define NS_PLUGIN_FLAG_CLICKTOPLAY 0x0020 // this is a click-to-play plugin
|
#define NS_PLUGIN_FLAG_CLICKTOPLAY 0x0020 // this is a click-to-play plugin
|
||||||
|
|
||||||
|
static const char kPrefDefaultEnabledState[] = "plugin.default.state";
|
||||||
|
static const char kPrefDefaultEnabledStateXpi[] = "plugin.defaultXpi.state";
|
||||||
|
|
||||||
inline char* new_str(const char* str)
|
inline char* new_str(const char* str)
|
||||||
{
|
{
|
||||||
if (str == nullptr)
|
if (str == nullptr)
|
||||||
|
@ -62,7 +65,9 @@ GetStatePrefNameForPlugin(nsPluginTag* aTag)
|
||||||
|
|
||||||
/* nsPluginTag */
|
/* nsPluginTag */
|
||||||
|
|
||||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime)
|
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
|
||||||
|
int64_t aLastModifiedTime,
|
||||||
|
bool fromExtension)
|
||||||
: mName(aPluginInfo->fName),
|
: mName(aPluginInfo->fName),
|
||||||
mDescription(aPluginInfo->fDescription),
|
mDescription(aPluginInfo->fDescription),
|
||||||
mLibrary(nullptr),
|
mLibrary(nullptr),
|
||||||
|
@ -74,7 +79,8 @@ nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime)
|
||||||
mLastModifiedTime(aLastModifiedTime),
|
mLastModifiedTime(aLastModifiedTime),
|
||||||
mNiceFileName(),
|
mNiceFileName(),
|
||||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||||
mCachedBlocklistStateValid(false)
|
mCachedBlocklistStateValid(false),
|
||||||
|
mIsFromExtension(fromExtension)
|
||||||
{
|
{
|
||||||
InitMime(aPluginInfo->fMimeTypeArray,
|
InitMime(aPluginInfo->fMimeTypeArray,
|
||||||
aPluginInfo->fMimeDescriptionArray,
|
aPluginInfo->fMimeDescriptionArray,
|
||||||
|
@ -94,6 +100,7 @@ nsPluginTag::nsPluginTag(const char* aName,
|
||||||
const char* const* aExtensions,
|
const char* const* aExtensions,
|
||||||
int32_t aVariants,
|
int32_t aVariants,
|
||||||
int64_t aLastModifiedTime,
|
int64_t aLastModifiedTime,
|
||||||
|
bool fromExtension,
|
||||||
bool aArgsAreUTF8)
|
bool aArgsAreUTF8)
|
||||||
: mName(aName),
|
: mName(aName),
|
||||||
mDescription(aDescription),
|
mDescription(aDescription),
|
||||||
|
@ -106,7 +113,8 @@ nsPluginTag::nsPluginTag(const char* aName,
|
||||||
mLastModifiedTime(aLastModifiedTime),
|
mLastModifiedTime(aLastModifiedTime),
|
||||||
mNiceFileName(),
|
mNiceFileName(),
|
||||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||||
mCachedBlocklistStateValid(false)
|
mCachedBlocklistStateValid(false),
|
||||||
|
mIsFromExtension(fromExtension)
|
||||||
{
|
{
|
||||||
InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
|
InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
|
||||||
static_cast<uint32_t>(aVariants));
|
static_cast<uint32_t>(aVariants));
|
||||||
|
@ -365,8 +373,10 @@ nsPluginTag::GetEnabledState(uint32_t *aEnabledState) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledState = Preferences::GetInt("plugin.default.state",
|
const char* const pref = mIsFromExtension ? kPrefDefaultEnabledStateXpi
|
||||||
nsIPluginTag::STATE_ENABLED);
|
: kPrefDefaultEnabledState;
|
||||||
|
|
||||||
|
enabledState = Preferences::GetInt(pref, nsIPluginTag::STATE_ENABLED);
|
||||||
if (enabledState >= nsIPluginTag::STATE_DISABLED &&
|
if (enabledState >= nsIPluginTag::STATE_DISABLED &&
|
||||||
enabledState <= nsIPluginTag::STATE_ENABLED) {
|
enabledState <= nsIPluginTag::STATE_ENABLED) {
|
||||||
*aEnabledState = (uint32_t)enabledState;
|
*aEnabledState = (uint32_t)enabledState;
|
||||||
|
@ -574,3 +584,8 @@ nsPluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime)
|
||||||
*aLastModifiedTime = mLastModifiedTime;
|
*aLastModifiedTime = mLastModifiedTime;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsPluginTag::IsFromExtension() const
|
||||||
|
{
|
||||||
|
return mIsFromExtension;
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,9 @@ public:
|
||||||
ePluginState_MaxValue = 3,
|
ePluginState_MaxValue = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime);
|
nsPluginTag(nsPluginInfo* aPluginInfo,
|
||||||
|
int64_t aLastModifiedTime,
|
||||||
|
bool fromExtension);
|
||||||
nsPluginTag(const char* aName,
|
nsPluginTag(const char* aName,
|
||||||
const char* aDescription,
|
const char* aDescription,
|
||||||
const char* aFileName,
|
const char* aFileName,
|
||||||
|
@ -47,6 +49,7 @@ public:
|
||||||
const char* const* aExtensions,
|
const char* const* aExtensions,
|
||||||
int32_t aVariants,
|
int32_t aVariants,
|
||||||
int64_t aLastModifiedTime,
|
int64_t aLastModifiedTime,
|
||||||
|
bool fromExtension,
|
||||||
bool aArgsAreUTF8 = false);
|
bool aArgsAreUTF8 = false);
|
||||||
virtual ~nsPluginTag();
|
virtual ~nsPluginTag();
|
||||||
|
|
||||||
|
@ -69,6 +72,8 @@ public:
|
||||||
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
|
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
|
||||||
nsCString GetNiceFileName();
|
nsCString GetNiceFileName();
|
||||||
|
|
||||||
|
bool IsFromExtension() const;
|
||||||
|
|
||||||
nsRefPtr<nsPluginTag> mNext;
|
nsRefPtr<nsPluginTag> mNext;
|
||||||
nsCString mName; // UTF-8
|
nsCString mName; // UTF-8
|
||||||
nsCString mDescription; // UTF-8
|
nsCString mDescription; // UTF-8
|
||||||
|
@ -92,6 +97,7 @@ private:
|
||||||
nsCString mNiceFileName; // UTF-8
|
nsCString mNiceFileName; // UTF-8
|
||||||
uint16_t mCachedBlocklistState;
|
uint16_t mCachedBlocklistState;
|
||||||
bool mCachedBlocklistStateValid;
|
bool mCachedBlocklistStateValid;
|
||||||
|
bool mIsFromExtension;
|
||||||
|
|
||||||
void InitMime(const char* const* aMimeTypes,
|
void InitMime(const char* const* aMimeTypes,
|
||||||
const char* const* aMimeDescriptions,
|
const char* const* aMimeDescriptions,
|
||||||
|
|
|
@ -309,6 +309,7 @@ PluginHangUIChild::HangUIDlgProc(HWND aDlgHandle, UINT aMsgCode, WPARAM aWParam,
|
||||||
}
|
}
|
||||||
case WM_DESTROY: {
|
case WM_DESTROY: {
|
||||||
EnableWindow(mParentWindow, TRUE);
|
EnableWindow(mParentWindow, TRUE);
|
||||||
|
SetForegroundWindow(mParentWindow);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -19,6 +19,9 @@ skip-if = !crashreporter
|
||||||
skip-if = !crashreporter
|
skip-if = !crashreporter
|
||||||
[test_hang_submit.xul]
|
[test_hang_submit.xul]
|
||||||
skip-if = !crashreporter
|
skip-if = !crashreporter
|
||||||
|
[test_hangui.xul]
|
||||||
|
skip-if = (!crashreporter) || (os != "win")
|
||||||
|
support-files = hangui_subpage.html hangui_common.js hangui_iface.js dialog_watcher.js
|
||||||
[test_idle_hang.xul]
|
[test_idle_hang.xul]
|
||||||
skip-if = (!crashreporter) || (os != "win")
|
skip-if = (!crashreporter) || (os != "win")
|
||||||
[test_npruntime.xul]
|
[test_npruntime.xul]
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
const EVENT_OBJECT_SHOW = 0x8002;
|
||||||
|
const EVENT_OBJECT_HIDE = 0x8003;
|
||||||
|
const WINEVENT_OUTOFCONTEXT = 0;
|
||||||
|
const WINEVENT_SKIPOWNPROCESS = 2;
|
||||||
|
const QS_ALLINPUT = 0x04FF;
|
||||||
|
const INFINITE = 0xFFFFFFFF;
|
||||||
|
const WAIT_OBJECT_0 = 0;
|
||||||
|
const WAIT_TIMEOUT = 258;
|
||||||
|
const PM_NOREMOVE = 0;
|
||||||
|
|
||||||
|
function DialogWatcher(titleText, onDialogStart, onDialogEnd) {
|
||||||
|
this.titleText = titleText;
|
||||||
|
this.onDialogStart = onDialogStart;
|
||||||
|
this.onDialogEnd = onDialogEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogWatcher.prototype.init = function() {
|
||||||
|
this.hwnd = undefined;
|
||||||
|
if (!this.user32) {
|
||||||
|
this.user32 = ctypes.open("user32.dll");
|
||||||
|
}
|
||||||
|
if (!this.findWindow) {
|
||||||
|
this.findWindow = user32.declare("FindWindowW",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.jschar.ptr,
|
||||||
|
ctypes.jschar.ptr);
|
||||||
|
}
|
||||||
|
if (!this.winEventProcType) {
|
||||||
|
this.winEventProcType = ctypes.FunctionType(ctypes.stdcall_abi,
|
||||||
|
ctypes.void_t,
|
||||||
|
[ctypes.uintptr_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.long,
|
||||||
|
ctypes.long,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t]).ptr;
|
||||||
|
}
|
||||||
|
if (!this.setWinEventHook) {
|
||||||
|
this.setWinEventHook = user32.declare("SetWinEventHook",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
this.winEventProcType,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t);
|
||||||
|
}
|
||||||
|
if (!this.unhookWinEvent) {
|
||||||
|
this.unhookWinEvent = user32.declare("UnhookWinEvent",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.int,
|
||||||
|
ctypes.uintptr_t);
|
||||||
|
}
|
||||||
|
if (!this.pointType) {
|
||||||
|
this.pointType = ctypes.StructType("tagPOINT",
|
||||||
|
[ { "x": ctypes.long },
|
||||||
|
{ "y": ctypes.long } ] );
|
||||||
|
}
|
||||||
|
if (!this.msgType) {
|
||||||
|
this.msgType = ctypes.StructType("tagMSG",
|
||||||
|
[ { "hwnd": ctypes.uintptr_t },
|
||||||
|
{ "message": ctypes.uint32_t },
|
||||||
|
{ "wParam": ctypes.uintptr_t },
|
||||||
|
{ "lParam": ctypes.intptr_t },
|
||||||
|
{ "time": ctypes.uint32_t },
|
||||||
|
{ "pt": this.pointType } ] );
|
||||||
|
}
|
||||||
|
if (!this.peekMessage) {
|
||||||
|
this.peekMessage = user32.declare("PeekMessageW",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.int,
|
||||||
|
this.msgType.ptr,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t);
|
||||||
|
}
|
||||||
|
if (!this.msgWaitForMultipleObjects) {
|
||||||
|
this.msgWaitForMultipleObjects = user32.declare("MsgWaitForMultipleObjects",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uintptr_t.ptr,
|
||||||
|
ctypes.int,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uint32_t);
|
||||||
|
}
|
||||||
|
if (!this.getWindowTextW) {
|
||||||
|
this.getWindowTextW = user32.declare("GetWindowTextW",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.int,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.jschar.ptr,
|
||||||
|
ctypes.int);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DialogWatcher.prototype.getWindowText = function(hwnd) {
|
||||||
|
var bufType = ctypes.ArrayType(ctypes.jschar);
|
||||||
|
var buffer = new bufType(256);
|
||||||
|
|
||||||
|
if (this.getWindowTextW(hwnd, buffer, buffer.length)) {
|
||||||
|
return buffer.readString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DialogWatcher.prototype.processWindowEvents = function(timeout) {
|
||||||
|
var onWinEvent = function(self, hook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
|
||||||
|
var nhwnd = Number(hwnd)
|
||||||
|
if (event == EVENT_OBJECT_SHOW) {
|
||||||
|
if (nhwnd == self.hwnd) {
|
||||||
|
// We've already picked up this event via FindWindow
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var windowText = self.getWindowText(hwnd);
|
||||||
|
if (windowText == self.titleText && self.onDialogStart) {
|
||||||
|
self.hwnd = nhwnd;
|
||||||
|
self.onDialogStart(nhwnd);
|
||||||
|
}
|
||||||
|
} else if (event == EVENT_OBJECT_HIDE && nhwnd == self.hwnd && self.onDialogEnd) {
|
||||||
|
self.onDialogEnd();
|
||||||
|
self.hwnd = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var self = this;
|
||||||
|
var callback = this.winEventProcType(function(hook, event, hwnd, idObject,
|
||||||
|
idChild, dwEventThread,
|
||||||
|
dwmsEventTime) {
|
||||||
|
onWinEvent(self, hook, event, hwnd, idObject, idChild, dwEventThread,
|
||||||
|
dwmsEventTime);
|
||||||
|
} );
|
||||||
|
var hook = this.setWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE,
|
||||||
|
0, callback, 0, 0,
|
||||||
|
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||||
|
if (!hook) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if the window is already showing
|
||||||
|
var hwnd = this.findWindow(null, this.titleText);
|
||||||
|
if (hwnd && hwnd > 0) {
|
||||||
|
this.hwnd = Number(hwnd);
|
||||||
|
if (this.onDialogStart) {
|
||||||
|
this.onDialogStart(this.hwnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeout) {
|
||||||
|
timeout = INFINITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
var waitStatus = WAIT_OBJECT_0;
|
||||||
|
var expectingStart = this.onDialogStart && this.hwnd === undefined;
|
||||||
|
while (this.hwnd === undefined || this.onDialogEnd && this.hwnd) {
|
||||||
|
waitStatus = this.msgWaitForMultipleObjects(0, null, 0, expectingStart ?
|
||||||
|
INFINITE : timeout, 0);
|
||||||
|
if (waitStatus == WAIT_OBJECT_0) {
|
||||||
|
var msg = new this.msgType;
|
||||||
|
this.peekMessage(msg.address(), 0, 0, 0, PM_NOREMOVE);
|
||||||
|
} else if (waitStatus == WAIT_TIMEOUT) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unhookWinEvent(hook);
|
||||||
|
// Returns true if the hook was successful, something was found, and we never timed out
|
||||||
|
return this.hwnd !== undefined && waitStatus == WAIT_OBJECT_0;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Plugin Hang UI constants
|
||||||
|
const HANGUIOP_NOTHING = 0;
|
||||||
|
const HANGUIOP_CANCEL = 1;
|
||||||
|
const HANGUIOP_COMMAND = 2;
|
||||||
|
const IDC_CONTINUE = 1001;
|
||||||
|
const IDC_STOP = 1002;
|
||||||
|
const IDC_NOFUTURE = 1003;
|
||||||
|
|
||||||
|
// Windows constants
|
||||||
|
const WM_CLOSE = 0x0010;
|
||||||
|
const WM_COMMAND = 0x0111;
|
||||||
|
const BM_GETCHECK = 0x00F0;
|
||||||
|
const BM_SETCHECK = 0x00F1;
|
||||||
|
const BN_CLICKED = 0;
|
||||||
|
const BST_CHECKED = 1;
|
||||||
|
|
||||||
|
// Test-specific constants
|
||||||
|
const EPSILON_MS = 1000;
|
||||||
|
const STALL_DURATION = 2;
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
var user32;
|
||||||
|
var sendMessage;
|
||||||
|
var getDlgItem;
|
||||||
|
var messageBox;
|
||||||
|
var watcher;
|
||||||
|
|
||||||
|
importScripts("hangui_common.js");
|
||||||
|
importScripts("dialog_watcher.js");
|
||||||
|
|
||||||
|
function initCTypes() {
|
||||||
|
if (!user32) {
|
||||||
|
user32 = ctypes.open("user32.dll");
|
||||||
|
}
|
||||||
|
if (!getDlgItem) {
|
||||||
|
getDlgItem = user32.declare("GetDlgItem",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.int);
|
||||||
|
}
|
||||||
|
if (!sendMessage) {
|
||||||
|
sendMessage = user32.declare("SendMessageW",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.intptr_t,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.uint32_t,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.intptr_t);
|
||||||
|
}
|
||||||
|
if (!messageBox) {
|
||||||
|
// Handy for debugging the test itself
|
||||||
|
messageBox = user32.declare("MessageBoxW",
|
||||||
|
ctypes.winapi_abi,
|
||||||
|
ctypes.int,
|
||||||
|
ctypes.uintptr_t,
|
||||||
|
ctypes.jschar.ptr,
|
||||||
|
ctypes.jschar.ptr,
|
||||||
|
ctypes.uint32_t);
|
||||||
|
}
|
||||||
|
if (!watcher) {
|
||||||
|
watcher = new DialogWatcher("Warning: Unresponsive plugin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function postSuccess(params) {
|
||||||
|
self.postMessage({"status": true, "params": params});
|
||||||
|
}
|
||||||
|
|
||||||
|
function postFail(params, msg) {
|
||||||
|
self.postMessage({"status": false, "params": params, "msg": msg});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDialogStart(inparams, hwnd) {
|
||||||
|
var params = Object.create(inparams);
|
||||||
|
params.testName += " (Start)";
|
||||||
|
params.callback = null;
|
||||||
|
if (!params.expectToFind) {
|
||||||
|
postFail(params, "Dialog showed when we weren't expecting it to!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (params.opCode == HANGUIOP_CANCEL) {
|
||||||
|
sendMessage(hwnd, WM_CLOSE, 0, 0);
|
||||||
|
} else if (params.opCode == HANGUIOP_COMMAND) {
|
||||||
|
if (params.check) {
|
||||||
|
var checkbox = getDlgItem(hwnd, IDC_NOFUTURE);
|
||||||
|
if (!checkbox) {
|
||||||
|
postFail(params, "Couldn't find checkbox");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendMessage(checkbox, BM_SETCHECK, BST_CHECKED, 0);
|
||||||
|
sendMessage(hwnd, WM_COMMAND, (BN_CLICKED << 16) | IDC_NOFUTURE, checkbox);
|
||||||
|
}
|
||||||
|
var button = getDlgItem(hwnd, params.commandId);
|
||||||
|
if (!button) {
|
||||||
|
postFail(params,
|
||||||
|
"GetDlgItem failed to find button with ID " + params.commandId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendMessage(hwnd, WM_COMMAND, (BN_CLICKED << 16) | params.commandId, button);
|
||||||
|
}
|
||||||
|
postSuccess(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDialogEnd(inparams) {
|
||||||
|
var params = Object.create(inparams);
|
||||||
|
params.testName += " (End)";
|
||||||
|
params.callback = inparams.callback;
|
||||||
|
postSuccess(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.onmessage = function(event) {
|
||||||
|
initCTypes();
|
||||||
|
watcher.init();
|
||||||
|
var params = event.data;
|
||||||
|
var timeout = params.timeoutMs;
|
||||||
|
if (params.expectToFind) {
|
||||||
|
watcher.onDialogStart = function(hwnd) { onDialogStart(params, hwnd); };
|
||||||
|
if (params.expectToClose) {
|
||||||
|
watcher.onDialogEnd = function() { onDialogEnd(params); };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
watcher.onDialogStart = null;
|
||||||
|
watcher.onDialogEnd = null;
|
||||||
|
}
|
||||||
|
var result = watcher.processWindowEvents(timeout);
|
||||||
|
if (result === null) {
|
||||||
|
postFail(params, "Hook failed");
|
||||||
|
} else if (!result) {
|
||||||
|
if (params.expectToFind) {
|
||||||
|
postFail(params, "The dialog didn't show but we were expecting it to");
|
||||||
|
} else {
|
||||||
|
postSuccess(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.onerror = function(event) {
|
||||||
|
var msg = "Error: " + event.message + " at " + event.filename + ":" + event.lineno;
|
||||||
|
postFail(null, msg);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<html>
|
||||||
|
<body onload="window.parent.frameLoaded()">
|
||||||
|
<embed id="plugin1" type="application/x-test" width="400" height="400"></embed>
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||||
|
type="text/css"?>
|
||||||
|
<window title="Basic Plugin Tests"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<title>Plugin Hang UI Test</title>
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="http://mochi.test:8888/chrome/dom/plugins/test/mochitest/hang_test.js" />
|
||||||
|
<script type="application/javascript"
|
||||||
|
src="http://mochi.test:8888/chrome/dom/plugins/test/mochitest/hangui_common.js" />
|
||||||
|
|
||||||
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<iframe id="iframe1" src="hangui_subpage.html" width="400" height="400"></iframe>
|
||||||
|
</body>
|
||||||
|
<script class="testbody" type="application/javascript">
|
||||||
|
<![CDATA[
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
const hangUITimeoutPref = "dom.ipc.plugins.hangUITimeoutSecs";
|
||||||
|
const hangUIMinDisplayPref = "dom.ipc.plugins.hangUIMinDisplaySecs";
|
||||||
|
const timeoutPref = "dom.ipc.plugins.timeoutSecs";
|
||||||
|
|
||||||
|
var worker = new ChromeWorker("hangui_iface.js");
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
var result = event.data;
|
||||||
|
var params = result.params;
|
||||||
|
var output = params.testName;
|
||||||
|
if (result.msg) {
|
||||||
|
output += ": " + result.msg;
|
||||||
|
}
|
||||||
|
ok(result.status, output);
|
||||||
|
if (params.callback) {
|
||||||
|
var cb = eval(params.callback);
|
||||||
|
var timeout = setTimeout(function() { clearTimeout(timeout); cb(); }, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
worker.onerror = function(event) {
|
||||||
|
var output = "Error: " + event.message + " at " + event.filename + ":" + event.lineno;
|
||||||
|
ok(false, output);
|
||||||
|
};
|
||||||
|
|
||||||
|
var iframe;
|
||||||
|
var p;
|
||||||
|
var os = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
|
||||||
|
|
||||||
|
function hanguiOperation(testName, timeoutSec, expectFind, expectClose, opCode,
|
||||||
|
commandId, check, cb) {
|
||||||
|
var timeoutMs = timeoutSec * 1000 + EPSILON_MS;
|
||||||
|
worker.postMessage({ "timeoutMs": timeoutMs, "expectToFind": expectFind,
|
||||||
|
"expectToClose": expectClose, "opCode": opCode,
|
||||||
|
"commandId": commandId, "check": check,
|
||||||
|
"testName": testName, "callback": cb });
|
||||||
|
}
|
||||||
|
|
||||||
|
function hanguiExpect(testName, shouldBeShowing, shouldClose, cb) {
|
||||||
|
var timeoutSec = Services.prefs.getIntPref(hangUITimeoutPref);
|
||||||
|
if (!shouldBeShowing && !timeoutSec) {
|
||||||
|
timeoutSec = Services.prefs.getIntPref(timeoutPref);
|
||||||
|
}
|
||||||
|
hanguiOperation(testName, timeoutSec, shouldBeShowing, shouldClose, HANGUIOP_NOTHING, 0, false, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hanguiContinue(testName, check, cb) {
|
||||||
|
var timeoutSec = Services.prefs.getIntPref(hangUITimeoutPref);
|
||||||
|
hanguiOperation(testName, timeoutSec, true, true, HANGUIOP_COMMAND, IDC_CONTINUE, check, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hanguiStop(testName, check, cb) {
|
||||||
|
var timeoutSec = Services.prefs.getIntPref(hangUITimeoutPref);
|
||||||
|
hanguiOperation(testName, timeoutSec, true, true, HANGUIOP_COMMAND, IDC_STOP, check, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hanguiCancel(testName, cb) {
|
||||||
|
var timeoutSec = Services.prefs.getIntPref(hangUITimeoutPref);
|
||||||
|
hanguiOperation(testName, timeoutSec, true, true, HANGUIOP_CANCEL, 0, false, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishTest() {
|
||||||
|
if (obsCount > 0) {
|
||||||
|
os.removeObserver(testObserver, "plugin-crashed");
|
||||||
|
--obsCount;
|
||||||
|
}
|
||||||
|
SpecialPowers.clearUserPref(hangUITimeoutPref);
|
||||||
|
SpecialPowers.clearUserPref(hangUIMinDisplayPref);
|
||||||
|
SpecialPowers.clearUserPref(timeoutPref);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
if (!SimpleTest.testPluginIsOOP()) {
|
||||||
|
ok(true, "Skipping this test when test plugin is not OOP.");
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetVars();
|
||||||
|
|
||||||
|
hanguiExpect("Prime ChromeWorker", false, false, "test1");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.frameLoaded = runTests;
|
||||||
|
|
||||||
|
var obsCount = 0;
|
||||||
|
|
||||||
|
function onPluginCrashedHangUI(aEvent) {
|
||||||
|
ok(true, "Plugin crashed notification received");
|
||||||
|
is(aEvent.type, "PluginCrashed", "event is correct type");
|
||||||
|
|
||||||
|
is(p, aEvent.target, "Plugin crashed event target is plugin element");
|
||||||
|
|
||||||
|
ok(aEvent instanceof Components.interfaces.nsIDOMCustomEvent,
|
||||||
|
"plugin crashed event has the right interface");
|
||||||
|
|
||||||
|
var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
|
||||||
|
var pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
|
||||||
|
isnot(pluginDumpID, "", "got a non-empty dump ID");
|
||||||
|
var pluginName = propBag.getPropertyAsAString("pluginName");
|
||||||
|
is(pluginName, "Test Plug-in", "got correct plugin name");
|
||||||
|
var pluginFilename = propBag.getPropertyAsAString("pluginFilename");
|
||||||
|
isnot(pluginFilename, "", "got a non-empty filename");
|
||||||
|
var didReport = propBag.getPropertyAsBool("submittedCrashReport");
|
||||||
|
// The app itself may or may not have decided to submit the report, so
|
||||||
|
// allow either true or false here.
|
||||||
|
ok((didReport == true || didReport == false), "event said crash report was submitted");
|
||||||
|
os.removeObserver(testObserver, "plugin-crashed");
|
||||||
|
--obsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetVars() {
|
||||||
|
iframe = document.getElementById('iframe1');
|
||||||
|
p = iframe.contentDocument.getElementById("plugin1");
|
||||||
|
if (obsCount == 0) {
|
||||||
|
os.addObserver(testObserver, "plugin-crashed", true);
|
||||||
|
++obsCount;
|
||||||
|
}
|
||||||
|
iframe.contentDocument.addEventListener("PluginCrashed",
|
||||||
|
onPluginCrashedHangUI,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test9b() {
|
||||||
|
hanguiExpect("test9b: Plugin Hang UI is not showing (checkbox)", false);
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
hanguiExpect("test9b: Plugin Hang UI is still not showing (checkbox)", false, false, "finishTest");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test9a() {
|
||||||
|
resetVars();
|
||||||
|
SpecialPowers.setIntPref(hangUITimeoutPref, 1);
|
||||||
|
SpecialPowers.setIntPref(hangUIMinDisplayPref, 1);
|
||||||
|
SpecialPowers.setIntPref(timeoutPref, 45);
|
||||||
|
hanguiContinue("test9a: Continue button works with checkbox", true, "test9b");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test9() {
|
||||||
|
window.frameLoaded = test9a;
|
||||||
|
iframe.contentWindow.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test8a() {
|
||||||
|
resetVars();
|
||||||
|
SpecialPowers.setIntPref(hangUITimeoutPref, 1);
|
||||||
|
SpecialPowers.setIntPref(hangUIMinDisplayPref, 4);
|
||||||
|
hanguiExpect("test8a: Plugin Hang UI is not showing (disabled due to hangUIMinDisplaySecs)", false, false, "test9");
|
||||||
|
var exceptionThrown = false;
|
||||||
|
try {
|
||||||
|
p.hang();
|
||||||
|
} catch(e) {
|
||||||
|
exceptionThrown = true;
|
||||||
|
}
|
||||||
|
ok(exceptionThrown, "test8a: Exception thrown from hang() when plugin was terminated");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test8() {
|
||||||
|
window.frameLoaded = test8a;
|
||||||
|
iframe.contentWindow.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test7a() {
|
||||||
|
resetVars();
|
||||||
|
SpecialPowers.setIntPref(hangUITimeoutPref, 0);
|
||||||
|
hanguiExpect("test7a: Plugin Hang UI is not showing (disabled)", false, false, "test8");
|
||||||
|
var exceptionThrown = false;
|
||||||
|
try {
|
||||||
|
p.hang();
|
||||||
|
} catch(e) {
|
||||||
|
exceptionThrown = true;
|
||||||
|
}
|
||||||
|
ok(exceptionThrown, "test7a: Exception thrown from hang() when plugin was terminated");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test7() {
|
||||||
|
window.frameLoaded = test7a;
|
||||||
|
iframe.contentWindow.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test6() {
|
||||||
|
SpecialPowers.setIntPref(hangUITimeoutPref, 1);
|
||||||
|
SpecialPowers.setIntPref(hangUIMinDisplayPref, 1);
|
||||||
|
SpecialPowers.setIntPref(timeoutPref, 3);
|
||||||
|
hanguiExpect("test6: Plugin Hang UI is showing", true, true, "test7");
|
||||||
|
var exceptionThrown = false;
|
||||||
|
try {
|
||||||
|
p.hang();
|
||||||
|
} catch(e) {
|
||||||
|
exceptionThrown = true;
|
||||||
|
}
|
||||||
|
ok(exceptionThrown, "test6: Exception thrown from hang() when plugin was terminated (child timeout)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test5a() {
|
||||||
|
resetVars();
|
||||||
|
hanguiCancel("test5a: Close button works", "test6");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test5() {
|
||||||
|
window.frameLoaded = test5a;
|
||||||
|
iframe.contentWindow.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test4() {
|
||||||
|
hanguiStop("test4: Stop button works", false, "test5");
|
||||||
|
// We'll get an exception here because the plugin was terminated
|
||||||
|
var exceptionThrown = false;
|
||||||
|
try {
|
||||||
|
p.hang();
|
||||||
|
} catch(e) {
|
||||||
|
exceptionThrown = true;
|
||||||
|
}
|
||||||
|
ok(exceptionThrown, "test4: Exception thrown from hang() when plugin was terminated");
|
||||||
|
}
|
||||||
|
|
||||||
|
function test3() {
|
||||||
|
hanguiContinue("test3: Continue button works", false, "test4");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test2() {
|
||||||
|
// This test is identical to test1 because there were some bugs where the
|
||||||
|
// Hang UI would show on the first hang but not on subsequent hangs
|
||||||
|
hanguiExpect("test2: Plugin Hang UI is showing", true, true, "test3");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test1() {
|
||||||
|
SpecialPowers.setIntPref(hangUITimeoutPref, 1);
|
||||||
|
SpecialPowers.setIntPref(hangUIMinDisplayPref, 1);
|
||||||
|
SpecialPowers.setIntPref(timeoutPref, 45);
|
||||||
|
hanguiExpect("test1: Plugin Hang UI is showing", true, true, "test2");
|
||||||
|
p.stall(STALL_DURATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</script>
|
||||||
|
</window>
|
|
@ -4,7 +4,7 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
DIRS += ['testplugin']
|
DIRS += ['testplugin', 'testaddon']
|
||||||
|
|
||||||
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
|
XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||||
|
plugin_file_name = Test.plugin
|
||||||
|
addon_file_name = testaddon_$(TARGET_XPCOM_ABI).xpi
|
||||||
|
else
|
||||||
|
plugin_file_name = $(DLL_PREFIX)nptest$(DLL_SUFFIX)
|
||||||
|
addon_file_name = testaddon.xpi
|
||||||
|
endif
|
||||||
|
|
||||||
|
# This is so hacky. Waiting on bug 988938.
|
||||||
|
testdir = $(abspath $(DEPTH)/_tests/xpcshell/dom/plugins/test/unit/)
|
||||||
|
addonpath = $(testdir)/$(addon_file_name)
|
||||||
|
|
||||||
|
libs::
|
||||||
|
$(NSINSTALL) -D $(testdir)
|
||||||
|
rm -f $(addonpath)
|
||||||
|
cd $(srcdir) && zip -rD $(addonpath) install.rdf
|
||||||
|
cd $(DIST) && zip -rD $(addonpath) plugins/$(plugin_file_name)
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||||
|
|
||||||
|
<Description about="urn:mozilla:install-manifest">
|
||||||
|
<em:id>test-plugin-from-xpi@tests.mozilla.org</em:id>
|
||||||
|
<em:version>1</em:version>
|
||||||
|
<em:name>Test plugin from XPI</em:name>
|
||||||
|
<em:description>This tests shipping a plugin through an extensions.</em:description>
|
||||||
|
|
||||||
|
<em:targetApplication>
|
||||||
|
<Description>
|
||||||
|
<em:id>toolkit@mozilla.org</em:id>
|
||||||
|
<em:minVersion>0</em:minVersion>
|
||||||
|
<em:maxVersion>*</em:maxVersion>
|
||||||
|
</Description>
|
||||||
|
</em:targetApplication>
|
||||||
|
|
||||||
|
<em:unpack>true</em:unpack>
|
||||||
|
|
||||||
|
</Description>
|
||||||
|
</RDF>
|
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
|
@ -149,6 +149,7 @@ static bool getAuthInfo(NPObject* npobj, const NPVariant* args, uint32_t argCoun
|
||||||
static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
|
static bool stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||||
|
@ -213,6 +214,7 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
|
||||||
"asyncCallbackTest",
|
"asyncCallbackTest",
|
||||||
"checkGCRace",
|
"checkGCRace",
|
||||||
"hang",
|
"hang",
|
||||||
|
"stall",
|
||||||
"getClipboardText",
|
"getClipboardText",
|
||||||
"callOnDestroy",
|
"callOnDestroy",
|
||||||
"reinitWidget",
|
"reinitWidget",
|
||||||
|
@ -278,6 +280,7 @@ static const ScriptableFunction sPluginMethodFunctions[] = {
|
||||||
asyncCallbackTest,
|
asyncCallbackTest,
|
||||||
checkGCRace,
|
checkGCRace,
|
||||||
hangPlugin,
|
hangPlugin,
|
||||||
|
stallPlugin,
|
||||||
getClipboardText,
|
getClipboardText,
|
||||||
callOnDestroy,
|
callOnDestroy,
|
||||||
reinitWidget,
|
reinitWidget,
|
||||||
|
@ -3355,6 +3358,24 @@ hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||||
|
NPVariant* result)
|
||||||
|
{
|
||||||
|
uint32_t stallTimeSeconds = 0;
|
||||||
|
if ((argCount == 1) && NPVARIANT_IS_INT32(args[0])) {
|
||||||
|
stallTimeSeconds = (uint32_t) NPVARIANT_TO_INT32(args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
Sleep(stallTimeSeconds * 1000U);
|
||||||
|
#else
|
||||||
|
sleep(stallTimeSeconds);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_GTK)
|
#if defined(MOZ_WIDGET_GTK)
|
||||||
bool
|
bool
|
||||||
getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
|
||||||
|
|
|
@ -3,13 +3,15 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
const Ci = Components.interfaces;
|
|
||||||
|
Cu.import("resource://gre/modules/Promise.jsm");
|
||||||
|
|
||||||
const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
|
const gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
|
||||||
const gIsOSX = ("nsILocalFileMac" in Ci);
|
const gIsOSX = ("nsILocalFileMac" in Ci);
|
||||||
const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) ||
|
const gIsLinux = ("@mozilla.org/gnome-gconf-service;1" in Cc) ||
|
||||||
("@mozilla.org/gio-service;1" in Cc);
|
("@mozilla.org/gio-service;1" in Cc);
|
||||||
|
const gDirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||||
|
|
||||||
// Finds the test plugin library
|
// Finds the test plugin library
|
||||||
function get_test_plugin() {
|
function get_test_plugin() {
|
||||||
|
@ -42,7 +44,7 @@ function get_test_plugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds the test nsIPluginTag
|
// Finds the test nsIPluginTag
|
||||||
function get_test_plugintag(aName) {
|
function get_test_plugintag(aName="Test Plug-in") {
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
|
@ -119,3 +121,79 @@ function get_test_plugin_no_symlink() {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gGlobalScope = this;
|
||||||
|
function loadAddonManager() {
|
||||||
|
let ns = {};
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm", ns);
|
||||||
|
let head = "../../../../toolkit/mozapps/extensions/test/xpcshell/head_addons.js";
|
||||||
|
let file = do_get_file(head);
|
||||||
|
let uri = ns.Services.io.newFileURI(file);
|
||||||
|
ns.Services.scriptloader.loadSubScript(uri.spec, gGlobalScope);
|
||||||
|
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
||||||
|
startupManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install addon and return a Promise<boolean> that is
|
||||||
|
// resolve with true on success, false otherwise.
|
||||||
|
function installAddon(relativePath) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
let success = () => deferred.resolve(true);
|
||||||
|
let fail = () => deferred.resolve(false);
|
||||||
|
let listener = {
|
||||||
|
onDownloadCancelled: fail,
|
||||||
|
onDownloadFailed: fail,
|
||||||
|
onInstallCancelled: fail,
|
||||||
|
onInstallFailed: fail,
|
||||||
|
onInstallEnded: success,
|
||||||
|
};
|
||||||
|
|
||||||
|
let installCallback = install => {
|
||||||
|
install.addListener(listener);
|
||||||
|
install.install();
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = do_get_file(relativePath, false);
|
||||||
|
AddonManager.getInstallForFile(file, installCallback,
|
||||||
|
"application/x-xpinstall");
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uninstall addon and return a Promise<boolean> that is
|
||||||
|
// resolve with true on success, false otherwise.
|
||||||
|
function uninstallAddon(id) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
AddonManager.getAddonByID(id, addon => {
|
||||||
|
if (!addon) {
|
||||||
|
deferred.resolve(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
let listener = {};
|
||||||
|
let handler = addon => {
|
||||||
|
if (addon.id !== id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddonManager.removeAddonListener(listener);
|
||||||
|
deferred.resolve(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
listener.onUninstalled = handler;
|
||||||
|
listener.onDisabled = handler;
|
||||||
|
|
||||||
|
AddonManager.addAddonListener(listener);
|
||||||
|
addon.uninstall();
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a Promise<Addon> that is resolved with
|
||||||
|
// the corresponding addon or rejected.
|
||||||
|
function getAddonByID(id) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
AddonManager.getAddonByID(id, addon => deferred.resolve(addon));
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Promise.jsm");
|
||||||
|
|
||||||
|
const ADDON_ID = "test-plugin-from-xpi@tests.mozilla.org";
|
||||||
|
const XRE_EXTENSIONS_DIR_LIST = "XREExtDL";
|
||||||
|
const NS_APP_PLUGINS_DIR_LIST = "APluginsDL";
|
||||||
|
|
||||||
|
const gPluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||||
|
const gXPCOMABI = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).XPCOMABI;
|
||||||
|
let gProfileDir = null;
|
||||||
|
|
||||||
|
function getAddonRoot(profileDir, id) {
|
||||||
|
let dir = profileDir.clone();
|
||||||
|
dir.append("extensions");
|
||||||
|
Assert.ok(dir.exists(), "Extensions dir should exist: " + dir.path);
|
||||||
|
dir.append(id);
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTestaddonFilename() {
|
||||||
|
let abiPart = "";
|
||||||
|
if (gIsOSX) {
|
||||||
|
abiPart = "_" + gXPCOMABI;
|
||||||
|
}
|
||||||
|
return "testaddon" + abiPart + ".xpi";
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
loadAddonManager();
|
||||||
|
gProfileDir = do_get_profile();
|
||||||
|
do_register_cleanup(() => shutdownManager());
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* test_state() {
|
||||||
|
// Remove test so we will have only one "Test Plug-in" registered.
|
||||||
|
// xpcshell tests have plugins in per-test profiles, so that's fine.
|
||||||
|
let file = get_test_plugin();
|
||||||
|
file.remove(true);
|
||||||
|
|
||||||
|
let success = yield installAddon(getTestaddonFilename());
|
||||||
|
Assert.ok(success, "Should have installed addon.");
|
||||||
|
let addonDir = getAddonRoot(gProfileDir, ADDON_ID);
|
||||||
|
|
||||||
|
let provider = {
|
||||||
|
classID: Components.ID("{0af6b2d7-a06c-49b7-babc-636d292b0dbb}"),
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider,
|
||||||
|
Ci.nsIDirectoryServiceProvider2]),
|
||||||
|
|
||||||
|
getFile: function (prop, persistant) {
|
||||||
|
throw Cr.NS_ERROR_FAILURE;
|
||||||
|
},
|
||||||
|
|
||||||
|
getFiles: function (prop) {
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
switch (prop) {
|
||||||
|
case XRE_EXTENSIONS_DIR_LIST:
|
||||||
|
result.push(addonDir);
|
||||||
|
break;
|
||||||
|
case NS_APP_PLUGINS_DIR_LIST:
|
||||||
|
let pluginDir = addonDir.clone();
|
||||||
|
pluginDir.append("plugins");
|
||||||
|
result.push(pluginDir);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Cr.NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
|
||||||
|
hasMoreElements: () => result.length > 0,
|
||||||
|
getNext: () => result.shift(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||||
|
dirSvc.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
|
||||||
|
|
||||||
|
// We installed a non-restartless addon, need to restart the manager.
|
||||||
|
restartManager();
|
||||||
|
gPluginHost.reloadPlugins();
|
||||||
|
|
||||||
|
Assert.ok(addonDir.exists(), "Addon path should exist: " + addonDir.path);
|
||||||
|
Assert.ok(addonDir.isDirectory(), "Addon path should be a directory: " + addonDir.path);
|
||||||
|
let pluginDir = addonDir.clone();
|
||||||
|
pluginDir.append("plugins");
|
||||||
|
Assert.ok(pluginDir.exists(), "Addon plugins path should exist: " + pluginDir.path);
|
||||||
|
Assert.ok(pluginDir.isDirectory(), "Addon plugins path should be a directory: " + pluginDir.path);
|
||||||
|
|
||||||
|
let addon = yield getAddonByID(ADDON_ID);
|
||||||
|
Assert.ok(!addon.appDisabled, "Addon should not be appDisabled");
|
||||||
|
Assert.ok(addon.isActive, "Addon should be active");
|
||||||
|
Assert.ok(addon.isCompatible, "Addon should be compatible");
|
||||||
|
Assert.ok(!addon.userDisabled, "Addon should not be user disabled");
|
||||||
|
|
||||||
|
let testPlugin = get_test_plugintag();
|
||||||
|
Assert.notEqual(testPlugin, null, "Test plugin should have been found");
|
||||||
|
Assert.equal(testPlugin.enabledState, Ci.nsIPluginTag.STATE_ENABLED, "Test plugin from addon should have state enabled");
|
||||||
|
|
||||||
|
pluginDir.append(testPlugin.filename);
|
||||||
|
Assert.ok(pluginDir.exists(), "Plugin file should exist in addon directory: " + pluginDir.path);
|
||||||
|
});
|
|
@ -17,3 +17,4 @@ fail-if = os == "android"
|
||||||
[test_persist_in_prefs.js]
|
[test_persist_in_prefs.js]
|
||||||
[test_bug854467.js]
|
[test_bug854467.js]
|
||||||
[test_plugin_default_state.js]
|
[test_plugin_default_state.js]
|
||||||
|
[test_plugin_default_state_xpi.js]
|
||||||
|
|
|
@ -831,14 +831,12 @@ public:
|
||||||
mContext->Save();
|
mContext->Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset(gfxContext *aContext) {
|
void EnsureSaved(gfxContext *aContext) {
|
||||||
// Do the equivalent of destroying and re-creating this object.
|
MOZ_ASSERT(!mContext || mContext == aContext, "wrong context");
|
||||||
NS_PRECONDITION(aContext, "must provide a context");
|
if (!mContext) {
|
||||||
if (mContext) {
|
mContext = aContext;
|
||||||
mContext->Restore();
|
mContext->Save();
|
||||||
}
|
}
|
||||||
mContext = aContext;
|
|
||||||
mContext->Save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -366,6 +366,7 @@ private:
|
||||||
GROUP3_OP_TEST = 0,
|
GROUP3_OP_TEST = 0,
|
||||||
GROUP3_OP_NOT = 2,
|
GROUP3_OP_NOT = 2,
|
||||||
GROUP3_OP_NEG = 3,
|
GROUP3_OP_NEG = 3,
|
||||||
|
GROUP3_OP_IMUL = 5,
|
||||||
GROUP3_OP_DIV = 6,
|
GROUP3_OP_DIV = 6,
|
||||||
GROUP3_OP_IDIV = 7,
|
GROUP3_OP_IDIV = 7,
|
||||||
|
|
||||||
|
@ -1155,6 +1156,13 @@ public:
|
||||||
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
|
m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void imull_r(RegisterID multiplier)
|
||||||
|
{
|
||||||
|
spew("imull %s",
|
||||||
|
nameIReg(4, multiplier));
|
||||||
|
m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IMUL, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
void imull_mr(int offset, RegisterID base, RegisterID dst)
|
void imull_mr(int offset, RegisterID base, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("imull %s0x%x(%s), %s",
|
spew("imull %s0x%x(%s), %s",
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
var intMin = -2147483648;
|
||||||
|
|
||||||
|
assertEq(intMin % (-2147483648), -0);
|
||||||
|
assertEq(intMin % (-3), -2);
|
||||||
|
assertEq(intMin % (-1), -0);
|
||||||
|
assertEq(intMin % 1, -0);
|
||||||
|
assertEq(intMin % 3, -2);
|
||||||
|
assertEq(intMin % 10, -8);
|
||||||
|
assertEq(intMin % 2147483647, -1);
|
||||||
|
|
||||||
|
assertEq((-2147483648) % (-2147483648), -0);
|
||||||
|
for (var i = -10; i <= 10; ++i)
|
||||||
|
assertEq(i % (-2147483648), i);
|
||||||
|
assertEq(2147483647 % (-2147483648), 2147483647);
|
||||||
|
|
||||||
|
assertEq((-2147483648) / (-2147483648), 1);
|
||||||
|
assertEq(0 / (-2147483648), -0);
|
||||||
|
assertEq((-2147483648) / (-1), 2147483648);
|
||||||
|
assertEq((-0) / (-2147483648), 0);
|
|
@ -158,7 +158,7 @@ MDefinition::valueHash() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MDefinition::congruentIfOperandsEqual(MDefinition *ins) const
|
MDefinition::congruentIfOperandsEqual(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (op() != ins->op())
|
if (op() != ins->op())
|
||||||
return false;
|
return false;
|
||||||
|
@ -491,7 +491,7 @@ MConstant::valueHash() const
|
||||||
return (HashNumber)JSVAL_TO_IMPL(value_).asBits;
|
return (HashNumber)JSVAL_TO_IMPL(value_).asBits;
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
MConstant::congruentTo(MDefinition *ins) const
|
MConstant::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (!ins->isConstant())
|
if (!ins->isConstant())
|
||||||
return false;
|
return false;
|
||||||
|
@ -674,7 +674,7 @@ MParameter::valueHash() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MParameter::congruentTo(MDefinition *ins) const
|
MParameter::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (!ins->isParameter())
|
if (!ins->isParameter())
|
||||||
return false;
|
return false;
|
||||||
|
@ -760,7 +760,7 @@ MCallDOMNative::computeMovable()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MCallDOMNative::congruentTo(MDefinition *ins) const
|
MCallDOMNative::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (!isMovable())
|
if (!isMovable())
|
||||||
return false;
|
return false;
|
||||||
|
@ -768,7 +768,7 @@ MCallDOMNative::congruentTo(MDefinition *ins) const
|
||||||
if (!ins->isCall())
|
if (!ins->isCall())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MCall *call = ins->toCall();
|
const MCall *call = ins->toCall();
|
||||||
|
|
||||||
if (!call->isCallDOMNative())
|
if (!call->isCallDOMNative())
|
||||||
return false;
|
return false;
|
||||||
|
@ -981,7 +981,7 @@ MPhi::foldsTo(TempAllocator &alloc, bool useValueNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MPhi::congruentTo(MDefinition *ins) const
|
MPhi::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (!ins->isPhi())
|
if (!ins->isPhi())
|
||||||
return false;
|
return false;
|
||||||
|
@ -2717,7 +2717,7 @@ MNewArray::shouldUseVM() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MLoadFixedSlot::mightAlias(MDefinition *store)
|
MLoadFixedSlot::mightAlias(const MDefinition *store) const
|
||||||
{
|
{
|
||||||
if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
|
if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
|
||||||
return false;
|
return false;
|
||||||
|
@ -2725,51 +2725,51 @@ MLoadFixedSlot::mightAlias(MDefinition *store)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MAsmJSLoadHeap::mightAlias(MDefinition *def)
|
MAsmJSLoadHeap::mightAlias(const MDefinition *def) const
|
||||||
{
|
{
|
||||||
if (def->isAsmJSStoreHeap()) {
|
if (def->isAsmJSStoreHeap()) {
|
||||||
MAsmJSStoreHeap *store = def->toAsmJSStoreHeap();
|
const MAsmJSStoreHeap *store = def->toAsmJSStoreHeap();
|
||||||
if (store->viewType() != viewType())
|
if (store->viewType() != viewType())
|
||||||
return true;
|
return true;
|
||||||
if (!ptr()->isConstant() || !store->ptr()->isConstant())
|
if (!ptr()->isConstant() || !store->ptr()->isConstant())
|
||||||
return true;
|
return true;
|
||||||
MConstant *otherPtr = store->ptr()->toConstant();
|
const MConstant *otherPtr = store->ptr()->toConstant();
|
||||||
return ptr()->toConstant()->value() == otherPtr->value();
|
return ptr()->toConstant()->value() == otherPtr->value();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MAsmJSLoadHeap::congruentTo(MDefinition *ins) const
|
MAsmJSLoadHeap::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (!ins->isAsmJSLoadHeap())
|
if (!ins->isAsmJSLoadHeap())
|
||||||
return false;
|
return false;
|
||||||
MAsmJSLoadHeap *load = ins->toAsmJSLoadHeap();
|
const MAsmJSLoadHeap *load = ins->toAsmJSLoadHeap();
|
||||||
return load->viewType() == viewType() && congruentIfOperandsEqual(load);
|
return load->viewType() == viewType() && congruentIfOperandsEqual(load);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MAsmJSLoadGlobalVar::mightAlias(MDefinition *def)
|
MAsmJSLoadGlobalVar::mightAlias(const MDefinition *def) const
|
||||||
{
|
{
|
||||||
if (def->isAsmJSStoreGlobalVar()) {
|
if (def->isAsmJSStoreGlobalVar()) {
|
||||||
MAsmJSStoreGlobalVar *store = def->toAsmJSStoreGlobalVar();
|
const MAsmJSStoreGlobalVar *store = def->toAsmJSStoreGlobalVar();
|
||||||
return store->globalDataOffset() == globalDataOffset_;
|
return store->globalDataOffset() == globalDataOffset_;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MAsmJSLoadGlobalVar::congruentTo(MDefinition *ins) const
|
MAsmJSLoadGlobalVar::congruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (ins->isAsmJSLoadGlobalVar()) {
|
if (ins->isAsmJSLoadGlobalVar()) {
|
||||||
MAsmJSLoadGlobalVar *load = ins->toAsmJSLoadGlobalVar();
|
const MAsmJSLoadGlobalVar *load = ins->toAsmJSLoadGlobalVar();
|
||||||
return globalDataOffset_ == load->globalDataOffset_;
|
return globalDataOffset_ == load->globalDataOffset_;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MLoadSlot::mightAlias(MDefinition *store)
|
MLoadSlot::mightAlias(const MDefinition *store) const
|
||||||
{
|
{
|
||||||
if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot())
|
if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot())
|
||||||
return false;
|
return false;
|
||||||
|
@ -2880,7 +2880,7 @@ MStoreTypedArrayElementStatic::length() const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MGetPropertyPolymorphic::mightAlias(MDefinition *store)
|
MGetPropertyPolymorphic::mightAlias(const MDefinition *store) const
|
||||||
{
|
{
|
||||||
// Allow hoisting this instruction if the store does not write to a
|
// Allow hoisting this instruction if the store does not write to a
|
||||||
// slot read by this instruction.
|
// slot read by this instruction.
|
||||||
|
@ -2889,7 +2889,7 @@ MGetPropertyPolymorphic::mightAlias(MDefinition *store)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (size_t i = 0; i < numShapes(); i++) {
|
for (size_t i = 0; i < numShapes(); i++) {
|
||||||
Shape *shape = this->shape(i);
|
const Shape *shape = this->shape(i);
|
||||||
if (shape->slot() < shape->numFixedSlots()) {
|
if (shape->slot() < shape->numFixedSlots()) {
|
||||||
// Fixed slot.
|
// Fixed slot.
|
||||||
uint32_t slot = shape->slot();
|
uint32_t slot = shape->slot();
|
||||||
|
|
184
js/src/jit/MIR.h
184
js/src/jit/MIR.h
|
@ -376,10 +376,10 @@ class MDefinition : public MNode
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual HashNumber valueHash() const;
|
virtual HashNumber valueHash() const;
|
||||||
virtual bool congruentTo(MDefinition *ins) const {
|
virtual bool congruentTo(const MDefinition *ins) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool congruentIfOperandsEqual(MDefinition *ins) const;
|
bool congruentIfOperandsEqual(const MDefinition *ins) const;
|
||||||
virtual MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
virtual MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
virtual void analyzeEdgeCasesForward();
|
virtual void analyzeEdgeCasesForward();
|
||||||
virtual void analyzeEdgeCasesBackward();
|
virtual void analyzeEdgeCasesBackward();
|
||||||
|
@ -584,7 +584,7 @@ class MDefinition : public MNode
|
||||||
bool isEffectful() const {
|
bool isEffectful() const {
|
||||||
return getAliasSet().isStore();
|
return getAliasSet().isStore();
|
||||||
}
|
}
|
||||||
virtual bool mightAlias(MDefinition *store) {
|
virtual bool mightAlias(const MDefinition *store) const {
|
||||||
// Return whether this load may depend on the specified store, given
|
// Return whether this load may depend on the specified store, given
|
||||||
// that the alias sets intersect. This may be refined to exclude
|
// that the alias sets intersect. This may be refined to exclude
|
||||||
// possible aliasing in cases where alias set flags are too imprecise.
|
// possible aliasing in cases where alias set flags are too imprecise.
|
||||||
|
@ -745,7 +745,7 @@ class MBinaryInstruction : public MAryInstruction<2>
|
||||||
replaceOperand(1, temp);
|
replaceOperand(1, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binaryCongruentTo(MDefinition *ins) const
|
bool binaryCongruentTo(const MDefinition *ins) const
|
||||||
{
|
{
|
||||||
if (op() != ins->op())
|
if (op() != ins->op())
|
||||||
return false;
|
return false;
|
||||||
|
@ -756,9 +756,9 @@ class MBinaryInstruction : public MAryInstruction<2>
|
||||||
if (isEffectful() || ins->isEffectful())
|
if (isEffectful() || ins->isEffectful())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MDefinition *left = getOperand(0);
|
const MDefinition *left = getOperand(0);
|
||||||
MDefinition *right = getOperand(1);
|
const MDefinition *right = getOperand(1);
|
||||||
MDefinition *tmp;
|
const MDefinition *tmp;
|
||||||
|
|
||||||
if (isCommutative() && left->valueNumber() > right->valueNumber()) {
|
if (isCommutative() && left->valueNumber() > right->valueNumber()) {
|
||||||
tmp = right;
|
tmp = right;
|
||||||
|
@ -766,9 +766,9 @@ class MBinaryInstruction : public MAryInstruction<2>
|
||||||
left = tmp;
|
left = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
MBinaryInstruction *bi = static_cast<MBinaryInstruction *>(ins);
|
const MBinaryInstruction *bi = static_cast<const MBinaryInstruction *>(ins);
|
||||||
MDefinition *insLeft = bi->getOperand(0);
|
const MDefinition *insLeft = bi->getOperand(0);
|
||||||
MDefinition *insRight = bi->getOperand(1);
|
const MDefinition *insRight = bi->getOperand(1);
|
||||||
if (isCommutative() && insLeft->valueNumber() > insRight->valueNumber()) {
|
if (isCommutative() && insLeft->valueNumber() > insRight->valueNumber()) {
|
||||||
tmp = insRight;
|
tmp = insRight;
|
||||||
insRight = insLeft;
|
insRight = insLeft;
|
||||||
|
@ -923,7 +923,7 @@ class MConstant : public MNullaryInstruction
|
||||||
void printOpcode(FILE *fp) const;
|
void printOpcode(FILE *fp) const;
|
||||||
|
|
||||||
HashNumber valueHash() const;
|
HashNumber valueHash() const;
|
||||||
bool congruentTo(MDefinition *ins) const;
|
bool congruentTo(const MDefinition *ins) const;
|
||||||
|
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
return AliasSet::None();
|
return AliasSet::None();
|
||||||
|
@ -991,7 +991,7 @@ class MParameter : public MNullaryInstruction
|
||||||
void printOpcode(FILE *fp) const;
|
void printOpcode(FILE *fp) const;
|
||||||
|
|
||||||
HashNumber valueHash() const;
|
HashNumber valueHash() const;
|
||||||
bool congruentTo(MDefinition *ins) const;
|
bool congruentTo(const MDefinition *ins) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MCallee : public MNullaryInstruction
|
class MCallee : public MNullaryInstruction
|
||||||
|
@ -1006,7 +1006,7 @@ class MCallee : public MNullaryInstruction
|
||||||
public:
|
public:
|
||||||
INSTRUCTION_HEADER(Callee)
|
INSTRUCTION_HEADER(Callee)
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1920,7 +1920,7 @@ class MCallDOMNative : public MCall
|
||||||
public:
|
public:
|
||||||
virtual AliasSet getAliasSet() const MOZ_OVERRIDE;
|
virtual AliasSet getAliasSet() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool congruentTo(MDefinition *ins) const MOZ_OVERRIDE;
|
virtual bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool isCallDOMNative() const MOZ_OVERRIDE {
|
virtual bool isCallDOMNative() const MOZ_OVERRIDE {
|
||||||
return true;
|
return true;
|
||||||
|
@ -2299,7 +2299,7 @@ class MCompare
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!binaryCongruentTo(ins))
|
if (!binaryCongruentTo(ins))
|
||||||
return false;
|
return false;
|
||||||
return compareType() == ins->toCompare()->compareType() &&
|
return compareType() == ins->toCompare()->compareType() &&
|
||||||
|
@ -2335,7 +2335,7 @@ class MBox : public MUnaryInstruction
|
||||||
return new(alloc) MBox(alloc, ins);
|
return new(alloc) MBox(alloc, ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -2417,7 +2417,7 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
||||||
bool fallible() const {
|
bool fallible() const {
|
||||||
return mode() != Infallible;
|
return mode() != Infallible;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isUnbox() || ins->toUnbox()->mode() != mode())
|
if (!ins->isUnbox() || ins->toUnbox()->mode() != mode())
|
||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
|
@ -2845,7 +2845,7 @@ class MToDouble
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isToDouble() || ins->toToDouble()->conversion() != conversion())
|
if (!ins->isToDouble() || ins->toToDouble()->conversion() != conversion())
|
||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
|
@ -2907,7 +2907,7 @@ class MToFloat32
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
virtual MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isToFloat32() || ins->toToFloat32()->conversion() != conversion())
|
if (!ins->isToFloat32() || ins->toToFloat32()->conversion() != conversion())
|
||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
|
@ -2940,7 +2940,7 @@ class MAsmJSUnsignedToDouble
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -2966,7 +2966,7 @@ class MAsmJSUnsignedToFloat32
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3024,7 +3024,7 @@ class MToInt32
|
||||||
return conversion_;
|
return conversion_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3060,7 +3060,7 @@ class MTruncateToInt32 : public MUnaryInstruction
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3101,7 +3101,7 @@ class MToString : public MUnaryInstruction
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3134,7 +3134,7 @@ class MBitNot
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
void infer();
|
void infer();
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3237,7 +3237,7 @@ class MBinaryBitwiseInstruction
|
||||||
virtual MDefinition *foldIfEqual() = 0;
|
virtual MDefinition *foldIfEqual() = 0;
|
||||||
virtual void infer(BaselineInspector *inspector, jsbytecode *pc);
|
virtual void infer(BaselineInspector *inspector, jsbytecode *pc);
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return binaryCongruentTo(ins);
|
return binaryCongruentTo(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3453,7 +3453,7 @@ class MBinaryArithInstruction
|
||||||
|
|
||||||
virtual void trySpecializeFloat32(TempAllocator &alloc);
|
virtual void trySpecializeFloat32(TempAllocator &alloc);
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return binaryCongruentTo(ins);
|
return binaryCongruentTo(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -3504,7 +3504,7 @@ class MMinMax
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isMinMax())
|
if (!ins->isMinMax())
|
||||||
return false;
|
return false;
|
||||||
if (isMax() != ins->toMinMax()->isMax())
|
if (isMax() != ins->toMinMax()->isMax())
|
||||||
|
@ -3551,7 +3551,7 @@ class MAbs
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
bool fallible() const;
|
bool fallible() const;
|
||||||
|
@ -3592,7 +3592,7 @@ class MSqrt
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3635,7 +3635,7 @@ class MAtan2
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3678,7 +3678,7 @@ class MHypot
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3719,7 +3719,7 @@ class MPow
|
||||||
MDefinition *power() const {
|
MDefinition *power() const {
|
||||||
return rhs();
|
return rhs();
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
|
@ -3757,7 +3757,7 @@ class MPowHalf
|
||||||
static MPowHalf *New(TempAllocator &alloc, MDefinition *input) {
|
static MPowHalf *New(TempAllocator &alloc, MDefinition *input) {
|
||||||
return new(alloc) MPowHalf(input);
|
return new(alloc) MPowHalf(input);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
bool operandIsNeverNegativeInfinity() const {
|
bool operandIsNeverNegativeInfinity() const {
|
||||||
|
@ -3865,7 +3865,7 @@ class MMathFunction
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isMathFunction())
|
if (!ins->isMathFunction())
|
||||||
return false;
|
return false;
|
||||||
if (ins->toMathFunction()->function() != function())
|
if (ins->toMathFunction()->function() != function())
|
||||||
|
@ -4021,11 +4021,11 @@ class MMul : public MBinaryArithInstruction
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isMul())
|
if (!ins->isMul())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MMul *mul = ins->toMul();
|
const MMul *mul = ins->toMul();
|
||||||
if (canBeNegativeZero_ != mul->canBeNegativeZero())
|
if (canBeNegativeZero_ != mul->canBeNegativeZero())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -4060,7 +4060,7 @@ class MMul : public MBinaryArithInstruction
|
||||||
bool truncate();
|
bool truncate();
|
||||||
bool isOperandTruncated(size_t index) const;
|
bool isOperandTruncated(size_t index) const;
|
||||||
|
|
||||||
Mode mode() { return mode_; }
|
Mode mode() const { return mode_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MDiv : public MBinaryArithInstruction
|
class MDiv : public MBinaryArithInstruction
|
||||||
|
@ -4257,7 +4257,7 @@ class MConcat
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -4296,7 +4296,7 @@ class MConcatPar
|
||||||
return getOperand(2);
|
return getOperand(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -4326,7 +4326,7 @@ class MCharCodeAt
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4464,7 +4464,7 @@ class MLoadArrowThis
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -4570,7 +4570,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode<MPhi>
|
||||||
|
|
||||||
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
MDefinition *foldsTo(TempAllocator &alloc, bool useValueNumbers);
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const;
|
bool congruentTo(const MDefinition *ins) const;
|
||||||
|
|
||||||
bool isIterator() const {
|
bool isIterator() const {
|
||||||
return isIterator_;
|
return isIterator_;
|
||||||
|
@ -5055,7 +5055,7 @@ class MStringReplace
|
||||||
return new(alloc) MStringReplace(string, pattern, replacement);
|
return new(alloc) MStringReplace(string, pattern, replacement);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5254,7 +5254,7 @@ class MSlots
|
||||||
MDefinition *object() const {
|
MDefinition *object() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5287,7 +5287,7 @@ class MElements
|
||||||
MDefinition *object() const {
|
MDefinition *object() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5324,7 +5324,7 @@ class MConstantElements : public MNullaryInstruction
|
||||||
return (HashNumber)(size_t) value_;
|
return (HashNumber)(size_t) value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return ins->isConstantElements() && ins->toConstantElements()->value() == value();
|
return ins->isConstantElements() && ins->toConstantElements()->value() == value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5355,7 +5355,7 @@ class MConvertElementsToDoubles
|
||||||
MDefinition *elements() const {
|
MDefinition *elements() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5403,7 +5403,7 @@ class MMaybeToDoubleElement
|
||||||
MDefinition *value() const {
|
MDefinition *value() const {
|
||||||
return getOperand(1);
|
return getOperand(1);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5432,7 +5432,7 @@ class MInitializedLength
|
||||||
MDefinition *elements() const {
|
MDefinition *elements() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5491,7 +5491,7 @@ class MArrayLength
|
||||||
MDefinition *elements() const {
|
MDefinition *elements() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5554,7 +5554,7 @@ class MTypedArrayLength
|
||||||
MDefinition *object() const {
|
MDefinition *object() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5591,7 +5591,7 @@ class MTypedArrayElements
|
||||||
MDefinition *object() const {
|
MDefinition *object() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5625,7 +5625,7 @@ class MNeuterCheck
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5662,7 +5662,7 @@ class MTypedObjectElements
|
||||||
MDefinition *object() const {
|
MDefinition *object() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -5817,10 +5817,10 @@ class MBoundsCheck
|
||||||
void setMaximum(int32_t n) {
|
void setMaximum(int32_t n) {
|
||||||
maximum_ = n;
|
maximum_ = n;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isBoundsCheck())
|
if (!ins->isBoundsCheck())
|
||||||
return false;
|
return false;
|
||||||
MBoundsCheck *other = ins->toBoundsCheck();
|
const MBoundsCheck *other = ins->toBoundsCheck();
|
||||||
if (minimum() != other->minimum() || maximum() != other->maximum())
|
if (minimum() != other->minimum() || maximum() != other->maximum())
|
||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(other);
|
return congruentIfOperandsEqual(other);
|
||||||
|
@ -5923,10 +5923,10 @@ class MLoadElement
|
||||||
bool fallible() const {
|
bool fallible() const {
|
||||||
return needsHoleCheck();
|
return needsHoleCheck();
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadElement())
|
if (!ins->isLoadElement())
|
||||||
return false;
|
return false;
|
||||||
MLoadElement *other = ins->toLoadElement();
|
const MLoadElement *other = ins->toLoadElement();
|
||||||
if (needsHoleCheck() != other->needsHoleCheck())
|
if (needsHoleCheck() != other->needsHoleCheck())
|
||||||
return false;
|
return false;
|
||||||
if (loadDoubles() != other->loadDoubles())
|
if (loadDoubles() != other->loadDoubles())
|
||||||
|
@ -5986,10 +5986,10 @@ class MLoadElementHole
|
||||||
bool needsHoleCheck() const {
|
bool needsHoleCheck() const {
|
||||||
return needsHoleCheck_;
|
return needsHoleCheck_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadElementHole())
|
if (!ins->isLoadElementHole())
|
||||||
return false;
|
return false;
|
||||||
MLoadElementHole *other = ins->toLoadElementHole();
|
const MLoadElementHole *other = ins->toLoadElementHole();
|
||||||
if (needsHoleCheck() != other->needsHoleCheck())
|
if (needsHoleCheck() != other->needsHoleCheck())
|
||||||
return false;
|
return false;
|
||||||
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
|
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
|
||||||
|
@ -6305,10 +6305,10 @@ class MLoadTypedArrayElement
|
||||||
return AliasSet::Load(AliasSet::TypedArrayElement);
|
return AliasSet::Load(AliasSet::TypedArrayElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadTypedArrayElement())
|
if (!ins->isLoadTypedArrayElement())
|
||||||
return false;
|
return false;
|
||||||
MLoadTypedArrayElement *other = ins->toLoadTypedArrayElement();
|
const MLoadTypedArrayElement *other = ins->toLoadTypedArrayElement();
|
||||||
if (arrayType_ != other->arrayType_)
|
if (arrayType_ != other->arrayType_)
|
||||||
return false;
|
return false;
|
||||||
return congruentIfOperandsEqual(other);
|
return congruentIfOperandsEqual(other);
|
||||||
|
@ -6366,10 +6366,10 @@ class MLoadTypedArrayElementHole
|
||||||
MDefinition *index() const {
|
MDefinition *index() const {
|
||||||
return getOperand(1);
|
return getOperand(1);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadTypedArrayElementHole())
|
if (!ins->isLoadTypedArrayElementHole())
|
||||||
return false;
|
return false;
|
||||||
MLoadTypedArrayElementHole *other = ins->toLoadTypedArrayElementHole();
|
const MLoadTypedArrayElementHole *other = ins->toLoadTypedArrayElementHole();
|
||||||
if (arrayType() != other->arrayType())
|
if (arrayType() != other->arrayType())
|
||||||
return false;
|
return false;
|
||||||
if (allowDouble() != other->allowDouble())
|
if (allowDouble() != other->allowDouble())
|
||||||
|
@ -6684,7 +6684,7 @@ class MClampToUint8
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -6724,7 +6724,7 @@ class MLoadFixedSlot
|
||||||
size_t slot() const {
|
size_t slot() const {
|
||||||
return slot_;
|
return slot_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadFixedSlot())
|
if (!ins->isLoadFixedSlot())
|
||||||
return false;
|
return false;
|
||||||
if (slot() != ins->toLoadFixedSlot()->slot())
|
if (slot() != ins->toLoadFixedSlot()->slot())
|
||||||
|
@ -6736,7 +6736,7 @@ class MLoadFixedSlot
|
||||||
return AliasSet::Load(AliasSet::FixedSlot);
|
return AliasSet::Load(AliasSet::FixedSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mightAlias(MDefinition *store);
|
bool mightAlias(const MDefinition *store) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MStoreFixedSlot
|
class MStoreFixedSlot
|
||||||
|
@ -6938,7 +6938,7 @@ class MGetPropertyCache
|
||||||
}
|
}
|
||||||
TypePolicy *typePolicy() { return this; }
|
TypePolicy *typePolicy() { return this; }
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!idempotent_)
|
if (!idempotent_)
|
||||||
return false;
|
return false;
|
||||||
if (!ins->isGetPropertyCache())
|
if (!ins->isGetPropertyCache())
|
||||||
|
@ -6998,7 +6998,7 @@ class MGetPropertyPolymorphic
|
||||||
return new(alloc) MGetPropertyPolymorphic(alloc, obj, name);
|
return new(alloc) MGetPropertyPolymorphic(alloc, obj, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isGetPropertyPolymorphic())
|
if (!ins->isGetPropertyPolymorphic())
|
||||||
return false;
|
return false;
|
||||||
if (name() != ins->toGetPropertyPolymorphic()->name())
|
if (name() != ins->toGetPropertyPolymorphic()->name())
|
||||||
|
@ -7031,7 +7031,7 @@ class MGetPropertyPolymorphic
|
||||||
return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot | AliasSet::DynamicSlot);
|
return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot | AliasSet::DynamicSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mightAlias(MDefinition *store);
|
bool mightAlias(const MDefinition *store) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emit code to store a value to an object's slots if its shape matches
|
// Emit code to store a value to an object's slots if its shape matches
|
||||||
|
@ -7362,7 +7362,7 @@ class MGuardShape
|
||||||
BailoutKind bailoutKind() const {
|
BailoutKind bailoutKind() const {
|
||||||
return bailoutKind_;
|
return bailoutKind_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isGuardShape())
|
if (!ins->isGuardShape())
|
||||||
return false;
|
return false;
|
||||||
if (shape() != ins->toGuardShape()->shape())
|
if (shape() != ins->toGuardShape()->shape())
|
||||||
|
@ -7414,7 +7414,7 @@ class MGuardObjectType
|
||||||
bool bailOnEquality() const {
|
bool bailOnEquality() const {
|
||||||
return bailOnEquality_;
|
return bailOnEquality_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isGuardObjectType())
|
if (!ins->isGuardObjectType())
|
||||||
return false;
|
return false;
|
||||||
if (typeObject() != ins->toGuardObjectType()->typeObject())
|
if (typeObject() != ins->toGuardObjectType()->typeObject())
|
||||||
|
@ -7466,7 +7466,7 @@ class MGuardObjectIdentity
|
||||||
bool bailOnEquality() const {
|
bool bailOnEquality() const {
|
||||||
return bailOnEquality_;
|
return bailOnEquality_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isGuardObjectIdentity())
|
if (!ins->isGuardObjectIdentity())
|
||||||
return false;
|
return false;
|
||||||
if (singleObject() != ins->toGuardObjectIdentity()->singleObject())
|
if (singleObject() != ins->toGuardObjectIdentity()->singleObject())
|
||||||
|
@ -7511,7 +7511,7 @@ class MGuardClass
|
||||||
const Class *getClass() const {
|
const Class *getClass() const {
|
||||||
return class_;
|
return class_;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isGuardClass())
|
if (!ins->isGuardClass())
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != ins->toGuardClass()->getClass())
|
if (getClass() != ins->toGuardClass()->getClass())
|
||||||
|
@ -7556,7 +7556,7 @@ class MLoadSlot
|
||||||
return slot_;
|
return slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isLoadSlot())
|
if (!ins->isLoadSlot())
|
||||||
return false;
|
return false;
|
||||||
if (slot() != ins->toLoadSlot()->slot())
|
if (slot() != ins->toLoadSlot()->slot())
|
||||||
|
@ -7567,7 +7567,7 @@ class MLoadSlot
|
||||||
JS_ASSERT(slots()->type() == MIRType_Slots);
|
JS_ASSERT(slots()->type() == MIRType_Slots);
|
||||||
return AliasSet::Load(AliasSet::DynamicSlot);
|
return AliasSet::Load(AliasSet::DynamicSlot);
|
||||||
}
|
}
|
||||||
bool mightAlias(MDefinition *store);
|
bool mightAlias(const MDefinition *store) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inline call to access a function's environment (scope chain).
|
// Inline call to access a function's environment (scope chain).
|
||||||
|
@ -8297,7 +8297,7 @@ class MGetDOMProperty
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!isDomMovable())
|
if (!isDomMovable())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -8374,7 +8374,7 @@ class MStringLength
|
||||||
MDefinition *string() const {
|
MDefinition *string() const {
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -8651,10 +8651,10 @@ class MInArray
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
return AliasSet::Load(AliasSet::Element);
|
return AliasSet::Load(AliasSet::Element);
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
if (!ins->isInArray())
|
if (!ins->isInArray())
|
||||||
return false;
|
return false;
|
||||||
MInArray *other = ins->toInArray();
|
const MInArray *other = ins->toInArray();
|
||||||
if (needsHoleCheck() != other->needsHoleCheck())
|
if (needsHoleCheck() != other->needsHoleCheck())
|
||||||
return false;
|
return false;
|
||||||
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
|
if (needsNegativeIntCheck() != other->needsNegativeIntCheck())
|
||||||
|
@ -8735,7 +8735,7 @@ class MArgumentsLength : public MNullaryInstruction
|
||||||
return new(alloc) MArgumentsLength();
|
return new(alloc) MArgumentsLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -8775,7 +8775,7 @@ class MGetFrameArgument
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -8816,7 +8816,7 @@ class MSetFrameArgument
|
||||||
return getOperand(0);
|
return getOperand(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -8954,7 +8954,7 @@ class MGuardThreadExclusive
|
||||||
BailoutKind bailoutKind() const {
|
BailoutKind bailoutKind() const {
|
||||||
return Bailout_Normal;
|
return Bailout_Normal;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -8985,7 +8985,7 @@ class MFilterTypeSet
|
||||||
return new(alloc) MFilterTypeSet(def, types);
|
return new(alloc) MFilterTypeSet(def, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *def) const {
|
bool congruentTo(const MDefinition *def) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -9028,7 +9028,7 @@ class MTypeBarrier
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool congruentTo(MDefinition *def) const {
|
bool congruentTo(const MDefinition *def) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -9559,7 +9559,7 @@ class MHaveSameClass
|
||||||
TypePolicy *typePolicy() {
|
TypePolicy *typePolicy() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool congruentTo(MDefinition *ins) const {
|
bool congruentTo(const MDefinition *ins) const {
|
||||||
return congruentIfOperandsEqual(ins);
|
return congruentIfOperandsEqual(ins);
|
||||||
}
|
}
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
|
@ -9689,11 +9689,11 @@ class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
|
||||||
|
|
||||||
MDefinition *ptr() const { return getOperand(0); }
|
MDefinition *ptr() const { return getOperand(0); }
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const;
|
bool congruentTo(const MDefinition *ins) const;
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
return AliasSet::Load(AliasSet::AsmJSHeap);
|
return AliasSet::Load(AliasSet::AsmJSHeap);
|
||||||
}
|
}
|
||||||
bool mightAlias(MDefinition *def);
|
bool mightAlias(const MDefinition *def) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
||||||
|
@ -9743,13 +9743,13 @@ class MAsmJSLoadGlobalVar : public MNullaryInstruction
|
||||||
|
|
||||||
unsigned globalDataOffset() const { return globalDataOffset_; }
|
unsigned globalDataOffset() const { return globalDataOffset_; }
|
||||||
|
|
||||||
bool congruentTo(MDefinition *ins) const;
|
bool congruentTo(const MDefinition *ins) const;
|
||||||
|
|
||||||
AliasSet getAliasSet() const {
|
AliasSet getAliasSet() const {
|
||||||
return isConstant_ ? AliasSet::None() : AliasSet::Load(AliasSet::AsmJSGlobalVar);
|
return isConstant_ ? AliasSet::None() : AliasSet::Load(AliasSet::AsmJSGlobalVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mightAlias(MDefinition *def);
|
bool mightAlias(const MDefinition *def) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MAsmJSStoreGlobalVar : public MUnaryInstruction
|
class MAsmJSStoreGlobalVar : public MUnaryInstruction
|
||||||
|
|
|
@ -1062,12 +1062,18 @@ class AssemblerX86Shared
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void imull(const Register &multiplier) {
|
||||||
|
masm.imull_r(multiplier.code());
|
||||||
|
}
|
||||||
void imull(Imm32 imm, const Register &dest) {
|
void imull(Imm32 imm, const Register &dest) {
|
||||||
masm.imull_i32r(dest.code(), imm.value, dest.code());
|
masm.imull_i32r(dest.code(), imm.value, dest.code());
|
||||||
}
|
}
|
||||||
void imull(const Register &src, const Register &dest) {
|
void imull(const Register &src, const Register &dest) {
|
||||||
masm.imull_rr(src.code(), dest.code());
|
masm.imull_rr(src.code(), dest.code());
|
||||||
}
|
}
|
||||||
|
void imull(Imm32 imm, const Register &src, const Register &dest) {
|
||||||
|
masm.imull_i32r(src.code(), imm.value, dest.code());
|
||||||
|
}
|
||||||
void imull(const Operand &src, const Register &dest) {
|
void imull(const Operand &src, const Register &dest) {
|
||||||
switch (src.kind()) {
|
switch (src.kind()) {
|
||||||
case Operand::REG:
|
case Operand::REG:
|
||||||
|
|
|
@ -1007,6 +1007,74 @@ CodeGeneratorShared::addCacheLocations(const CacheLocationList &locs, size_t *nu
|
||||||
return firstIndex;
|
return firstIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReciprocalMulConstants
|
||||||
|
CodeGeneratorShared::computeDivisionConstants(int d) {
|
||||||
|
// In what follows, d is positive and is not a power of 2.
|
||||||
|
JS_ASSERT(d > 0 && (d & (d - 1)) != 0);
|
||||||
|
|
||||||
|
// Speeding up division by non power-of-2 constants is possible by
|
||||||
|
// calculating, during compilation, a value M such that high-order
|
||||||
|
// bits of M*n correspond to the result of the division. Formally,
|
||||||
|
// we compute values 0 <= M < 2^32 and 0 <= s < 31 such that
|
||||||
|
// (M * n) >> (32 + s) = floor(n/d) if n >= 0
|
||||||
|
// (M * n) >> (32 + s) = ceil(n/d) - 1 if n < 0.
|
||||||
|
// The original presentation of this technique appears in Hacker's
|
||||||
|
// Delight, a book by Henry S. Warren, Jr.. A proof of correctness
|
||||||
|
// for our version follows.
|
||||||
|
|
||||||
|
// Define p = 32 + s, M = ceil(2^p/d), and assume that s satisfies
|
||||||
|
// M - 2^p/d <= 2^(s+1)/d. (1)
|
||||||
|
// (Observe that s = FloorLog32(d) satisfies this, because in this
|
||||||
|
// case d <= 2^(s+1) and so the RHS of (1) is at least one). Then,
|
||||||
|
//
|
||||||
|
// a) If s <= FloorLog32(d), then M <= 2^32 - 1.
|
||||||
|
// Proof: Indeed, M is monotone in s and, for s = FloorLog32(d),
|
||||||
|
// the inequalities 2^31 > d >= 2^s + 1 readily imply
|
||||||
|
// 2^p / d = 2^p/(d - 1) * (d - 1)/d
|
||||||
|
// <= 2^32 * (1 - 1/d) < 2 * (2^31 - 1) = 2^32 - 2.
|
||||||
|
// The claim follows by applying the ceiling function.
|
||||||
|
//
|
||||||
|
// b) For any 0 <= n < 2^31, floor(Mn/2^p) = floor(n/d).
|
||||||
|
// Proof: Put x = floor(Mn/2^p); it's the unique integer for which
|
||||||
|
// Mn/2^p - 1 < x <= Mn/2^p. (2)
|
||||||
|
// Using M >= 2^p/d on the LHS and (1) on the RHS, we get
|
||||||
|
// n/d - 1 < x <= n/d + n/(2^31 d) < n/d + 1/d.
|
||||||
|
// Since x is an integer, it's not in the interval (n/d, (n+1)/d),
|
||||||
|
// and so n/d - 1 < x <= n/d, which implies x = floor(n/d).
|
||||||
|
//
|
||||||
|
// c) For any -2^31 <= n < 0, floor(Mn/2^p) + 1 = ceil(n/d).
|
||||||
|
// Proof: The proof is similar. Equation (2) holds as above. Using
|
||||||
|
// M > 2^p/d (d isn't a power of 2) on the RHS and (1) on the LHS,
|
||||||
|
// n/d + n/(2^31 d) - 1 < x < n/d.
|
||||||
|
// Using n >= -2^31 and summing 1,
|
||||||
|
// n/d - 1/d < x + 1 < n/d + 1.
|
||||||
|
// Since x + 1 is an integer, this implies n/d <= x + 1 < n/d + 1.
|
||||||
|
// In other words, x + 1 = ceil(n/d).
|
||||||
|
//
|
||||||
|
// Condition (1) isn't necessary for the existence of M and s with
|
||||||
|
// the properties above. Hacker's Delight provides a slightly less
|
||||||
|
// restrictive condition when d >= 196611, at the cost of a 3-page
|
||||||
|
// proof of correctness.
|
||||||
|
|
||||||
|
// Note that, since d*M - 2^p = d - (2^p)%d, (1) can be written as
|
||||||
|
// 2^(s+1) >= d - (2^p)%d.
|
||||||
|
// We now compute the least s with this property...
|
||||||
|
|
||||||
|
int32_t shift = 0;
|
||||||
|
while ((int64_t(1) << (shift+1)) + (int64_t(1) << (shift+32)) % d < d)
|
||||||
|
shift++;
|
||||||
|
|
||||||
|
// ...and the corresponding M. This may not fit in a signed 32-bit
|
||||||
|
// integer; we will compute (M - 2^32) * n + (2^32 * n) instead of
|
||||||
|
// M * n if this is the case (cf. item (a) above).
|
||||||
|
ReciprocalMulConstants rmc;
|
||||||
|
rmc.multiplier = int32_t((int64_t(1) << (shift+32))/d + 1);
|
||||||
|
rmc.shift_amount = shift;
|
||||||
|
|
||||||
|
return rmc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef JS_TRACE_LOGGING
|
#ifdef JS_TRACE_LOGGING
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -45,6 +45,11 @@ struct PatchableBackedgeInfo
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ReciprocalMulConstants {
|
||||||
|
int32_t multiplier;
|
||||||
|
int32_t shift_amount;
|
||||||
|
};
|
||||||
|
|
||||||
class CodeGeneratorShared : public LInstructionVisitor
|
class CodeGeneratorShared : public LInstructionVisitor
|
||||||
{
|
{
|
||||||
js::Vector<OutOfLineCode *, 0, SystemAllocPolicy> outOfLineCode_;
|
js::Vector<OutOfLineCode *, 0, SystemAllocPolicy> outOfLineCode_;
|
||||||
|
@ -402,6 +407,7 @@ class CodeGeneratorShared : public LInstructionVisitor
|
||||||
|
|
||||||
bool addCache(LInstruction *lir, size_t cacheIndex);
|
bool addCache(LInstruction *lir, size_t cacheIndex);
|
||||||
size_t addCacheLocations(const CacheLocationList &locs, size_t *numLocs);
|
size_t addCacheLocations(const CacheLocationList &locs, size_t *numLocs);
|
||||||
|
ReciprocalMulConstants computeDivisionConstants(int d);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool addOutOfLineCode(OutOfLineCode *code);
|
bool addOutOfLineCode(OutOfLineCode *code);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
|
using mozilla::Abs;
|
||||||
using mozilla::FloatingPoint;
|
using mozilla::FloatingPoint;
|
||||||
using mozilla::FloorLog2;
|
using mozilla::FloorLog2;
|
||||||
using mozilla::NegativeInfinity;
|
using mozilla::NegativeInfinity;
|
||||||
|
@ -869,14 +870,23 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI *ins)
|
||||||
{
|
{
|
||||||
Register lhs = ToRegister(ins->numerator());
|
Register lhs = ToRegister(ins->numerator());
|
||||||
mozilla::DebugOnly<Register> output = ToRegister(ins->output());
|
mozilla::DebugOnly<Register> output = ToRegister(ins->output());
|
||||||
|
|
||||||
int32_t shift = ins->shift();
|
int32_t shift = ins->shift();
|
||||||
|
bool negativeDivisor = ins->negativeDivisor();
|
||||||
|
MDiv *mir = ins->mir();
|
||||||
|
|
||||||
// We use defineReuseInput so these should always be the same, which is
|
// We use defineReuseInput so these should always be the same, which is
|
||||||
// convenient since all of our instructions here are two-address.
|
// convenient since all of our instructions here are two-address.
|
||||||
JS_ASSERT(lhs == output);
|
JS_ASSERT(lhs == output);
|
||||||
|
|
||||||
|
if (!mir->isTruncated() && negativeDivisor) {
|
||||||
|
// 0 divided by a negative number must return a double.
|
||||||
|
masm.testl(lhs, lhs);
|
||||||
|
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (shift != 0) {
|
if (shift != 0) {
|
||||||
MDiv *mir = ins->mir();
|
|
||||||
if (!mir->isTruncated()) {
|
if (!mir->isTruncated()) {
|
||||||
// If the remainder is != 0, bailout since this must be a double.
|
// If the remainder is != 0, bailout since this must be a double.
|
||||||
masm.testl(lhs, Imm32(UINT32_MAX >> (32 - shift)));
|
masm.testl(lhs, Imm32(UINT32_MAX >> (32 - shift)));
|
||||||
|
@ -884,24 +894,108 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI *ins)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mir->canBeNegativeDividend()) {
|
|
||||||
// Numerator is unsigned, so needs no adjusting. Do the shift.
|
|
||||||
masm.sarl(Imm32(shift), lhs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the value so that shifting produces a correctly rounded result
|
// Adjust the value so that shifting produces a correctly rounded result
|
||||||
// when the numerator is negative. See 10-1 "Signed Division by a Known
|
// when the numerator is negative. See 10-1 "Signed Division by a Known
|
||||||
// Power of 2" in Henry S. Warren, Jr.'s Hacker's Delight.
|
// Power of 2" in Henry S. Warren, Jr.'s Hacker's Delight.
|
||||||
Register lhsCopy = ToRegister(ins->numeratorCopy());
|
if (mir->canBeNegativeDividend()) {
|
||||||
JS_ASSERT(lhsCopy != lhs);
|
Register lhsCopy = ToRegister(ins->numeratorCopy());
|
||||||
if (shift > 1)
|
JS_ASSERT(lhsCopy != lhs);
|
||||||
masm.sarl(Imm32(31), lhs);
|
if (shift > 1)
|
||||||
masm.shrl(Imm32(32 - shift), lhs);
|
masm.sarl(Imm32(31), lhs);
|
||||||
masm.addl(lhsCopy, lhs);
|
masm.shrl(Imm32(32 - shift), lhs);
|
||||||
|
masm.addl(lhsCopy, lhs);
|
||||||
|
}
|
||||||
|
|
||||||
// Do the shift.
|
|
||||||
masm.sarl(Imm32(shift), lhs);
|
masm.sarl(Imm32(shift), lhs);
|
||||||
|
if (negativeDivisor)
|
||||||
|
masm.negl(lhs);
|
||||||
|
} else if (shift == 0 && negativeDivisor) {
|
||||||
|
// INT32_MIN / -1 overflows.
|
||||||
|
masm.negl(lhs);
|
||||||
|
if (!mir->isTruncated() && !bailoutIf(Assembler::Overflow, ins->snapshot()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CodeGeneratorX86Shared::visitDivOrModConstantI(LDivOrModConstantI *ins) {
|
||||||
|
Register lhs = ToRegister(ins->numerator());
|
||||||
|
Register output = ToRegister(ins->output());
|
||||||
|
int32_t d = ins->denominator();
|
||||||
|
|
||||||
|
// This emits the division answer into edx or the modulus answer into eax.
|
||||||
|
JS_ASSERT(output == eax || output == edx);
|
||||||
|
JS_ASSERT(lhs != eax && lhs != edx);
|
||||||
|
|
||||||
|
// The absolute value of the denominator isn't a power of 2 (see LDivPowTwoI
|
||||||
|
// and LModPowTwoI).
|
||||||
|
JS_ASSERT((Abs(d) & (Abs(d) - 1)) != 0);
|
||||||
|
|
||||||
|
// We will first divide by Abs(d), and negate the answer if d is negative.
|
||||||
|
// If desired, this can be avoided by generalizing computeDivisionConstants.
|
||||||
|
ReciprocalMulConstants rmc = computeDivisionConstants(Abs(d));
|
||||||
|
|
||||||
|
// As explained in the comments of computeDivisionConstants, we first compute
|
||||||
|
// X >> (32 + shift), where X is either (rmc.multiplier * n) if the multiplier
|
||||||
|
// is non-negative or (rmc.multiplier * n) + (2^32 * n) otherwise. This is the
|
||||||
|
// desired division result if n is non-negative, and is one less than the result
|
||||||
|
// otherwise.
|
||||||
|
masm.movl(lhs, eax);
|
||||||
|
masm.movl(Imm32(rmc.multiplier), edx);
|
||||||
|
masm.imull(edx);
|
||||||
|
if (rmc.multiplier < 0)
|
||||||
|
masm.addl(lhs, edx);
|
||||||
|
masm.sarl(Imm32(rmc.shift_amount), edx);
|
||||||
|
|
||||||
|
// We'll subtract -1 instead of adding 1, because (n < 0 ? -1 : 0) can be
|
||||||
|
// computed with just a sign-extending shift of 31 bits.
|
||||||
|
if (ins->canBeNegativeDividend()) {
|
||||||
|
masm.movl(lhs, eax);
|
||||||
|
masm.sarl(Imm32(31), eax);
|
||||||
|
masm.subl(eax, edx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After this, edx contains the correct division result.
|
||||||
|
if (d < 0)
|
||||||
|
masm.negl(edx);
|
||||||
|
|
||||||
|
if (output == eax) {
|
||||||
|
masm.imull(Imm32(-d), edx, eax);
|
||||||
|
masm.addl(lhs, eax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ins->mir()->isTruncated()) {
|
||||||
|
if (output == edx) {
|
||||||
|
// This is a division op. Multiply the obtained value by d to check if
|
||||||
|
// the correct answer is an integer. This cannot overflow, since |d| > 1.
|
||||||
|
masm.imull(Imm32(d), edx, eax);
|
||||||
|
masm.cmpl(lhs, eax);
|
||||||
|
if (!bailoutIf(Assembler::NotEqual, ins->snapshot()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If lhs is zero and the divisor is negative, the answer should have
|
||||||
|
// been -0.
|
||||||
|
if (d < 0) {
|
||||||
|
masm.testl(lhs, lhs);
|
||||||
|
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (ins->canBeNegativeDividend()) {
|
||||||
|
// This is a mod op. If the computed value is zero and lhs
|
||||||
|
// is negative, the answer should have been -0.
|
||||||
|
Label done;
|
||||||
|
|
||||||
|
masm.cmpl(lhs, Imm32(0));
|
||||||
|
masm.j(Assembler::GreaterThanOrEqual, &done);
|
||||||
|
|
||||||
|
masm.testl(eax, eax);
|
||||||
|
if (!bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
masm.bind(&done);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1012,7 +1106,7 @@ CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
|
||||||
masm.branchTest32(Assembler::Signed, lhs, lhs, &negative);
|
masm.branchTest32(Assembler::Signed, lhs, lhs, &negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
masm.andl(Imm32((1 << shift) - 1), lhs);
|
masm.andl(Imm32((uint32_t(1) << shift) - 1), lhs);
|
||||||
|
|
||||||
if (ins->mir()->canBeNegativeDividend()) {
|
if (ins->mir()->canBeNegativeDividend()) {
|
||||||
Label done;
|
Label done;
|
||||||
|
@ -1020,11 +1114,19 @@ CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
|
||||||
|
|
||||||
// Negative numbers need a negate, bitmask, negate
|
// Negative numbers need a negate, bitmask, negate
|
||||||
masm.bind(&negative);
|
masm.bind(&negative);
|
||||||
// visitModI has an overflow check here to catch INT_MIN % -1, but
|
|
||||||
// here the rhs is a power of 2, and cannot be -1, so the check is not generated.
|
// Unlike in the visitModI case, we are not computing the mod by means of a
|
||||||
|
// division. Therefore, the divisor = -1 case isn't problematic (the andl
|
||||||
|
// always returns 0, which is what we expect).
|
||||||
|
//
|
||||||
|
// The negl instruction overflows if lhs == INT32_MIN, but this is also not
|
||||||
|
// a problem: shift is at most 31, and so the andl also always returns 0.
|
||||||
masm.negl(lhs);
|
masm.negl(lhs);
|
||||||
masm.andl(Imm32((1 << shift) - 1), lhs);
|
masm.andl(Imm32((uint32_t(1) << shift) - 1), lhs);
|
||||||
masm.negl(lhs);
|
masm.negl(lhs);
|
||||||
|
|
||||||
|
// Since a%b has the same sign as b, and a is negative in this branch,
|
||||||
|
// an answer of 0 means the correct result is actually -0. Bail out.
|
||||||
if (!ins->mir()->isTruncated() && !bailoutIf(Assembler::Zero, ins->snapshot()))
|
if (!ins->mir()->isTruncated() && !bailoutIf(Assembler::Zero, ins->snapshot()))
|
||||||
return false;
|
return false;
|
||||||
masm.bind(&done);
|
masm.bind(&done);
|
||||||
|
|
|
@ -124,6 +124,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||||
virtual bool visitMulI(LMulI *ins);
|
virtual bool visitMulI(LMulI *ins);
|
||||||
virtual bool visitDivI(LDivI *ins);
|
virtual bool visitDivI(LDivI *ins);
|
||||||
virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
|
virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
|
||||||
|
virtual bool visitDivOrModConstantI(LDivOrModConstantI *ins);
|
||||||
virtual bool visitModI(LModI *ins);
|
virtual bool visitModI(LModI *ins);
|
||||||
virtual bool visitModPowTwoI(LModPowTwoI *ins);
|
virtual bool visitModPowTwoI(LModPowTwoI *ins);
|
||||||
virtual bool visitBitNotI(LBitNotI *ins);
|
virtual bool visitBitNotI(LBitNotI *ins);
|
||||||
|
|
|
@ -47,12 +47,13 @@ class LDivI : public LBinaryMath<1>
|
||||||
class LDivPowTwoI : public LBinaryMath<0>
|
class LDivPowTwoI : public LBinaryMath<0>
|
||||||
{
|
{
|
||||||
const int32_t shift_;
|
const int32_t shift_;
|
||||||
|
const bool negativeDivisor_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LIR_HEADER(DivPowTwoI)
|
LIR_HEADER(DivPowTwoI)
|
||||||
|
|
||||||
LDivPowTwoI(const LAllocation &lhs, const LAllocation &lhsCopy, int32_t shift)
|
LDivPowTwoI(const LAllocation &lhs, const LAllocation &lhsCopy, int32_t shift, bool negativeDivisor)
|
||||||
: shift_(shift)
|
: shift_(shift), negativeDivisor_(negativeDivisor)
|
||||||
{
|
{
|
||||||
setOperand(0, lhs);
|
setOperand(0, lhs);
|
||||||
setOperand(1, lhsCopy);
|
setOperand(1, lhsCopy);
|
||||||
|
@ -67,11 +68,45 @@ class LDivPowTwoI : public LBinaryMath<0>
|
||||||
int32_t shift() const {
|
int32_t shift() const {
|
||||||
return shift_;
|
return shift_;
|
||||||
}
|
}
|
||||||
|
bool negativeDivisor() const {
|
||||||
|
return negativeDivisor_;
|
||||||
|
}
|
||||||
MDiv *mir() const {
|
MDiv *mir() const {
|
||||||
return mir_->toDiv();
|
return mir_->toDiv();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LDivOrModConstantI : public LInstructionHelper<1, 1, 1>
|
||||||
|
{
|
||||||
|
const int32_t denominator_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LIR_HEADER(DivOrModConstantI)
|
||||||
|
|
||||||
|
LDivOrModConstantI(const LAllocation &lhs, int32_t denominator, const LDefinition& temp)
|
||||||
|
: denominator_(denominator)
|
||||||
|
{
|
||||||
|
setOperand(0, lhs);
|
||||||
|
setTemp(0, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LAllocation *numerator() {
|
||||||
|
return getOperand(0);
|
||||||
|
}
|
||||||
|
int32_t denominator() const {
|
||||||
|
return denominator_;
|
||||||
|
}
|
||||||
|
MBinaryArithInstruction *mir() const {
|
||||||
|
JS_ASSERT(mir_->isDiv() || mir_->isMod());
|
||||||
|
return static_cast<MBinaryArithInstruction *>(mir_);
|
||||||
|
}
|
||||||
|
bool canBeNegativeDividend() const {
|
||||||
|
if (mir_->isMod())
|
||||||
|
return mir_->toMod()->canBeNegativeDividend();
|
||||||
|
return mir_->toDiv()->canBeNegativeDividend();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LModI : public LBinaryMath<1>
|
class LModI : public LBinaryMath<1>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
|
using mozilla::Abs;
|
||||||
using mozilla::FloorLog2;
|
using mozilla::FloorLog2;
|
||||||
|
|
||||||
LTableSwitch *
|
LTableSwitch *
|
||||||
|
@ -137,26 +138,29 @@ LIRGeneratorX86Shared::lowerDivI(MDiv *div)
|
||||||
if (div->rhs()->isConstant()) {
|
if (div->rhs()->isConstant()) {
|
||||||
int32_t rhs = div->rhs()->toConstant()->value().toInt32();
|
int32_t rhs = div->rhs()->toConstant()->value().toInt32();
|
||||||
|
|
||||||
// Check for division by a positive power of two, which is an easy and
|
// Division by powers of two can be done by shifting, and division by
|
||||||
// important case to optimize. Note that other optimizations are also
|
// other numbers can be done by a reciprocal multiplication technique.
|
||||||
// possible; division by negative powers of two can be optimized in a
|
int32_t shift = FloorLog2(Abs(rhs));
|
||||||
// similar manner as positive powers of two, and division by other
|
if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
|
||||||
// constants can be optimized by a reciprocal multiplication technique.
|
|
||||||
int32_t shift = FloorLog2(rhs);
|
|
||||||
if (rhs > 0 && 1 << shift == rhs) {
|
|
||||||
LAllocation lhs = useRegisterAtStart(div->lhs());
|
LAllocation lhs = useRegisterAtStart(div->lhs());
|
||||||
LDivPowTwoI *lir;
|
LDivPowTwoI *lir;
|
||||||
if (!div->canBeNegativeDividend()) {
|
if (!div->canBeNegativeDividend()) {
|
||||||
// Numerator is unsigned, so does not need adjusting.
|
// Numerator is unsigned, so does not need adjusting.
|
||||||
lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift);
|
lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift, rhs < 0);
|
||||||
} else {
|
} else {
|
||||||
// Numerator is signed, and needs adjusting, and an extra
|
// Numerator is signed, and needs adjusting, and an extra
|
||||||
// lhs copy register is needed.
|
// lhs copy register is needed.
|
||||||
lir = new(alloc()) LDivPowTwoI(lhs, useRegister(div->lhs()), shift);
|
lir = new(alloc()) LDivPowTwoI(lhs, useRegister(div->lhs()), shift, rhs < 0);
|
||||||
}
|
}
|
||||||
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||||
return false;
|
return false;
|
||||||
return defineReuseInput(lir, div, 0);
|
return defineReuseInput(lir, div, 0);
|
||||||
|
} else if (rhs != 0) {
|
||||||
|
LDivOrModConstantI *lir;
|
||||||
|
lir = new(alloc()) LDivOrModConstantI(useRegister(div->lhs()), rhs, tempFixed(eax));
|
||||||
|
if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||||
|
return false;
|
||||||
|
return defineFixed(lir, div, LAllocation(AnyRegister(edx)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,12 +179,18 @@ LIRGeneratorX86Shared::lowerModI(MMod *mod)
|
||||||
|
|
||||||
if (mod->rhs()->isConstant()) {
|
if (mod->rhs()->isConstant()) {
|
||||||
int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
|
int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
|
||||||
int32_t shift = FloorLog2(rhs);
|
int32_t shift = FloorLog2(Abs(rhs));
|
||||||
if (rhs > 0 && 1 << shift == rhs) {
|
if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) {
|
||||||
LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
|
LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
|
||||||
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||||
return false;
|
return false;
|
||||||
return defineReuseInput(lir, mod, 0);
|
return defineReuseInput(lir, mod, 0);
|
||||||
|
} else if (rhs != 0) {
|
||||||
|
LDivOrModConstantI *lir;
|
||||||
|
lir = new(alloc()) LDivOrModConstantI(useRegister(mod->lhs()), rhs, tempFixed(edx));
|
||||||
|
if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
|
||||||
|
return false;
|
||||||
|
return defineFixed(lir, mod, LAllocation(AnyRegister(eax)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
_(UnboxFloatingPoint) \
|
_(UnboxFloatingPoint) \
|
||||||
_(DivI) \
|
_(DivI) \
|
||||||
_(DivPowTwoI) \
|
_(DivPowTwoI) \
|
||||||
|
_(DivOrModConstantI) \
|
||||||
_(ModI) \
|
_(ModI) \
|
||||||
_(ModPowTwoI) \
|
_(ModPowTwoI) \
|
||||||
_(PowHalfD) \
|
_(PowHalfD) \
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
_(BoxFloatingPoint) \
|
_(BoxFloatingPoint) \
|
||||||
_(DivI) \
|
_(DivI) \
|
||||||
_(DivPowTwoI) \
|
_(DivPowTwoI) \
|
||||||
|
_(DivOrModConstantI) \
|
||||||
_(ModI) \
|
_(ModI) \
|
||||||
_(ModPowTwoI) \
|
_(ModPowTwoI) \
|
||||||
_(PowHalfD) \
|
_(PowHalfD) \
|
||||||
|
|
|
@ -121,7 +121,7 @@ interface ScheduledGCCallback : nsISupports
|
||||||
/**
|
/**
|
||||||
* interface of Components.utils
|
* interface of Components.utils
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(5e253a02-f91f-4fb3-9335-db0fca23f2e0)]
|
[scriptable, uuid(45b80e00-fb0d-439e-b7bf-54f24af0c4a6)]
|
||||||
interface nsIXPCComponents_Utils : nsISupports
|
interface nsIXPCComponents_Utils : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -568,6 +568,13 @@ interface nsIXPCComponents_Utils : nsISupports
|
||||||
* function throws. If it throws, you probably shouldn't be using it.
|
* function throws. If it throws, you probably shouldn't be using it.
|
||||||
*/
|
*/
|
||||||
nsIPrincipal getWebIDLCallerPrincipal();
|
nsIPrincipal getWebIDLCallerPrincipal();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the principal of a script object, after unwrapping any cross-
|
||||||
|
* compartment wrappers.
|
||||||
|
*/
|
||||||
|
[implicit_jscontext]
|
||||||
|
nsIPrincipal getObjectPrincipal(in jsval obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3257,7 +3257,7 @@ nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
|
||||||
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
||||||
/* stopAtOuter = */ false));
|
/* stopAtOuter = */ false));
|
||||||
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
||||||
if (nsContentUtils::IsSystemPrincipal(GetObjectPrincipal(global))) {
|
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
|
||||||
JS_ReportError(cx, "Script may not be disabled for system globals");
|
JS_ReportError(cx, "Script may not be disabled for system globals");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -3273,7 +3273,7 @@ nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
|
||||||
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
|
||||||
/* stopAtOuter = */ false));
|
/* stopAtOuter = */ false));
|
||||||
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
|
||||||
if (nsContentUtils::IsSystemPrincipal(GetObjectPrincipal(global))) {
|
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
|
||||||
JS_ReportError(cx, "Script may not be disabled for system globals");
|
JS_ReportError(cx, "Script may not be disabled for system globals");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -3616,6 +3616,21 @@ nsXPCComponents_Utils::GetWebIDLCallerPrincipal(nsIPrincipal **aResult)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsXPCComponents_Utils::GetObjectPrincipal(HandleValue val, JSContext *cx,
|
||||||
|
nsIPrincipal **result)
|
||||||
|
{
|
||||||
|
if (!val.isObject())
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
RootedObject obj(cx, &val.toObject());
|
||||||
|
obj = js::CheckedUnwrap(obj);
|
||||||
|
MOZ_ASSERT(obj);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> prin = nsContentUtils::GetObjectPrincipal(obj);
|
||||||
|
prin.forget(result);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
function run_test() {
|
const Cc = Components.classes;
|
||||||
var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"].getService(
|
const Ci = Components.interfaces;
|
||||||
Components.interfaces.nsIScriptSecurityManager);
|
const Cu = Components.utils;
|
||||||
|
|
||||||
do_check_true(secMan.isSystemPrincipal(secMan.getObjectPrincipal({})));
|
function run_test() {
|
||||||
|
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||||
|
do_check_true(secMan.isSystemPrincipal(Cu.getObjectPrincipal({})));
|
||||||
|
var sb = new Cu.Sandbox('http://www.example.com');
|
||||||
|
Cu.evalInSandbox('var obj = { foo: 42 };', sb);
|
||||||
|
do_check_eq(Cu.getObjectPrincipal(sb.obj).origin, 'http://www.example.com');
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,19 @@ using mozilla::CSSSizeOrRatio;
|
||||||
|
|
||||||
static int gFrameTreeLockCount = 0;
|
static int gFrameTreeLockCount = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
ApplySkipSides(int aSkipSides, nsMargin* aMargin)
|
||||||
|
{
|
||||||
|
if (aSkipSides & SIDE_BIT_LEFT)
|
||||||
|
aMargin->left = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_TOP)
|
||||||
|
aMargin->top = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_RIGHT)
|
||||||
|
aMargin->right = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_BOTTOM)
|
||||||
|
aMargin->bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
|
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
|
||||||
// recalculating this for each frame in a continuation (perf), hold
|
// recalculating this for each frame in a continuation (perf), hold
|
||||||
// a cache of various coordinate information that we need in order
|
// a cache of various coordinate information that we need in order
|
||||||
|
@ -81,10 +94,18 @@ struct InlineBackgroundData
|
||||||
mBoundingBox.SetRect(0,0,0,0);
|
mBoundingBox.SetRect(0,0,0,0);
|
||||||
mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0;
|
mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0;
|
||||||
mFrame = mBlockFrame = nullptr;
|
mFrame = mBlockFrame = nullptr;
|
||||||
|
mLeftBorderData.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a continuous rect for (an inline) aFrame relative to the
|
||||||
|
* continuation that draws the left-most part of the background.
|
||||||
|
* This is used when painting backgrounds.
|
||||||
|
*/
|
||||||
nsRect GetContinuousRect(nsIFrame* aFrame)
|
nsRect GetContinuousRect(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::inlineFrame);
|
||||||
|
|
||||||
SetFrame(aFrame);
|
SetFrame(aFrame);
|
||||||
|
|
||||||
nscoord x;
|
nscoord x;
|
||||||
|
@ -98,12 +119,9 @@ struct InlineBackgroundData
|
||||||
NS_STYLE_DIRECTION_RTL);
|
NS_STYLE_DIRECTION_RTL);
|
||||||
nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x;
|
nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x;
|
||||||
|
|
||||||
// No need to use our GetPrevContinuation/GetNextContinuation methods
|
|
||||||
// here, since ib-split siblings are certainly not on the same line.
|
|
||||||
|
|
||||||
nsIFrame* inlineFrame = aFrame->GetPrevContinuation();
|
|
||||||
// If the continuation is fluid we know inlineFrame is not on the same line.
|
// If the continuation is fluid we know inlineFrame is not on the same line.
|
||||||
// If it's not fluid, we need to test further to be sure.
|
// If it's not fluid, we need to test further to be sure.
|
||||||
|
nsIFrame* inlineFrame = aFrame->GetPrevContinuation();
|
||||||
while (inlineFrame && !inlineFrame->GetNextInFlow() &&
|
while (inlineFrame && !inlineFrame->GetNextInFlow() &&
|
||||||
AreOnSameLine(aFrame, inlineFrame)) {
|
AreOnSameLine(aFrame, inlineFrame)) {
|
||||||
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||||
|
@ -140,6 +158,39 @@ struct InlineBackgroundData
|
||||||
return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height);
|
return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a continuous rect for (an inline) aFrame relative to the
|
||||||
|
* continuation that should draw the left-border. This is used when painting
|
||||||
|
* borders and clipping backgrounds. This may NOT be the same continuous rect
|
||||||
|
* as for drawing backgrounds; the continuation with the left-border might be
|
||||||
|
* somewhere in the middle of that rect (e.g. BIDI), in those cases we need
|
||||||
|
* the reverse background order starting at the left-border continuation.
|
||||||
|
*/
|
||||||
|
nsRect GetBorderContinuousRect(nsIFrame* aFrame, nsRect aBorderArea)
|
||||||
|
{
|
||||||
|
// Calling GetContinuousRect(aFrame) here may lead to Reset/Init which
|
||||||
|
// resets our mLeftBorderData so we save it ...
|
||||||
|
LeftBorderData saved(mLeftBorderData);
|
||||||
|
nsRect joinedBorderArea = GetContinuousRect(aFrame);
|
||||||
|
if (!saved.mIsValid || saved.mFrame != mLeftBorderData.mFrame) {
|
||||||
|
if (aFrame == mLeftBorderData.mFrame) {
|
||||||
|
mLeftBorderData.SetX(joinedBorderArea.x);
|
||||||
|
} else if (mLeftBorderData.mFrame) {
|
||||||
|
mLeftBorderData.SetX(GetContinuousRect(mLeftBorderData.mFrame).x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ... and restore it when possible.
|
||||||
|
mLeftBorderData.mX = saved.mX;
|
||||||
|
}
|
||||||
|
if (joinedBorderArea.x > mLeftBorderData.mX) {
|
||||||
|
joinedBorderArea.x =
|
||||||
|
-(mUnbrokenWidth + joinedBorderArea.x - aBorderArea.width);
|
||||||
|
} else {
|
||||||
|
joinedBorderArea.x -= mLeftBorderData.mX;
|
||||||
|
}
|
||||||
|
return joinedBorderArea;
|
||||||
|
}
|
||||||
|
|
||||||
nsRect GetBoundingRect(nsIFrame* aFrame)
|
nsRect GetBoundingRect(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
SetFrame(aFrame);
|
SetFrame(aFrame);
|
||||||
|
@ -157,13 +208,22 @@ struct InlineBackgroundData
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsIFrame* mFrame;
|
struct LeftBorderData {
|
||||||
nsBlockFrame* mBlockFrame;
|
nsIFrame* mFrame; // the continuation that may have a left-border
|
||||||
nsRect mBoundingBox;
|
nscoord mX; // cached GetContinuousRect(mFrame).x
|
||||||
nscoord mContinuationPoint;
|
bool mIsValid; // true if mX is valid
|
||||||
nscoord mUnbrokenWidth;
|
void Reset() { mFrame = nullptr; mIsValid = false; }
|
||||||
nscoord mLineContinuationPoint;
|
void SetX(nscoord aX) { mX = aX; mIsValid = true; }
|
||||||
bool mBidiEnabled;
|
};
|
||||||
|
|
||||||
|
nsIFrame* mFrame;
|
||||||
|
nsBlockFrame* mBlockFrame;
|
||||||
|
nsRect mBoundingBox;
|
||||||
|
nscoord mContinuationPoint;
|
||||||
|
nscoord mUnbrokenWidth;
|
||||||
|
nscoord mLineContinuationPoint;
|
||||||
|
LeftBorderData mLeftBorderData;
|
||||||
|
bool mBidiEnabled;
|
||||||
|
|
||||||
void SetFrame(nsIFrame* aFrame)
|
void SetFrame(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
@ -236,6 +296,7 @@ protected:
|
||||||
|
|
||||||
void Init(nsIFrame* aFrame)
|
void Init(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
mLeftBorderData.Reset();
|
||||||
mBidiEnabled = aFrame->PresContext()->BidiEnabled();
|
mBidiEnabled = aFrame->PresContext()->BidiEnabled();
|
||||||
if (mBidiEnabled) {
|
if (mBidiEnabled) {
|
||||||
// Find the containing block frame
|
// Find the containing block frame
|
||||||
|
@ -252,8 +313,11 @@ protected:
|
||||||
// Start with the previous flow frame as our continuation point
|
// Start with the previous flow frame as our continuation point
|
||||||
// is the total of the widths of the previous frames.
|
// is the total of the widths of the previous frames.
|
||||||
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
||||||
|
|
||||||
while (inlineFrame) {
|
while (inlineFrame) {
|
||||||
|
if (!mLeftBorderData.mFrame &&
|
||||||
|
!(inlineFrame->GetSkipSides() & SIDE_BIT_LEFT)) {
|
||||||
|
mLeftBorderData.mFrame = inlineFrame;
|
||||||
|
}
|
||||||
nsRect rect = inlineFrame->GetRect();
|
nsRect rect = inlineFrame->GetRect();
|
||||||
mContinuationPoint += rect.width;
|
mContinuationPoint += rect.width;
|
||||||
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
||||||
|
@ -268,6 +332,10 @@ protected:
|
||||||
// unbroken width.
|
// unbroken width.
|
||||||
inlineFrame = aFrame;
|
inlineFrame = aFrame;
|
||||||
while (inlineFrame) {
|
while (inlineFrame) {
|
||||||
|
if (!mLeftBorderData.mFrame &&
|
||||||
|
!(inlineFrame->GetSkipSides() & SIDE_BIT_LEFT)) {
|
||||||
|
mLeftBorderData.mFrame = inlineFrame;
|
||||||
|
}
|
||||||
nsRect rect = inlineFrame->GetRect();
|
nsRect rect = inlineFrame->GetRect();
|
||||||
mUnbrokenWidth += rect.width;
|
mUnbrokenWidth += rect.width;
|
||||||
mBoundingBox.UnionRect(mBoundingBox, rect);
|
mBoundingBox.UnionRect(mBoundingBox, rect);
|
||||||
|
@ -305,7 +373,8 @@ static void DrawBorderImage(nsPresContext* aPresContext,
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsStyleBorder& aStyleBorder,
|
const nsStyleBorder& aStyleBorder,
|
||||||
const nsRect& aDirtyRect);
|
const nsRect& aDirtyRect,
|
||||||
|
int aSkipSides);
|
||||||
|
|
||||||
static nscolor MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
static nscolor MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
||||||
nscolor aBackgroundColor,
|
nscolor aBackgroundColor,
|
||||||
|
@ -371,6 +440,106 @@ MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
||||||
return theColor;
|
return theColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetRadii(nsIFrame* aForFrame, const nsStyleBorder& aBorder,
|
||||||
|
const nsRect& aOrigBorderArea, const nsRect& aBorderArea,
|
||||||
|
gfxCornerSizes* aBgRadii)
|
||||||
|
{
|
||||||
|
nscoord radii[8];
|
||||||
|
bool haveRoundedCorners;
|
||||||
|
nsSize sz = aBorderArea.Size();
|
||||||
|
nsSize frameSize = aForFrame->GetSize();
|
||||||
|
if (&aBorder == aForFrame->StyleBorder() &&
|
||||||
|
frameSize == aOrigBorderArea.Size()) {
|
||||||
|
haveRoundedCorners = aForFrame->GetBorderRadii(sz, sz, 0, radii);
|
||||||
|
} else {
|
||||||
|
haveRoundedCorners =
|
||||||
|
nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius, frameSize, sz, 0, radii);
|
||||||
|
}
|
||||||
|
if (haveRoundedCorners) {
|
||||||
|
auto d2a = aForFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
|
nsCSSRendering::ComputePixelRadii(radii, d2a, aBgRadii);
|
||||||
|
}
|
||||||
|
return haveRoundedCorners;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsRect
|
||||||
|
JoinBoxesForVerticalSlice(nsIFrame* aFrame, const nsRect& aBorderArea)
|
||||||
|
{
|
||||||
|
// Inflate vertically as if our continuations were laid out vertically
|
||||||
|
// adjacent. Note that we don't touch the width.
|
||||||
|
nsRect borderArea = aBorderArea;
|
||||||
|
nscoord h = 0;
|
||||||
|
nsIFrame* f = aFrame->GetNextContinuation();
|
||||||
|
for (; f; f = f->GetNextContinuation()) {
|
||||||
|
MOZ_ASSERT(!(f->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT),
|
||||||
|
"anonymous ib-split block shouldn't have border/background");
|
||||||
|
h += f->GetRect().height;
|
||||||
|
}
|
||||||
|
borderArea.height += h;
|
||||||
|
h = 0;
|
||||||
|
f = aFrame->GetPrevContinuation();
|
||||||
|
for (; f; f = f->GetPrevContinuation()) {
|
||||||
|
MOZ_ASSERT(!(f->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT),
|
||||||
|
"anonymous ib-split block shouldn't have border/background");
|
||||||
|
h += f->GetRect().height;
|
||||||
|
}
|
||||||
|
borderArea.y -= h;
|
||||||
|
borderArea.height += h;
|
||||||
|
return borderArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inflate aBorderArea which is relative to aFrame's origin to calculate
|
||||||
|
* a hypothetical non-split frame area for all the continuations.
|
||||||
|
* See "Joining Boxes for 'slice'" in
|
||||||
|
* http://dev.w3.org/csswg/css-break/#break-decoration
|
||||||
|
*/
|
||||||
|
enum InlineBoxOrder { eForBorder, eForBackground };
|
||||||
|
static nsRect
|
||||||
|
JoinBoxesForSlice(nsIFrame* aFrame, const nsRect& aBorderArea,
|
||||||
|
InlineBoxOrder aOrder)
|
||||||
|
{
|
||||||
|
if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
|
||||||
|
return (aOrder == eForBorder
|
||||||
|
? gInlineBGData->GetBorderContinuousRect(aFrame, aBorderArea)
|
||||||
|
: gInlineBGData->GetContinuousRect(aFrame)) +
|
||||||
|
aBorderArea.TopLeft();
|
||||||
|
}
|
||||||
|
return JoinBoxesForVerticalSlice(aFrame, aBorderArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsBoxDecorationSlice(const nsStyleBorder& aStyleBorder)
|
||||||
|
{
|
||||||
|
return aStyleBorder.mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsRect
|
||||||
|
BoxDecorationRectForBorder(nsIFrame* aFrame, const nsRect& aBorderArea,
|
||||||
|
const nsStyleBorder* aStyleBorder = nullptr)
|
||||||
|
{
|
||||||
|
if (!aStyleBorder) {
|
||||||
|
aStyleBorder = aFrame->StyleBorder();
|
||||||
|
}
|
||||||
|
return ::IsBoxDecorationSlice(*aStyleBorder)
|
||||||
|
? ::JoinBoxesForSlice(aFrame, aBorderArea, eForBorder)
|
||||||
|
: aBorderArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsRect
|
||||||
|
BoxDecorationRectForBackground(nsIFrame* aFrame, const nsRect& aBorderArea,
|
||||||
|
const nsStyleBorder* aStyleBorder = nullptr)
|
||||||
|
{
|
||||||
|
if (!aStyleBorder) {
|
||||||
|
aStyleBorder = aFrame->StyleBorder();
|
||||||
|
}
|
||||||
|
return ::IsBoxDecorationSlice(*aStyleBorder)
|
||||||
|
? ::JoinBoxesForSlice(aFrame, aBorderArea, eForBackground)
|
||||||
|
: aBorderArea;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Thebes Border Rendering Code Start
|
// Thebes Border Rendering Code Start
|
||||||
|
|
||||||
|
@ -449,10 +618,6 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||||
nsStyleContext* aStyleContext,
|
nsStyleContext* aStyleContext,
|
||||||
int aSkipSides)
|
int aSkipSides)
|
||||||
{
|
{
|
||||||
nsMargin border;
|
|
||||||
nscoord twipsRadii[8];
|
|
||||||
nsCompatibility compatMode = aPresContext->CompatibilityMode();
|
|
||||||
|
|
||||||
SN("++ PaintBorder");
|
SN("++ PaintBorder");
|
||||||
|
|
||||||
// Check to see if we have an appearance defined. If so, we let the theme
|
// Check to see if we have an appearance defined. If so, we let the theme
|
||||||
|
@ -467,66 +632,74 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||||
|
|
||||||
if (aStyleBorder.IsBorderImageLoaded()) {
|
if (aStyleBorder.IsBorderImageLoaded()) {
|
||||||
DrawBorderImage(aPresContext, aRenderingContext, aForFrame,
|
DrawBorderImage(aPresContext, aRenderingContext, aForFrame,
|
||||||
aBorderArea, aStyleBorder, aDirtyRect);
|
aBorderArea, aStyleBorder, aDirtyRect, aSkipSides);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get our style context's color struct.
|
// Get our style context's color struct.
|
||||||
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
||||||
|
|
||||||
// in NavQuirks mode we want to use the parent's context as a starting point
|
// In NavQuirks mode we want to use the parent's context as a starting point
|
||||||
// for determining the background color
|
// for determining the background color.
|
||||||
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame
|
bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
|
||||||
(aForFrame, compatMode == eCompatibility_NavQuirks ? true : false);
|
nsIFrame* bgFrame = FindNonTransparentBackgroundFrame(aForFrame, quirks);
|
||||||
nsStyleContext* bgContext = bgFrame->StyleContext();
|
nsStyleContext* bgContext = bgFrame->StyleContext();
|
||||||
nscolor bgColor =
|
nscolor bgColor =
|
||||||
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
||||||
|
|
||||||
border = aStyleBorder.GetComputedBorder();
|
nsMargin border = aStyleBorder.GetComputedBorder();
|
||||||
if ((0 == border.left) && (0 == border.right) &&
|
if (0 == border.left && 0 == border.right &&
|
||||||
(0 == border.top) && (0 == border.bottom)) {
|
0 == border.top && 0 == border.bottom) {
|
||||||
// Empty border area
|
// Empty border area
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsSize frameSize = aForFrame->GetSize();
|
// Compute the outermost boundary of the area that might be painted.
|
||||||
if (&aStyleBorder == aForFrame->StyleBorder() &&
|
// Same coordinate space as aBorderArea & aBGClipRect.
|
||||||
frameSize == aBorderArea.Size()) {
|
nsRect joinedBorderArea =
|
||||||
aForFrame->GetBorderRadii(twipsRadii);
|
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aStyleBorder);
|
||||||
|
gfxCornerSizes bgRadii;
|
||||||
|
::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
|
||||||
|
|
||||||
|
|
||||||
|
SF(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
|
||||||
|
joinedBorderArea.width, joinedBorderArea.height);
|
||||||
|
|
||||||
|
// start drawing
|
||||||
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
||||||
|
ctx->Save();
|
||||||
|
|
||||||
|
if (::IsBoxDecorationSlice(aStyleBorder)) {
|
||||||
|
if (aSkipSides == 0) {
|
||||||
|
// No continuations most likely, or ::first-letter that wants all border-
|
||||||
|
// sides on the first continuation.
|
||||||
|
joinedBorderArea = aBorderArea;
|
||||||
|
} else if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
|
||||||
|
// No need for a clip, just skip the sides we don't want.
|
||||||
|
::ApplySkipSides(aSkipSides, &border);
|
||||||
|
} else {
|
||||||
|
// We're drawing borders around the joined continuation boxes so we need
|
||||||
|
// to clip that to the slice that we want for this frame.
|
||||||
|
aRenderingContext.IntersectClip(aBorderArea);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nsIFrame::ComputeBorderRadii(aStyleBorder.mBorderRadius, frameSize,
|
MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
|
||||||
aBorderArea.Size(), aSkipSides, twipsRadii);
|
"Should use aBorderArea for box-decoration-break:clone");
|
||||||
|
MOZ_ASSERT(aForFrame->GetSkipSides() == 0,
|
||||||
|
"Should not skip sides for box-decoration-break:clone except "
|
||||||
|
"::first-letter/line continuations or other frame types that "
|
||||||
|
"don't have borders but those shouldn't reach this point.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn off rendering for all of the zero sized sides
|
// Convert to dev pixels.
|
||||||
if (aSkipSides & SIDE_BIT_TOP) border.top = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_RIGHT) border.right = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_BOTTOM) border.bottom = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_LEFT) border.left = 0;
|
|
||||||
|
|
||||||
// get the inside and outside parts of the border
|
|
||||||
nsRect outerRect(aBorderArea);
|
|
||||||
|
|
||||||
SF(" outerRect: %d %d %d %d\n", outerRect.x, outerRect.y, outerRect.width, outerRect.height);
|
|
||||||
|
|
||||||
// we can assume that we're already clipped to aDirtyRect -- I think? (!?)
|
|
||||||
|
|
||||||
// Get our conversion values
|
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
|
gfxRect joinedBorderAreaPx =
|
||||||
// convert outer and inner rects
|
nsLayoutUtils::RectToGfxRect(joinedBorderArea, twipsPerPixel);
|
||||||
gfxRect oRect(nsLayoutUtils::RectToGfxRect(outerRect, twipsPerPixel));
|
|
||||||
|
|
||||||
// convert the border widths
|
|
||||||
gfxFloat borderWidths[4] = { gfxFloat(border.top / twipsPerPixel),
|
gfxFloat borderWidths[4] = { gfxFloat(border.top / twipsPerPixel),
|
||||||
gfxFloat(border.right / twipsPerPixel),
|
gfxFloat(border.right / twipsPerPixel),
|
||||||
gfxFloat(border.bottom / twipsPerPixel),
|
gfxFloat(border.bottom / twipsPerPixel),
|
||||||
gfxFloat(border.left / twipsPerPixel) };
|
gfxFloat(border.left / twipsPerPixel) };
|
||||||
|
|
||||||
// convert the radii
|
|
||||||
gfxCornerSizes borderRadii;
|
|
||||||
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
|
||||||
|
|
||||||
uint8_t borderStyles[4];
|
uint8_t borderStyles[4];
|
||||||
nscolor borderColors[4];
|
nscolor borderColors[4];
|
||||||
nsBorderColors *compositeColors[4];
|
nsBorderColors *compositeColors[4];
|
||||||
|
@ -543,32 +716,25 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
SF(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
SF(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
||||||
|
//SF ("bgRadii: %f %f %f %f\n", bgRadii[0], bgRadii[1], bgRadii[2], bgRadii[3]);
|
||||||
// start drawing
|
|
||||||
gfxContext *ctx = aRenderingContext.ThebesContext();
|
|
||||||
|
|
||||||
ctx->Save();
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// this will draw a transparent red backround underneath the oRect area
|
// this will draw a transparent red backround underneath the border area
|
||||||
ctx->Save();
|
ctx->Save();
|
||||||
ctx->Rectangle(oRect);
|
ctx->Rectangle(joinedBorderAreaPx);
|
||||||
ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
|
ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
|
||||||
ctx->Fill();
|
ctx->Fill();
|
||||||
ctx->Restore();
|
ctx->Restore();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//SF ("borderRadii: %f %f %f %f\n", borderRadii[0], borderRadii[1], borderRadii[2], borderRadii[3]);
|
|
||||||
|
|
||||||
nsCSSBorderRenderer br(twipsPerPixel,
|
nsCSSBorderRenderer br(twipsPerPixel,
|
||||||
ctx,
|
ctx,
|
||||||
oRect,
|
joinedBorderAreaPx,
|
||||||
borderStyles,
|
borderStyles,
|
||||||
borderWidths,
|
borderWidths,
|
||||||
borderRadii,
|
bgRadii,
|
||||||
borderColors,
|
borderColors,
|
||||||
compositeColors,
|
compositeColors,
|
||||||
aSkipSides,
|
|
||||||
bgColor);
|
bgColor);
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
|
@ -688,7 +854,7 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
|
||||||
outlineWidths,
|
outlineWidths,
|
||||||
outlineRadii,
|
outlineRadii,
|
||||||
outlineColors,
|
outlineColors,
|
||||||
nullptr, 0,
|
nullptr,
|
||||||
bgColor);
|
bgColor);
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
|
@ -741,7 +907,7 @@ nsCSSRendering::PaintFocus(nsPresContext* aPresContext,
|
||||||
focusWidths,
|
focusWidths,
|
||||||
focusRadii,
|
focusRadii,
|
||||||
focusColors,
|
focusColors,
|
||||||
nullptr, 0,
|
nullptr,
|
||||||
NS_RGB(255, 0, 0));
|
NS_RGB(255, 0, 0));
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
|
@ -996,13 +1162,10 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||||
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
|
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
|
||||||
if (!shadows)
|
if (!shadows)
|
||||||
return;
|
return;
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
|
||||||
|
|
||||||
|
gfxContextAutoSaveRestore gfxStateRestorer;
|
||||||
bool hasBorderRadius;
|
bool hasBorderRadius;
|
||||||
bool nativeTheme; // mutually exclusive with hasBorderRadius
|
bool nativeTheme; // mutually exclusive with hasBorderRadius
|
||||||
gfxCornerSizes borderRadii;
|
|
||||||
|
|
||||||
// Get any border radius, since box-shadow must also have rounded corners if the frame does
|
|
||||||
const nsStyleDisplay* styleDisplay = aForFrame->StyleDisplay();
|
const nsStyleDisplay* styleDisplay = aForFrame->StyleDisplay();
|
||||||
nsITheme::Transparency transparency;
|
nsITheme::Transparency transparency;
|
||||||
if (aForFrame->IsThemed(styleDisplay, &transparency)) {
|
if (aForFrame->IsThemed(styleDisplay, &transparency)) {
|
||||||
|
@ -1013,17 +1176,29 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||||
nativeTheme = transparency != nsITheme::eOpaque;
|
nativeTheme = transparency != nsITheme::eOpaque;
|
||||||
} else {
|
} else {
|
||||||
nativeTheme = false;
|
nativeTheme = false;
|
||||||
|
hasBorderRadius = true; // we'll update this below
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRect frameRect = nativeTheme ?
|
||||||
|
aForFrame->GetVisualOverflowRectRelativeToSelf() + aFrameArea.TopLeft() :
|
||||||
|
aFrameArea;
|
||||||
|
frameRect = ::BoxDecorationRectForBorder(aForFrame, frameRect);
|
||||||
|
|
||||||
|
// Get any border radius, since box-shadow must also have rounded corners if
|
||||||
|
// the frame does.
|
||||||
|
gfxCornerSizes borderRadii;
|
||||||
|
const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
|
if (hasBorderRadius) {
|
||||||
nscoord twipsRadii[8];
|
nscoord twipsRadii[8];
|
||||||
NS_ASSERTION(aFrameArea.Size() == aForFrame->VisualBorderRectRelativeToSelf().Size(),
|
NS_ASSERTION(aFrameArea.Size() == aForFrame->VisualBorderRectRelativeToSelf().Size(),
|
||||||
"unexpected size");
|
"unexpected size");
|
||||||
hasBorderRadius = aForFrame->GetBorderRadii(twipsRadii);
|
nsSize sz = frameRect.Size();
|
||||||
|
hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, 0, twipsRadii);
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect frameRect =
|
|
||||||
nativeTheme ? aForFrame->GetVisualOverflowRectRelativeToSelf() + aFrameArea.TopLeft() : aFrameArea;
|
|
||||||
gfxRect frameGfxRect(nsLayoutUtils::RectToGfxRect(frameRect, twipsPerPixel));
|
gfxRect frameGfxRect(nsLayoutUtils::RectToGfxRect(frameRect, twipsPerPixel));
|
||||||
frameGfxRect.Round();
|
frameGfxRect.Round();
|
||||||
|
|
||||||
|
@ -1047,6 +1222,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||||
std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0));
|
std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skipSides = aForFrame->GetSkipSides();
|
||||||
for (uint32_t i = shadows->Length(); i > 0; --i) {
|
for (uint32_t i = shadows->Length(); i > 0; --i) {
|
||||||
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
||||||
if (shadowItem->mInset)
|
if (shadowItem->mInset)
|
||||||
|
@ -1127,7 +1303,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||||
} else {
|
} else {
|
||||||
renderContext->Save();
|
renderContext->Save();
|
||||||
// Clip out the area of the actual frame so the shadow is not shown within
|
// Clip out the area of the actual frame so the shadow is not shown within
|
||||||
// the frame
|
// the frame.
|
||||||
renderContext->NewPath();
|
renderContext->NewPath();
|
||||||
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
|
@ -1139,6 +1315,36 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||||
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
|
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
|
||||||
renderContext->Clip();
|
renderContext->Clip();
|
||||||
|
|
||||||
|
// Clip the shadow so that we only get the part that applies to aForFrame.
|
||||||
|
nsRect fragmentClip = shadowRectPlusBlur;
|
||||||
|
if (skipSides) {
|
||||||
|
if (skipSides & SIDE_BIT_LEFT) {
|
||||||
|
nscoord xmost = fragmentClip.XMost();
|
||||||
|
fragmentClip.x = aFrameArea.x;
|
||||||
|
fragmentClip.width = xmost - fragmentClip.x;
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_RIGHT) {
|
||||||
|
nscoord xmost = fragmentClip.XMost();
|
||||||
|
nscoord overflow = xmost - aFrameArea.XMost();
|
||||||
|
if (overflow > 0) {
|
||||||
|
fragmentClip.width -= overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_TOP) {
|
||||||
|
nscoord ymost = fragmentClip.YMost();
|
||||||
|
fragmentClip.y = aFrameArea.y;
|
||||||
|
fragmentClip.height = ymost - fragmentClip.y;
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_BOTTOM) {
|
||||||
|
nscoord ymost = fragmentClip.YMost();
|
||||||
|
nscoord overflow = ymost - aFrameArea.YMost();
|
||||||
|
if (overflow > 0) {
|
||||||
|
fragmentClip.height -= overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aRenderingContext.IntersectClip(fragmentClip);
|
||||||
|
|
||||||
gfxCornerSizes clipRectRadii;
|
gfxCornerSizes clipRectRadii;
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
||||||
|
@ -1188,18 +1394,20 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
|
||||||
|
aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
|
||||||
|
|
||||||
|
nsRect frameRect = ::BoxDecorationRectForBorder(aForFrame, aFrameArea);
|
||||||
|
nsRect paddingRect = frameRect;
|
||||||
|
nsMargin border = aForFrame->GetUsedBorder();
|
||||||
|
paddingRect.Deflate(border);
|
||||||
|
|
||||||
// Get any border radius, since box-shadow must also have rounded corners
|
// Get any border radius, since box-shadow must also have rounded corners
|
||||||
// if the frame does.
|
// if the frame does.
|
||||||
nscoord twipsRadii[8];
|
nscoord twipsRadii[8];
|
||||||
NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
|
nsSize sz = frameRect.Size();
|
||||||
aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
|
bool hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, 0, twipsRadii);
|
||||||
bool hasBorderRadius = aForFrame->GetBorderRadii(twipsRadii);
|
const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
|
||||||
|
|
||||||
nsRect paddingRect = aFrameArea;
|
|
||||||
nsMargin border = aForFrame->GetUsedBorder();
|
|
||||||
aForFrame->ApplySkipSides(border);
|
|
||||||
paddingRect.Deflate(border);
|
|
||||||
|
|
||||||
gfxCornerSizes innerRadii;
|
gfxCornerSizes innerRadii;
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
|
@ -1221,13 +1429,9 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
||||||
if (!shadowItem->mInset)
|
if (!shadowItem->mInset)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
// shadowPaintRect: the area to paint on the temp surface
|
||||||
* shadowRect: the frame's padding rect
|
// shadowClipRect: the area on the temporary surface within shadowPaintRect
|
||||||
* shadowPaintRect: the area to paint on the temp surface, larger than shadowRect
|
// that we will NOT paint in
|
||||||
* so that blurs still happen properly near the edges
|
|
||||||
* shadowClipRect: the area on the temporary surface within shadowPaintRect
|
|
||||||
* that we will NOT paint in
|
|
||||||
*/
|
|
||||||
nscoord blurRadius = shadowItem->mRadius;
|
nscoord blurRadius = shadowItem->mRadius;
|
||||||
nsMargin blurMargin =
|
nsMargin blurMargin =
|
||||||
nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel);
|
nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel);
|
||||||
|
@ -1506,6 +1710,7 @@ GetBackgroundClip(gfxContext *aCtx, uint8_t aBackgroundClip,
|
||||||
aClipState->mCustomClip = false;
|
aClipState->mCustomClip = false;
|
||||||
aClipState->mRadiiAreOuter = true;
|
aClipState->mRadiiAreOuter = true;
|
||||||
aClipState->mClippedRadii = aBGRadii;
|
aClipState->mClippedRadii = aBGRadii;
|
||||||
|
|
||||||
if (aForFrame->GetType() == nsGkAtoms::scrollFrame &&
|
if (aForFrame->GetType() == nsGkAtoms::scrollFrame &&
|
||||||
NS_STYLE_BG_ATTACHMENT_LOCAL == aBackgroundAttachment) {
|
NS_STYLE_BG_ATTACHMENT_LOCAL == aBackgroundAttachment) {
|
||||||
// As of this writing, this is still in discussion in the CSS Working Group
|
// As of this writing, this is still in discussion in the CSS Working Group
|
||||||
|
@ -1604,15 +1809,13 @@ SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
|
||||||
// as above with bgArea, arguably a bug, but table painting seems
|
// as above with bgArea, arguably a bug, but table painting seems
|
||||||
// to depend on it.
|
// to depend on it.
|
||||||
|
|
||||||
if (aHaveRoundedCorners || aClipState.mHasAdditionalBGClipArea) {
|
|
||||||
aAutoSR->Reset(aCtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aClipState.mHasAdditionalBGClipArea) {
|
if (aClipState.mHasAdditionalBGClipArea) {
|
||||||
gfxRect bgAreaGfx = nsLayoutUtils::RectToGfxRect(
|
gfxRect bgAreaGfx = nsLayoutUtils::RectToGfxRect(
|
||||||
aClipState.mAdditionalBGClipArea, aAppUnitsPerPixel);
|
aClipState.mAdditionalBGClipArea, aAppUnitsPerPixel);
|
||||||
bgAreaGfx.Round();
|
bgAreaGfx.Round();
|
||||||
bgAreaGfx.Condition();
|
bgAreaGfx.Condition();
|
||||||
|
|
||||||
|
aAutoSR->EnsureSaved(aCtx);
|
||||||
aCtx->NewPath();
|
aCtx->NewPath();
|
||||||
aCtx->Rectangle(bgAreaGfx, true);
|
aCtx->Rectangle(bgAreaGfx, true);
|
||||||
aCtx->Clip();
|
aCtx->Clip();
|
||||||
|
@ -1633,6 +1836,7 @@ SetupBackgroundClip(BackgroundClipState& aClipState, gfxContext *aCtx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aAutoSR->EnsureSaved(aCtx);
|
||||||
aCtx->NewPath();
|
aCtx->NewPath();
|
||||||
aCtx->RoundedRectangle(bgAreaGfx, aClipState.mClippedRadii, aClipState.mRadiiAreOuter);
|
aCtx->RoundedRectangle(bgAreaGfx, aClipState.mClippedRadii, aClipState.mRadiiAreOuter);
|
||||||
aCtx->Clip();
|
aCtx->Clip();
|
||||||
|
@ -2407,26 +2611,14 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Compute the outermost boundary of the area that might be painted.
|
// Compute the outermost boundary of the area that might be painted.
|
||||||
gfxContext *ctx = aRenderingContext.ThebesContext();
|
// Same coordinate space as aBorderArea & aBGClipRect.
|
||||||
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
|
nsRect paintBorderArea =
|
||||||
|
::BoxDecorationRectForBackground(aForFrame, aBorderArea, &aBorder);
|
||||||
// Same coordinate space as aBorderArea & aBGClipRect
|
nsRect clipBorderArea =
|
||||||
|
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aBorder);
|
||||||
gfxCornerSizes bgRadii;
|
gfxCornerSizes bgRadii;
|
||||||
bool haveRoundedCorners;
|
bool haveRoundedCorners =
|
||||||
{
|
::GetRadii(aForFrame, aBorder, aBorderArea, clipBorderArea, &bgRadii);
|
||||||
nscoord radii[8];
|
|
||||||
nsSize frameSize = aForFrame->GetSize();
|
|
||||||
if (&aBorder == aForFrame->StyleBorder() &&
|
|
||||||
frameSize == aBorderArea.Size()) {
|
|
||||||
haveRoundedCorners = aForFrame->GetBorderRadii(radii);
|
|
||||||
} else {
|
|
||||||
haveRoundedCorners = nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius,
|
|
||||||
frameSize, aBorderArea.Size(),
|
|
||||||
aForFrame->GetSkipSides(), radii);
|
|
||||||
}
|
|
||||||
if (haveRoundedCorners)
|
|
||||||
ComputePixelRadii(radii, appUnitsPerPixel, &bgRadii);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The 'bgClipArea' (used only by the image tiling logic, far below)
|
// The 'bgClipArea' (used only by the image tiling logic, far below)
|
||||||
// is the caller-provided aBGClipRect if any, or else the area
|
// is the caller-provided aBGClipRect if any, or else the area
|
||||||
|
@ -2434,6 +2626,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
// SetupCurrentBackgroundClip. (Arguably it should be the
|
// SetupCurrentBackgroundClip. (Arguably it should be the
|
||||||
// intersection, but that breaks the table painter -- in particular,
|
// intersection, but that breaks the table painter -- in particular,
|
||||||
// taking the intersection breaks reftests/bugs/403249-1[ab].)
|
// taking the intersection breaks reftests/bugs/403249-1[ab].)
|
||||||
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
||||||
|
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
|
||||||
BackgroundClipState clipState;
|
BackgroundClipState clipState;
|
||||||
uint8_t currentBackgroundClip;
|
uint8_t currentBackgroundClip;
|
||||||
bool isSolidBorder;
|
bool isSolidBorder;
|
||||||
|
@ -2463,7 +2657,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
|
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
|
||||||
aForFrame, aBorderArea,
|
aForFrame, clipBorderArea,
|
||||||
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
|
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
|
||||||
&clipState);
|
&clipState);
|
||||||
}
|
}
|
||||||
|
@ -2472,6 +2666,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
if (drawBackgroundColor && !isCanvasFrame)
|
if (drawBackgroundColor && !isCanvasFrame)
|
||||||
ctx->SetColor(gfxRGBA(bgColor));
|
ctx->SetColor(gfxRGBA(bgColor));
|
||||||
|
|
||||||
|
// NOTE: no Save() yet, we do that later by calling autoSR.EnsureSaved(ctx)
|
||||||
|
// in the cases we need it.
|
||||||
gfxContextAutoSaveRestore autoSR;
|
gfxContextAutoSaveRestore autoSR;
|
||||||
|
|
||||||
// If there is no background image, draw a color. (If there is
|
// If there is no background image, draw a color. (If there is
|
||||||
|
@ -2531,19 +2727,30 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
// already called GetBackgroundClip above and it stored its results
|
// already called GetBackgroundClip above and it stored its results
|
||||||
// in clipState.
|
// in clipState.
|
||||||
if (clipSet) {
|
if (clipSet) {
|
||||||
|
autoSR = gfxContextAutoSaveRestore(); // reset the previous one
|
||||||
GetBackgroundClip(ctx, currentBackgroundClip, layer.mAttachment, aForFrame,
|
GetBackgroundClip(ctx, currentBackgroundClip, layer.mAttachment, aForFrame,
|
||||||
aBorderArea, aDirtyRect, haveRoundedCorners,
|
clipBorderArea, aDirtyRect, haveRoundedCorners,
|
||||||
bgRadii, appUnitsPerPixel, &clipState);
|
bgRadii, appUnitsPerPixel, &clipState);
|
||||||
}
|
}
|
||||||
SetupBackgroundClip(clipState, ctx, haveRoundedCorners,
|
SetupBackgroundClip(clipState, ctx, haveRoundedCorners,
|
||||||
appUnitsPerPixel, &autoSR);
|
appUnitsPerPixel, &autoSR);
|
||||||
clipSet = true;
|
clipSet = true;
|
||||||
|
if (!clipBorderArea.IsEqualEdges(aBorderArea)) {
|
||||||
|
// We're drawing the background for the joined continuation boxes
|
||||||
|
// so we need to clip that to the slice that we want for this frame.
|
||||||
|
gfxRect clip =
|
||||||
|
nsLayoutUtils::RectToGfxRect(aBorderArea, appUnitsPerPixel);
|
||||||
|
autoSR.EnsureSaved(ctx);
|
||||||
|
ctx->NewPath();
|
||||||
|
ctx->SnappedRectangle(clip);
|
||||||
|
ctx->Clip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((aLayer < 0 || i == (uint32_t)startLayer) &&
|
if ((aLayer < 0 || i == (uint32_t)startLayer) &&
|
||||||
!clipState.mDirtyRectGfx.IsEmpty()) {
|
!clipState.mDirtyRectGfx.IsEmpty()) {
|
||||||
nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame,
|
nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame,
|
||||||
aFlags, aBorderArea, clipState.mBGClipArea, *bg, layer);
|
aFlags, paintBorderArea, clipState.mBGClipArea, layer);
|
||||||
if (!state.mFillArea.IsEmpty()) {
|
if (!state.mFillArea.IsEmpty()) {
|
||||||
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
||||||
NS_ASSERTION(ctx->CurrentOperator() == gfxContext::OPERATOR_OVER,
|
NS_ASSERTION(ctx->CurrentOperator() == gfxContext::OPERATOR_OVER,
|
||||||
|
@ -2552,7 +2759,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
state.mImageRenderer.DrawBackground(aPresContext, aRenderingContext,
|
state.mImageRenderer.DrawBackground(aPresContext, aRenderingContext,
|
||||||
state.mDestArea, state.mFillArea,
|
state.mDestArea, state.mFillArea,
|
||||||
state.mAnchor + aBorderArea.TopLeft(),
|
state.mAnchor + paintBorderArea.TopLeft(),
|
||||||
clipState.mDirtyRect);
|
clipState.mDirtyRect);
|
||||||
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_OVER);
|
ctx->SetOperator(gfxContext::OPERATOR_OVER);
|
||||||
|
@ -2607,26 +2814,12 @@ nsCSSRendering::PaintBackgroundColorWithSC(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the outermost boundary of the area that might be painted.
|
// Compute the outermost boundary of the area that might be painted.
|
||||||
gfxContext *ctx = aRenderingContext.ThebesContext();
|
// Same coordinate space as aBorderArea.
|
||||||
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
|
nsRect clipBorderArea =
|
||||||
|
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aBorder);
|
||||||
// Same coordinate space as aBorderArea
|
|
||||||
gfxCornerSizes bgRadii;
|
gfxCornerSizes bgRadii;
|
||||||
bool haveRoundedCorners;
|
bool haveRoundedCorners =
|
||||||
{
|
::GetRadii(aForFrame, aBorder, aBorderArea, clipBorderArea, &bgRadii);
|
||||||
nscoord radii[8];
|
|
||||||
nsSize frameSize = aForFrame->GetSize();
|
|
||||||
if (&aBorder == aForFrame->StyleBorder() &&
|
|
||||||
frameSize == aBorderArea.Size()) {
|
|
||||||
haveRoundedCorners = aForFrame->GetBorderRadii(radii);
|
|
||||||
} else {
|
|
||||||
haveRoundedCorners = nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius,
|
|
||||||
frameSize, aBorderArea.Size(),
|
|
||||||
aForFrame->GetSkipSides(), radii);
|
|
||||||
}
|
|
||||||
if (haveRoundedCorners)
|
|
||||||
ComputePixelRadii(radii, appUnitsPerPixel, &bgRadii);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The background is rendered over the 'background-clip' area,
|
// The background is rendered over the 'background-clip' area,
|
||||||
// which is normally equal to the border area but may be reduced
|
// which is normally equal to the border area but may be reduced
|
||||||
|
@ -2636,6 +2829,8 @@ nsCSSRendering::PaintBackgroundColorWithSC(nsPresContext* aPresContext,
|
||||||
// radii as the border code will.
|
// radii as the border code will.
|
||||||
// The background-color is drawn based on the bottom
|
// The background-color is drawn based on the bottom
|
||||||
// background-clip.
|
// background-clip.
|
||||||
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
||||||
|
nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
|
||||||
const nsStyleBackground *bg = aBackgroundSC->StyleBackground();
|
const nsStyleBackground *bg = aBackgroundSC->StyleBackground();
|
||||||
uint8_t currentBackgroundClip = bg->BottomLayer().mClip;
|
uint8_t currentBackgroundClip = bg->BottomLayer().mClip;
|
||||||
bool isSolidBorder =
|
bool isSolidBorder =
|
||||||
|
@ -2650,7 +2845,7 @@ nsCSSRendering::PaintBackgroundColorWithSC(nsPresContext* aPresContext,
|
||||||
|
|
||||||
BackgroundClipState clipState;
|
BackgroundClipState clipState;
|
||||||
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
|
GetBackgroundClip(ctx, currentBackgroundClip, bg->BottomLayer().mAttachment,
|
||||||
aForFrame, aBorderArea,
|
aForFrame, clipBorderArea,
|
||||||
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
|
aDirtyRect, haveRoundedCorners, bgRadii, appUnitsPerPixel,
|
||||||
&clipState);
|
&clipState);
|
||||||
|
|
||||||
|
@ -2675,47 +2870,17 @@ nsRect
|
||||||
nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer,
|
const nsStyleBackground::Layer& aLayer,
|
||||||
nsIFrame** aAttachedToFrame)
|
nsIFrame** aAttachedToFrame)
|
||||||
{
|
{
|
||||||
// Compute background origin area relative to aBorderArea now as we may need
|
// Compute background origin area relative to aBorderArea now as we may need
|
||||||
// it to compute the effective image size for a CSS gradient.
|
// it to compute the effective image size for a CSS gradient.
|
||||||
nsRect bgPositioningArea(0, 0, 0, 0);
|
nsRect bgPositioningArea;
|
||||||
|
|
||||||
nsIAtom* frameType = aForFrame->GetType();
|
nsIAtom* frameType = aForFrame->GetType();
|
||||||
nsIFrame* geometryFrame = aForFrame;
|
nsIFrame* geometryFrame = aForFrame;
|
||||||
if (frameType == nsGkAtoms::inlineFrame) {
|
if (MOZ_UNLIKELY(frameType == nsGkAtoms::scrollFrame &&
|
||||||
// XXXjwalden Strictly speaking this is not quite faithful to how
|
NS_STYLE_BG_ATTACHMENT_LOCAL == aLayer.mAttachment)) {
|
||||||
// background-break is supposed to interact with background-origin values,
|
|
||||||
// but it's a non-trivial amount of work to make it fully conformant, and
|
|
||||||
// until the specification is more finalized (and assuming background-break
|
|
||||||
// even makes the cut) it doesn't make sense to hammer out exact behavior.
|
|
||||||
switch (aBackground.mBackgroundInlinePolicy) {
|
|
||||||
case NS_STYLE_BG_INLINE_POLICY_EACH_BOX:
|
|
||||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
|
||||||
break;
|
|
||||||
case NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX:
|
|
||||||
bgPositioningArea = gInlineBGData->GetBoundingRect(aForFrame);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NS_ERROR("Unknown background-inline-policy value! "
|
|
||||||
"Please, teach me what to do.");
|
|
||||||
case NS_STYLE_BG_INLINE_POLICY_CONTINUOUS:
|
|
||||||
bgPositioningArea = gInlineBGData->GetContinuousRect(aForFrame);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (frameType == nsGkAtoms::canvasFrame) {
|
|
||||||
geometryFrame = aForFrame->GetFirstPrincipalChild();
|
|
||||||
// geometryFrame might be null if this canvas is a page created
|
|
||||||
// as an overflow container (e.g. the in-flow content has already
|
|
||||||
// finished and this page only displays the continuations of
|
|
||||||
// absolutely positioned content).
|
|
||||||
if (geometryFrame) {
|
|
||||||
bgPositioningArea = geometryFrame->GetRect();
|
|
||||||
}
|
|
||||||
} else if (frameType == nsGkAtoms::scrollFrame &&
|
|
||||||
NS_STYLE_BG_ATTACHMENT_LOCAL == aLayer.mAttachment) {
|
|
||||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
|
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
|
||||||
bgPositioningArea = nsRect(
|
bgPositioningArea = nsRect(
|
||||||
scrollableFrame->GetScrolledFrame()->GetPosition()
|
scrollableFrame->GetScrolledFrame()->GetPosition()
|
||||||
|
@ -2739,6 +2904,17 @@ nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
*aAttachedToFrame = aForFrame;
|
*aAttachedToFrame = aForFrame;
|
||||||
return bgPositioningArea;
|
return bgPositioningArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MOZ_UNLIKELY(frameType == nsGkAtoms::canvasFrame)) {
|
||||||
|
geometryFrame = aForFrame->GetFirstPrincipalChild();
|
||||||
|
// geometryFrame might be null if this canvas is a page created
|
||||||
|
// as an overflow container (e.g. the in-flow content has already
|
||||||
|
// finished and this page only displays the continuations of
|
||||||
|
// absolutely positioned content).
|
||||||
|
if (geometryFrame) {
|
||||||
|
bgPositioningArea = geometryFrame->GetRect();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||||
}
|
}
|
||||||
|
@ -2752,7 +2928,6 @@ nsCSSRendering::ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||||
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
|
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_BG_ORIGIN_CONTENT,
|
||||||
"unknown background-origin value");
|
"unknown background-origin value");
|
||||||
}
|
}
|
||||||
geometryFrame->ApplySkipSides(border);
|
|
||||||
bgPositioningArea.Deflate(border);
|
bgPositioningArea.Deflate(border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2836,11 +3011,10 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||||
uint32_t aFlags,
|
uint32_t aFlags,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsRect& aBGClipRect,
|
const nsRect& aBGClipRect,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer)
|
const nsStyleBackground::Layer& aLayer)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The background properties we need to keep in mind when drawing background
|
* The properties we need to keep in mind when drawing background
|
||||||
* layers are:
|
* layers are:
|
||||||
*
|
*
|
||||||
* background-image
|
* background-image
|
||||||
|
@ -2850,8 +3024,8 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||||
* background-clip
|
* background-clip
|
||||||
* background-origin
|
* background-origin
|
||||||
* background-size
|
* background-size
|
||||||
* background-break (-moz-background-inline-policy)
|
|
||||||
* background-blend-mode
|
* background-blend-mode
|
||||||
|
* box-decoration-break
|
||||||
*
|
*
|
||||||
* (background-color applies to the entire element and not to individual
|
* (background-color applies to the entire element and not to individual
|
||||||
* layers, so it is irrelevant to this method.)
|
* layers, so it is irrelevant to this method.)
|
||||||
|
@ -2874,22 +3048,21 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||||
* depends upon background-attachment (only in the case where that value
|
* depends upon background-attachment (only in the case where that value
|
||||||
* is 'fixed')
|
* is 'fixed')
|
||||||
* background-size
|
* background-size
|
||||||
* depends upon background-break (for the background positioning area for
|
* depends upon box-decoration-break (for the background positioning area
|
||||||
* resolving percentages), background-image (for the image's intrinsic
|
* for resolving percentages), background-image (for the image's intrinsic
|
||||||
* size), background-repeat (if that value is 'round'), and
|
* size), background-repeat (if that value is 'round'), and
|
||||||
* background-origin (for the background painting area, when
|
* background-origin (for the background painting area, when
|
||||||
* background-repeat is 'round')
|
* background-repeat is 'round')
|
||||||
* background-break
|
* box-decoration-break
|
||||||
* depends upon background-origin (specifying how the boxes making up the
|
* no dependencies
|
||||||
* background positioning area are determined)
|
|
||||||
*
|
*
|
||||||
* As a result of only-if dependencies we don't strictly do a topological
|
* As a result of only-if dependencies we don't strictly do a topological
|
||||||
* sort of the above properties when processing, but it's pretty close to one:
|
* sort of the above properties when processing, but it's pretty close to one:
|
||||||
*
|
*
|
||||||
* background-clip (by caller)
|
* background-clip (by caller)
|
||||||
* background-image
|
* background-image
|
||||||
* background-break, background-origin
|
* box-decoration-break, background-origin
|
||||||
* background-attachment (postfix for background-{origin,break} if 'fixed')
|
* background-attachment (postfix for background-origin if 'fixed')
|
||||||
* background-size
|
* background-size
|
||||||
* background-position
|
* background-position
|
||||||
* background-repeat
|
* background-repeat
|
||||||
|
@ -2915,7 +3088,7 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
||||||
// it to compute the effective image size for a CSS gradient.
|
// it to compute the effective image size for a CSS gradient.
|
||||||
nsRect bgPositioningArea =
|
nsRect bgPositioningArea =
|
||||||
ComputeBackgroundPositioningArea(aPresContext, aForFrame, aBorderArea,
|
ComputeBackgroundPositioningArea(aPresContext, aForFrame, aBorderArea,
|
||||||
aBackground, aLayer, &attachedToFrame);
|
aLayer, &attachedToFrame);
|
||||||
|
|
||||||
// For background-attachment:fixed backgrounds, we'll limit the area
|
// For background-attachment:fixed backgrounds, we'll limit the area
|
||||||
// where the background can be drawn to the viewport.
|
// where the background can be drawn to the viewport.
|
||||||
|
@ -2985,13 +3158,13 @@ nsCSSRendering::GetBackgroundLayerRect(nsPresContext* aPresContext,
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsRect& aClipRect,
|
const nsRect& aClipRect,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer,
|
const nsStyleBackground::Layer& aLayer,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
{
|
{
|
||||||
|
nsRect borderArea = ::BoxDecorationRectForBackground(aForFrame, aBorderArea);
|
||||||
nsBackgroundLayerState state =
|
nsBackgroundLayerState state =
|
||||||
PrepareBackgroundLayer(aPresContext, aForFrame, aFlags, aBorderArea,
|
PrepareBackgroundLayer(aPresContext, aForFrame, aFlags, borderArea,
|
||||||
aClipRect, aBackground, aLayer);
|
aClipRect, aLayer);
|
||||||
return state.mFillArea;
|
return state.mFillArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3029,7 +3202,8 @@ DrawBorderImage(nsPresContext* aPresContext,
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsStyleBorder& aStyleBorder,
|
const nsStyleBorder& aStyleBorder,
|
||||||
const nsRect& aDirtyRect)
|
const nsRect& aDirtyRect,
|
||||||
|
int aSkipSides)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(aStyleBorder.IsBorderImageLoaded(),
|
NS_PRECONDITION(aStyleBorder.IsBorderImageLoaded(),
|
||||||
"drawing border image that isn't successfully loaded");
|
"drawing border image that isn't successfully loaded");
|
||||||
|
@ -3051,10 +3225,39 @@ DrawBorderImage(nsPresContext* aPresContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: no Save() yet, we do that later by calling autoSR.EnsureSaved()
|
||||||
|
// in case we need it.
|
||||||
|
gfxContextAutoSaveRestore autoSR;
|
||||||
|
|
||||||
// Determine the border image area, which by default corresponds to the
|
// Determine the border image area, which by default corresponds to the
|
||||||
// border box but can be modified by 'border-image-outset'.
|
// border box but can be modified by 'border-image-outset'.
|
||||||
nsRect borderImgArea(aBorderArea);
|
// Note that 'border-radius' do not apply to 'border-image' borders per
|
||||||
borderImgArea.Inflate(aStyleBorder.GetImageOutset());
|
// <http://dev.w3.org/csswg/css-backgrounds/#corner-clipping>.
|
||||||
|
nsRect borderImgArea;
|
||||||
|
nsMargin borderWidths(aStyleBorder.GetComputedBorder());
|
||||||
|
nsMargin imageOutset(aStyleBorder.GetImageOutset());
|
||||||
|
if (::IsBoxDecorationSlice(aStyleBorder) && aSkipSides != 0) {
|
||||||
|
borderImgArea =
|
||||||
|
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aStyleBorder);
|
||||||
|
if (borderImgArea.IsEqualEdges(aBorderArea)) {
|
||||||
|
// No need for a clip, just skip the sides we don't want.
|
||||||
|
::ApplySkipSides(aSkipSides, &borderWidths);
|
||||||
|
::ApplySkipSides(aSkipSides, &imageOutset);
|
||||||
|
borderImgArea.Inflate(imageOutset);
|
||||||
|
} else {
|
||||||
|
// We're drawing borders around the joined continuation boxes so we need
|
||||||
|
// to clip that to the slice that we want for this frame.
|
||||||
|
borderImgArea.Inflate(imageOutset);
|
||||||
|
::ApplySkipSides(aSkipSides, &imageOutset);
|
||||||
|
nsRect clip = aBorderArea;
|
||||||
|
clip.Inflate(imageOutset);
|
||||||
|
autoSR.EnsureSaved(aRenderingContext.ThebesContext());
|
||||||
|
aRenderingContext.IntersectClip(clip);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
borderImgArea = aBorderArea;
|
||||||
|
borderImgArea.Inflate(imageOutset);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the image size used to compute slice points.
|
// Calculate the image size used to compute slice points.
|
||||||
CSSSizeOrRatio intrinsicSize = renderer.ComputeIntrinsicSize();
|
CSSSizeOrRatio intrinsicSize = renderer.ComputeIntrinsicSize();
|
||||||
|
@ -3093,7 +3296,6 @@ DrawBorderImage(nsPresContext* aPresContext,
|
||||||
value = imgDimension;
|
value = imgDimension;
|
||||||
slice.Side(s) = value;
|
slice.Side(s) = value;
|
||||||
|
|
||||||
nsMargin borderWidths(aStyleBorder.GetComputedBorder());
|
|
||||||
coord = aStyleBorder.mBorderImageWidth.Get(s);
|
coord = aStyleBorder.mBorderImageWidth.Get(s);
|
||||||
switch (coord.GetUnit()) {
|
switch (coord.GetUnit()) {
|
||||||
case eStyleUnit_Coord: // absolute dimension
|
case eStyleUnit_Coord: // absolute dimension
|
||||||
|
@ -4935,10 +5137,8 @@ nsContextBoxBlur::GetBlurRadiusMargin(nscoord aBlurRadius,
|
||||||
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
|
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
|
||||||
|
|
||||||
nsMargin result;
|
nsMargin result;
|
||||||
result.top = blurRadius.height * aAppUnitsPerDevPixel;
|
result.top = result.bottom = blurRadius.height * aAppUnitsPerDevPixel;
|
||||||
result.right = blurRadius.width * aAppUnitsPerDevPixel;
|
result.left = result.right = blurRadius.width * aAppUnitsPerDevPixel;
|
||||||
result.bottom = blurRadius.height * aAppUnitsPerDevPixel;
|
|
||||||
result.left = blurRadius.width * aAppUnitsPerDevPixel;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,7 +456,6 @@ struct nsCSSRendering {
|
||||||
ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
ComputeBackgroundPositioningArea(nsPresContext* aPresContext,
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer,
|
const nsStyleBackground::Layer& aLayer,
|
||||||
nsIFrame** aAttachedToFrame);
|
nsIFrame** aAttachedToFrame);
|
||||||
|
|
||||||
|
@ -466,7 +465,6 @@ struct nsCSSRendering {
|
||||||
uint32_t aFlags,
|
uint32_t aFlags,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsRect& aBGClipRect,
|
const nsRect& aBGClipRect,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer);
|
const nsStyleBackground::Layer& aLayer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -542,7 +540,6 @@ struct nsCSSRendering {
|
||||||
nsIFrame* aForFrame,
|
nsIFrame* aForFrame,
|
||||||
const nsRect& aBorderArea,
|
const nsRect& aBorderArea,
|
||||||
const nsRect& aClipRect,
|
const nsRect& aClipRect,
|
||||||
const nsStyleBackground& aBackground,
|
|
||||||
const nsStyleBackground::Layer& aLayer,
|
const nsStyleBackground::Layer& aLayer,
|
||||||
uint32_t aFlags);
|
uint32_t aFlags);
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,6 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
|
||||||
gfxCornerSizes& aBorderRadii,
|
gfxCornerSizes& aBorderRadii,
|
||||||
const nscolor* aBorderColors,
|
const nscolor* aBorderColors,
|
||||||
nsBorderColors* const* aCompositeColors,
|
nsBorderColors* const* aCompositeColors,
|
||||||
int aSkipSides,
|
|
||||||
nscolor aBackgroundColor)
|
nscolor aBackgroundColor)
|
||||||
: mContext(aDestContext),
|
: mContext(aDestContext),
|
||||||
mOuterRect(aOuterRect),
|
mOuterRect(aOuterRect),
|
||||||
|
@ -130,7 +129,6 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
|
||||||
mBorderColors(aBorderColors),
|
mBorderColors(aBorderColors),
|
||||||
mCompositeColors(aCompositeColors),
|
mCompositeColors(aCompositeColors),
|
||||||
mAUPP(aAppUnitsPerPixel),
|
mAUPP(aAppUnitsPerPixel),
|
||||||
mSkipSides(aSkipSides),
|
|
||||||
mBackgroundColor(aBackgroundColor)
|
mBackgroundColor(aBackgroundColor)
|
||||||
{
|
{
|
||||||
if (!mCompositeColors) {
|
if (!mCompositeColors) {
|
||||||
|
|
|
@ -79,7 +79,6 @@ struct nsCSSBorderRenderer {
|
||||||
gfxCornerSizes& aBorderRadii,
|
gfxCornerSizes& aBorderRadii,
|
||||||
const nscolor* aBorderColors,
|
const nscolor* aBorderColors,
|
||||||
nsBorderColors* const* aCompositeColors,
|
nsBorderColors* const* aCompositeColors,
|
||||||
int aSkipSides,
|
|
||||||
nscolor aBackgroundColor);
|
nscolor aBackgroundColor);
|
||||||
|
|
||||||
gfxCornerSizes mBorderCornerDimensions;
|
gfxCornerSizes mBorderCornerDimensions;
|
||||||
|
@ -105,8 +104,7 @@ struct nsCSSBorderRenderer {
|
||||||
// core app units per pixel
|
// core app units per pixel
|
||||||
int32_t mAUPP;
|
int32_t mAUPP;
|
||||||
|
|
||||||
// misc -- which sides to skip, the background color
|
// the background color
|
||||||
int mSkipSides;
|
|
||||||
nscolor mBackgroundColor;
|
nscolor mBackgroundColor;
|
||||||
|
|
||||||
// calculated values
|
// calculated values
|
||||||
|
|
|
@ -1934,14 +1934,8 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
nsBackgroundLayerState state =
|
nsBackgroundLayerState state =
|
||||||
nsCSSRendering::PrepareBackgroundLayer(presContext,
|
nsCSSRendering::PrepareBackgroundLayer(presContext, mFrame, flags,
|
||||||
mFrame,
|
borderArea, aClipRect, layer);
|
||||||
flags,
|
|
||||||
borderArea,
|
|
||||||
aClipRect,
|
|
||||||
*mBackgroundStyle,
|
|
||||||
layer);
|
|
||||||
|
|
||||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||||
// We only care about images here, not gradients.
|
// We only care about images here, not gradients.
|
||||||
if (!imageRenderer->IsRasterImage())
|
if (!imageRenderer->IsRasterImage())
|
||||||
|
@ -1974,14 +1968,8 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(LayerManager* aManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsBackgroundLayerState state =
|
nsBackgroundLayerState state =
|
||||||
nsCSSRendering::PrepareBackgroundLayer(presContext,
|
nsCSSRendering::PrepareBackgroundLayer(presContext, mFrame, flags,
|
||||||
mFrame,
|
borderArea, borderArea, layer);
|
||||||
flags,
|
|
||||||
borderArea,
|
|
||||||
borderArea,
|
|
||||||
*mBackgroundStyle,
|
|
||||||
layer);
|
|
||||||
|
|
||||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||||
// We only care about images here, not gradients.
|
// We only care about images here, not gradients.
|
||||||
if (!imageRenderer->IsRasterImage())
|
if (!imageRenderer->IsRasterImage())
|
||||||
|
@ -2194,12 +2182,13 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
*aSnap = true;
|
*aSnap = true;
|
||||||
|
|
||||||
// For policies other than EACH_BOX, don't try to optimize here, since
|
// For NS_STYLE_BOX_DECORATION_BREAK_SLICE, don't try to optimize here, since
|
||||||
// this could easily lead to O(N^2) behavior inside InlineBackgroundData,
|
// this could easily lead to O(N^2) behavior inside InlineBackgroundData,
|
||||||
// which expects frames to be sent to it in content order, not reverse
|
// which expects frames to be sent to it in content order, not reverse
|
||||||
// content order which we'll produce here.
|
// content order which we'll produce here.
|
||||||
// Of course, if there's only one frame in the flow, it doesn't matter.
|
// Of course, if there's only one frame in the flow, it doesn't matter.
|
||||||
if (mBackgroundStyle->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
|
if (mFrame->StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE ||
|
||||||
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
|
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
|
||||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||||
if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL) {
|
if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL) {
|
||||||
|
@ -2247,7 +2236,7 @@ nsDisplayBackgroundImage::GetPositioningArea()
|
||||||
return nsCSSRendering::ComputeBackgroundPositioningArea(
|
return nsCSSRendering::ComputeBackgroundPositioningArea(
|
||||||
mFrame->PresContext(), mFrame,
|
mFrame->PresContext(), mFrame,
|
||||||
nsRect(ToReferenceFrame(), mFrame->GetSize()),
|
nsRect(ToReferenceFrame(), mFrame->GetSize()),
|
||||||
*mBackgroundStyle, mBackgroundStyle->mLayers[mLayer],
|
mBackgroundStyle->mLayers[mLayer],
|
||||||
&attachedToFrame) + ToReferenceFrame();
|
&attachedToFrame) + ToReferenceFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2361,8 +2350,7 @@ nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder) {
|
||||||
}
|
}
|
||||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||||
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
|
return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
|
||||||
borderBox, clipRect,
|
borderBox, clipRect, layer,
|
||||||
*mBackgroundStyle, layer,
|
|
||||||
aBuilder->GetBackgroundPaintFlags());
|
aBuilder->GetBackgroundPaintFlags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2839,11 +2827,8 @@ nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint");
|
PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint");
|
||||||
for (uint32_t i = 0; i < rects.Length(); ++i) {
|
for (uint32_t i = 0; i < rects.Length(); ++i) {
|
||||||
aCtx->PushState();
|
|
||||||
aCtx->IntersectClip(rects[i]);
|
|
||||||
nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
|
nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
|
||||||
borderRect, rects[i], mOpacity);
|
borderRect, rects[i], mOpacity);
|
||||||
aCtx->PopState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ function foo()
|
||||||
<br style="clear: none;" id="br2">
|
<br style="clear: none;" id="br2">
|
||||||
<br style="height: auto; clear: both; width: auto;" id="br3">
|
<br style="height: auto; clear: both; width: auto;" id="br3">
|
||||||
<br style="position: static;" id="br4">
|
<br style="position: static;" id="br4">
|
||||||
<br style="background: yellow none repeat scroll 0% 0%; background-clip: initial; background-origin: initial; -moz-background-inline-policy: initial; display: inline;" id="br5">
|
<br style="background: yellow none repeat scroll 0% 0%; background-clip: initial; background-origin: initial; display: inline;" id="br5">
|
||||||
<br style="width: 1px; visibility: visible;" id="br6">
|
<br style="width: 1px; visibility: visible;" id="br6">
|
||||||
<br style="color: black; width: 2px; display: table-cell;" id="br7">
|
<br style="color: black; width: 2px; display: table-cell;" id="br7">
|
||||||
<table border="1"><tbody><tr style="display: list-item;" id="tableRow"><td>x</td></tr></tbody></table>
|
<table border="1"><tbody><tr style="display: list-item;" id="tableRow"><td>x</td></tr></tbody></table>
|
||||||
|
|
|
@ -849,12 +849,31 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
||||||
// This frame is a first-in-flow, but it might have a previous bidi
|
// This frame is a first-in-flow, but it might have a previous bidi
|
||||||
// continuation, in which case that continuation should handle the startSide
|
// continuation, in which case that continuation should handle the startSide
|
||||||
// border.
|
// border.
|
||||||
|
// For box-decoration-break:clone we setup clonePBM = startPBM + endPBM and
|
||||||
|
// add that to each line. For box-decoration-break:slice clonePBM is zero.
|
||||||
|
nscoord clonePBM = 0; // PBM = PaddingBorderMargin
|
||||||
|
const bool sliceBreak =
|
||||||
|
styleBorder->mBoxDecorationBreak == NS_STYLE_BOX_DECORATION_BREAK_SLICE;
|
||||||
if (!GetPrevContinuation()) {
|
if (!GetPrevContinuation()) {
|
||||||
aData->currentLine +=
|
nscoord startPBM =
|
||||||
// clamp negative calc() to 0
|
// clamp negative calc() to 0
|
||||||
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
|
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
|
||||||
styleBorder->GetComputedBorderWidth(startSide) +
|
styleBorder->GetComputedBorderWidth(startSide) +
|
||||||
GetCoord(styleMargin->mMargin.Get(startSide), 0);
|
GetCoord(styleMargin->mMargin.Get(startSide), 0);
|
||||||
|
if (MOZ_LIKELY(sliceBreak)) {
|
||||||
|
aData->currentLine += startPBM;
|
||||||
|
} else {
|
||||||
|
clonePBM = startPBM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nscoord endPBM =
|
||||||
|
// clamp negative calc() to 0
|
||||||
|
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
|
||||||
|
styleBorder->GetComputedBorderWidth(endSide) +
|
||||||
|
GetCoord(styleMargin->mMargin.Get(endSide), 0);
|
||||||
|
if (MOZ_UNLIKELY(!sliceBreak)) {
|
||||||
|
clonePBM += endPBM;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsLineList_iterator* savedLine = aData->line;
|
const nsLineList_iterator* savedLine = aData->line;
|
||||||
|
@ -863,6 +882,9 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
||||||
nsContainerFrame *lastInFlow;
|
nsContainerFrame *lastInFlow;
|
||||||
for (nsContainerFrame *nif = this; nif;
|
for (nsContainerFrame *nif = this; nif;
|
||||||
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
|
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
|
||||||
|
if (aData->currentLine == 0) {
|
||||||
|
aData->currentLine = clonePBM;
|
||||||
|
}
|
||||||
for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
|
for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
|
||||||
kid = kid->GetNextSibling()) {
|
kid = kid->GetNextSibling()) {
|
||||||
if (aType == nsLayoutUtils::MIN_WIDTH)
|
if (aType == nsLayoutUtils::MIN_WIDTH)
|
||||||
|
@ -891,12 +913,8 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
||||||
// We reached the last-in-flow, but it might have a next bidi
|
// We reached the last-in-flow, but it might have a next bidi
|
||||||
// continuation, in which case that continuation should handle
|
// continuation, in which case that continuation should handle
|
||||||
// the endSide border.
|
// the endSide border.
|
||||||
if (!lastInFlow->GetNextContinuation()) {
|
if (MOZ_LIKELY(!lastInFlow->GetNextContinuation() && sliceBreak)) {
|
||||||
aData->currentLine +=
|
aData->currentLine += endPBM;
|
||||||
// clamp negative calc() to 0
|
|
||||||
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
|
|
||||||
styleBorder->GetComputedBorderWidth(endSide) +
|
|
||||||
GetCoord(styleMargin->mMargin.Get(endSide), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -953,6 +953,11 @@ nsIFrame::GetUsedPadding() const
|
||||||
int
|
int
|
||||||
nsIFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsIFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the logical skip sides to physical sides using the frame's
|
// Convert the logical skip sides to physical sides using the frame's
|
||||||
// writing mode
|
// writing mode
|
||||||
WritingMode writingMode = GetWritingMode();
|
WritingMode writingMode = GetWritingMode();
|
||||||
|
@ -1277,7 +1282,8 @@ nsIFrame::OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ bool
|
/* virtual */ bool
|
||||||
nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
|
nsIFrame::GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
|
||||||
|
int aSkipSides, nscoord aRadii[8]) const
|
||||||
{
|
{
|
||||||
if (IsThemed()) {
|
if (IsThemed()) {
|
||||||
// When we're themed, the native theme code draws the border and
|
// When we're themed, the native theme code draws the border and
|
||||||
|
@ -1292,9 +1298,16 @@ nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
nsSize size = GetSize();
|
return ComputeBorderRadii(StyleBorder()->mBorderRadius,
|
||||||
return ComputeBorderRadii(StyleBorder()->mBorderRadius, size, size,
|
aFrameSize, aBorderArea,
|
||||||
GetSkipSides(), aRadii);
|
aSkipSides, aRadii);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsIFrame::GetBorderRadii(nscoord aRadii[8]) const
|
||||||
|
{
|
||||||
|
nsSize sz = GetSize();
|
||||||
|
return GetBorderRadii(sz, sz, GetSkipSides(), aRadii);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -4366,10 +4366,15 @@ ReduceRadii(nscoord aXBorder, nscoord aYBorder,
|
||||||
* have scrollbars.
|
* have scrollbars.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
ScrollFrameHelper::GetBorderRadii(nscoord aRadii[8]) const
|
ScrollFrameHelper::GetBorderRadii(const nsSize& aFrameSize,
|
||||||
|
const nsSize& aBorderArea,
|
||||||
|
int aSkipSides,
|
||||||
|
nscoord aRadii[8]) const
|
||||||
{
|
{
|
||||||
if (!mOuter->nsContainerFrame::GetBorderRadii(aRadii))
|
if (!mOuter->nsContainerFrame::GetBorderRadii(aFrameSize, aBorderArea,
|
||||||
|
aSkipSides, aRadii)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Since we can use GetActualScrollbarSizes (rather than
|
// Since we can use GetActualScrollbarSizes (rather than
|
||||||
// GetDesiredScrollbarSizes) since this doesn't affect reflow, we
|
// GetDesiredScrollbarSizes) since this doesn't affect reflow, we
|
||||||
|
|
|
@ -71,7 +71,8 @@ public:
|
||||||
bool& aCreateLayer,
|
bool& aCreateLayer,
|
||||||
bool aPositioned);
|
bool aPositioned);
|
||||||
|
|
||||||
bool GetBorderRadii(nscoord aRadii[8]) const;
|
bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
|
||||||
|
int aSkipSides, nscoord aRadii[8]) const;
|
||||||
|
|
||||||
// nsIReflowCallback
|
// nsIReflowCallback
|
||||||
virtual bool ReflowFinished() MOZ_OVERRIDE;
|
virtual bool ReflowFinished() MOZ_OVERRIDE;
|
||||||
|
@ -471,8 +472,9 @@ public:
|
||||||
const nsPoint& aScrollPosition);
|
const nsPoint& aScrollPosition);
|
||||||
nscoord GetIntrinsicVScrollbarWidth(nsRenderingContext *aRenderingContext);
|
nscoord GetIntrinsicVScrollbarWidth(nsRenderingContext *aRenderingContext);
|
||||||
|
|
||||||
virtual bool GetBorderRadii(nscoord aRadii[8]) const MOZ_OVERRIDE {
|
virtual bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
|
||||||
return mHelper.GetBorderRadii(aRadii);
|
int aSkipSides, nscoord aRadii[8]) const MOZ_OVERRIDE {
|
||||||
|
return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
|
||||||
|
@ -808,8 +810,9 @@ public:
|
||||||
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
|
NS_IMETHOD DoLayout(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE;
|
||||||
virtual nsresult GetPadding(nsMargin& aPadding) MOZ_OVERRIDE;
|
virtual nsresult GetPadding(nsMargin& aPadding) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool GetBorderRadii(nscoord aRadii[8]) const MOZ_OVERRIDE {
|
virtual bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
|
||||||
return mHelper.GetBorderRadii(aRadii);
|
int aSkipSides, nscoord aRadii[8]) const MOZ_OVERRIDE {
|
||||||
|
return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult Layout(nsBoxLayoutState& aState);
|
nsresult Layout(nsBoxLayoutState& aState);
|
||||||
|
|
|
@ -1042,12 +1042,16 @@ public:
|
||||||
static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
|
static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in border radii for this frame. Return whether any are
|
* Fill in border radii for this frame. Return whether any are nonzero.
|
||||||
* nonzero.
|
|
||||||
*
|
|
||||||
* Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
|
* Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
|
||||||
|
* aSkipSides is a union of SIDE_BIT_LEFT/RIGHT/TOP/BOTTOM bits that says
|
||||||
|
* which side(s) to skip.
|
||||||
*/
|
*/
|
||||||
virtual bool GetBorderRadii(nscoord aRadii[8]) const;
|
virtual bool GetBorderRadii(const nsSize& aFrameSize,
|
||||||
|
const nsSize& aBorderArea,
|
||||||
|
int aSkipSides,
|
||||||
|
nscoord aRadii[8]) const;
|
||||||
|
bool GetBorderRadii(nscoord aRadii[8]) const;
|
||||||
|
|
||||||
bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
|
bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
|
||||||
bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
|
bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
|
||||||
|
|
|
@ -1782,6 +1782,10 @@ nsImageFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
|
||||||
int
|
int
|
||||||
nsImageFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsImageFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
|
|
@ -115,7 +115,11 @@ nsInlineFrame::IsSelfEmpty()
|
||||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
|
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
|
||||||
!IsMarginZero(margin->mMargin.GetLeft());
|
!IsMarginZero(margin->mMargin.GetLeft());
|
||||||
if (haveLeft || haveRight) {
|
if (haveLeft || haveRight) {
|
||||||
if (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) {
|
// We skip this block and return false for box-decoration-break:clone since
|
||||||
|
// in that case all the continuations will have the border/padding/margin.
|
||||||
|
if ((GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
|
||||||
|
StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
bool haveStart, haveEnd;
|
bool haveStart, haveEnd;
|
||||||
if (NS_STYLE_DIRECTION_LTR == StyleVisibility()->mDirection) {
|
if (NS_STYLE_DIRECTION_LTR == StyleVisibility()->mDirection) {
|
||||||
haveStart = haveLeft;
|
haveStart = haveLeft;
|
||||||
|
@ -491,9 +495,15 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||||
RestyleManager* restyleManager = aPresContext->RestyleManager();
|
RestyleManager* restyleManager = aPresContext->RestyleManager();
|
||||||
WritingMode wm = aReflowState.GetWritingMode();
|
WritingMode wm = aReflowState.GetWritingMode();
|
||||||
nscoord startEdge = 0;
|
nscoord startEdge = 0;
|
||||||
|
const bool boxDecorationBreakClone =
|
||||||
|
MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE);
|
||||||
// Don't offset by our start borderpadding if we have a prev continuation or
|
// Don't offset by our start borderpadding if we have a prev continuation or
|
||||||
// if we're in a part of an {ib} split other than the first one.
|
// if we're in a part of an {ib} split other than the first one. For
|
||||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
// box-decoration-break:clone we always offset our start since all
|
||||||
|
// continuations have border/padding.
|
||||||
|
if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||||
}
|
}
|
||||||
nscoord availableISize = aReflowState.AvailableISize();
|
nscoord availableISize = aReflowState.AvailableISize();
|
||||||
|
@ -654,8 +664,10 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||||
|
|
||||||
// Make sure to not include our start border and padding if we have a prev
|
// Make sure to not include our start border and padding if we have a prev
|
||||||
// continuation or if we're in a part of an {ib} split other than the first
|
// continuation or if we're in a part of an {ib} split other than the first
|
||||||
// one.
|
// one. For box-decoration-break:clone we always include our start border
|
||||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
// and padding since all continuations have them.
|
||||||
|
if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,11 +676,13 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||||
* continuation and either not in an {ib} split or the last part of it. To
|
* continuation and either not in an {ib} split or the last part of it. To
|
||||||
* be the last continuation we have to be complete (so that we won't get a
|
* be the last continuation we have to be complete (so that we won't get a
|
||||||
* next-in-flow) and have no non-fluid continuations on our continuation
|
* next-in-flow) and have no non-fluid continuations on our continuation
|
||||||
* chain.
|
* chain. For box-decoration-break:clone we always apply the end border and
|
||||||
|
* padding since all continuations have them.
|
||||||
*/
|
*/
|
||||||
if (NS_FRAME_IS_COMPLETE(aStatus) &&
|
if ((NS_FRAME_IS_COMPLETE(aStatus) &&
|
||||||
!LastInFlow()->GetNextContinuation() &&
|
!LastInFlow()->GetNextContinuation() &&
|
||||||
!FrameIsNonLastInIBSplit()) {
|
!FrameIsNonLastInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,6 +886,11 @@ nsInlineFrame::PushFrames(nsPresContext* aPresContext,
|
||||||
int
|
int
|
||||||
nsInlineFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsInlineFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (!IsFirst()) {
|
if (!IsFirst()) {
|
||||||
nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation();
|
nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation();
|
||||||
|
|
|
@ -1076,9 +1076,12 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd,
|
||||||
// in an ib split. Note that the ib sibling (block-in-inline
|
// in an ib split. Note that the ib sibling (block-in-inline
|
||||||
// sibling) annotations only live on the first continuation, but we
|
// sibling) annotations only live on the first continuation, but we
|
||||||
// don't want to apply the start margin for later continuations
|
// don't want to apply the start margin for later continuations
|
||||||
// anyway.
|
// anyway. For box-decoration-break:clone we apply the start-margin
|
||||||
if (pfd->mFrame->GetPrevContinuation() ||
|
// on all continuations.
|
||||||
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
if ((pfd->mFrame->GetPrevContinuation() ||
|
||||||
|
pfd->mFrame->FrameIsNonFirstInIBSplit()) &&
|
||||||
|
aReflowState.mStyleBorder->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
// Zero this out so that when we compute the max-element-width of
|
// Zero this out so that when we compute the max-element-width of
|
||||||
// the frame we will properly avoid adding in the starting margin.
|
// the frame we will properly avoid adding in the starting margin.
|
||||||
pfd->mMargin.IStart(frameWM) = 0;
|
pfd->mMargin.IStart(frameWM) = 0;
|
||||||
|
@ -1160,6 +1163,9 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
* 3) The frame is in an {ib} split and is not the last part.
|
* 3) The frame is in an {ib} split and is not the last part.
|
||||||
*
|
*
|
||||||
* However, none of that applies if this is a letter frame (XXXbz why?)
|
* However, none of that applies if this is a letter frame (XXXbz why?)
|
||||||
|
*
|
||||||
|
* For box-decoration-break:clone we apply the end margin on all
|
||||||
|
* continuations (that are not letter frames).
|
||||||
*/
|
*/
|
||||||
if (pfd->mFrame->GetPrevContinuation() ||
|
if (pfd->mFrame->GetPrevContinuation() ||
|
||||||
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
||||||
|
@ -1167,8 +1173,10 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
}
|
}
|
||||||
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
|
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
|
||||||
pfd->mFrame->LastInFlow()->GetNextContinuation() ||
|
pfd->mFrame->LastInFlow()->GetNextContinuation() ||
|
||||||
pfd->mFrame->FrameIsNonLastInIBSplit())
|
pfd->mFrame->FrameIsNonLastInIBSplit()) &&
|
||||||
&& !pfd->GetFlag(PFD_ISLETTERFRAME)) {
|
!pfd->GetFlag(PFD_ISLETTERFRAME) &&
|
||||||
|
pfd->mFrame->StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
pfd->mMargin.IEnd(frameWM) = 0;
|
pfd->mMargin.IEnd(frameWM) = 0;
|
||||||
}
|
}
|
||||||
LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM);
|
LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM);
|
||||||
|
|
|
@ -253,8 +253,12 @@ nsSplittableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) co
|
||||||
return LOGICAL_SIDES_B_BOTH;
|
return LOGICAL_SIDES_B_BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
int skip = 0;
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skip = 0;
|
||||||
if (GetPrevInFlow()) {
|
if (GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>background-break: bounding-box</title>
|
|
||||||
<style type="text/css">
|
|
||||||
@font-face
|
|
||||||
{
|
|
||||||
font-family: Ahem;
|
|
||||||
src: url(../fonts/Ahem.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#outer
|
|
||||||
{
|
|
||||||
border: 1px solid black;
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
#ahem-lines
|
|
||||||
{
|
|
||||||
font-family: Ahem;
|
|
||||||
font-size: 32px;
|
|
||||||
white-space: pre;
|
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
-moz-background-inline-policy: bounding-box;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="outer">
|
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
|
||||||
<!-- EOL -->
|
|
||||||
<!-- EOL -->
|
|
||||||
</span></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>background-break: each-box</title>
|
<title>box-decoration-break: clone</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@font-face
|
@font-face
|
||||||
{
|
{
|
||||||
|
@ -21,14 +21,14 @@
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
background-image: url(blue-8x20-green-8x20.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
-moz-background-inline-policy: each-box;
|
box-decoration-break: clone;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="outer">
|
<div id="outer">
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
<span id="ahem-lines"> <!-- EOL -->
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
<!-- mix it up for clone --><!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
</span></div>
|
</span></div>
|
|
@ -1,37 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>background-size: cover; background-break: bounding-box</title>
|
|
||||||
<style type="text/css">
|
|
||||||
@font-face
|
|
||||||
{
|
|
||||||
font-family: Ahem;
|
|
||||||
src: url(../fonts/Ahem.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#outer
|
|
||||||
{
|
|
||||||
border: 1px solid black;
|
|
||||||
width: 10em;
|
|
||||||
}
|
|
||||||
#ahem-lines
|
|
||||||
{
|
|
||||||
font-family: Ahem;
|
|
||||||
font-size: 32px;
|
|
||||||
white-space: pre;
|
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
-moz-background-inline-policy: bounding-box;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="outer">
|
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
|
||||||
<!-- EOL -->
|
|
||||||
<!-- EOL -->
|
|
||||||
</span></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>background-size: cover; background-break: each-box</title>
|
<title>background-size: cover; box-decoration-break: clone</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@font-face
|
@font-face
|
||||||
{
|
{
|
||||||
|
@ -22,14 +22,14 @@
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
background-image: url(blue-8x20-green-8x20.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
-moz-background-inline-policy: each-box;
|
box-decoration-break: clone;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="outer">
|
<div id="outer">
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
<span id="ahem-lines"> <!-- EOL -->
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
<!-- mix it up for clone --><!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
</span></div>
|
</span></div>
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>background-size: cover; background-break: continuous</title>
|
<title>background-size: cover; box-decoration-break: slice</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@font-face
|
@font-face
|
||||||
{
|
{
|
||||||
|
@ -22,14 +22,14 @@
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
background-image: url(blue-8x20-green-8x20.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
-moz-background-inline-policy: continuous;
|
box-decoration-break: slice;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="outer">
|
<div id="outer">
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
<span id="ahem-lines"> <!-- EOL -->
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
<!-- mix it up for slice --><!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
</span></div>
|
</span></div>
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>background-break: continuous</title>
|
<title>box-decoration-break: slice</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@font-face
|
@font-face
|
||||||
{
|
{
|
||||||
|
@ -21,14 +21,14 @@
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
background-image: url(blue-8x20-green-8x20.png);
|
background-image: url(blue-8x20-green-8x20.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
-moz-background-inline-policy: continuous;
|
box-decoration-break: slice;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="outer">
|
<div id="outer">
|
||||||
<span id="ahem-lines"> <!-- EOL -->
|
<span id="ahem-lines"> <!-- EOL -->
|
||||||
<!-- mix it up for each-box and bounding-box --><!-- EOL -->
|
<!-- mix it up for slice --><!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
<!-- EOL -->
|
<!-- EOL -->
|
||||||
</span></div>
|
</span></div>
|
|
@ -90,19 +90,15 @@ fails-if(smallScreen&&Android) != background-size-body-contain-no-repeat.html ba
|
||||||
skip-if(B2G) == background-layers-1a.html background-layers-1-ref.html # bug 773482
|
skip-if(B2G) == background-layers-1a.html background-layers-1-ref.html # bug 773482
|
||||||
== background-layers-1b.html background-layers-1-ref.html
|
== background-layers-1b.html background-layers-1-ref.html
|
||||||
|
|
||||||
# -moz-background-inline-policy is touchy and hard to test due to stretching
|
# box-decoration-break's effect on backgrounds is touchy and hard to test due to stretching
|
||||||
# artifacts and the difficulty of covering exact lines, and its CSS3 analog is
|
# artifacts and the difficulty of covering exact lines, so just make sure
|
||||||
# on the chopping block at the moment, so just make sure background-size results
|
# background-size results in a different rendering when present.
|
||||||
# in a different rendering when present.
|
pref(layout.css.box-decoration-break.enabled,true) != background-size-cover-slice.html background-size-slice.html
|
||||||
!= background-size-cover-continuous.html background-size-continuous.html
|
pref(layout.css.box-decoration-break.enabled,true) != background-size-cover-clone.html background-size-clone.html
|
||||||
!= background-size-cover-each-box.html background-size-each-box.html
|
|
||||||
!= background-size-cover-bounding-box.html background-size-bounding-box.html
|
|
||||||
|
|
||||||
# ...and make sure each rendering with background-size is different from the
|
# ...and make sure each rendering with background-size is different from the
|
||||||
# others
|
# other
|
||||||
!= background-size-cover-continuous.html background-size-cover-each-box.html
|
pref(layout.css.box-decoration-break.enabled,true) != background-size-cover-slice.html background-size-cover-clone.html
|
||||||
!= background-size-cover-continuous.html background-size-cover-bounding-box.html
|
|
||||||
!= background-size-cover-each-box.html background-size-cover-bounding-box.html
|
|
||||||
|
|
||||||
== background-size-monster-ch.html background-size-monster-ref.html
|
== background-size-monster-ch.html background-size-monster-ref.html
|
||||||
== background-size-monster-cm.html background-size-monster-ref.html
|
== background-size-monster-cm.html background-size-monster-ref.html
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
<body style="line-height: 3; width: 500px; height: 250px;">
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: border-box; background-clip: border; background-origin: padding-box; background-origin: padding; margin: 7px 4px 2px 18px; border: 6px transparent solid; border-width: 2px 10px 15px 2px; -moz-background-inline-policy: continuous; background-inline-policy: continuous;">
|
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: border-box; background-origin: padding-box; margin: 7px 4px 2px 18px; border: 6px transparent solid; border-width: 2px 10px 15px 2px;">
|
||||||
blah<br>
|
blah<br>
|
||||||
blah<br>
|
blah<br>
|
||||||
blah
|
blah
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
<body style="line-height: 3; width: 500px; height: 250px;">
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-clip: padding; background-origin: content-box; background-origin: content; border: medium transparent solid; border-width: 7px 4px 2px 18px; padding: 2px 2% 3% 2px; -moz-background-inline-policy: continuous; background-inline-policy: continuous;">
|
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-origin: content-box; border: medium transparent solid; border-width: 7px 4px 2px 18px; padding: 2px 2% 3% 2px;">
|
||||||
blah<br>
|
blah<br>
|
||||||
blah<br>
|
blah<br>
|
||||||
blah
|
blah
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Testcase, bug 368020</title>
|
|
||||||
</head>
|
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: border-box; background-clip: border; background-origin: padding-box; background-origin: padding; margin: 7px 4px 2px 18px; border: 6px transparent solid; border-width: 2px 10px 15px 2px; -moz-background-inline-policy: bounding-box; background-inline-policy: bounding-box;">
|
|
||||||
blah<br>
|
|
||||||
blah<br>
|
|
||||||
blah
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,15 +0,0 @@
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Testcase, bug 368020</title>
|
|
||||||
</head>
|
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-clip: padding; background-origin: content-box; background-origin: content; border: medium transparent solid; border-width: 7px 4px 2px 18px; padding: 2px 2% 3% 2px; -moz-background-inline-policy: bounding-box; background-inline-policy: bounding-box;">
|
|
||||||
blah<br>
|
|
||||||
blah<br>
|
|
||||||
blah
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -5,7 +5,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
<body style="line-height: 3; width: 500px; height: 250px;">
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: border-box; background-clip: border; background-origin: padding-box; background-origin: padding; margin: 7px 4px 2px 18px; border: 6px transparent solid; border-width: 2px 10px 15px 2px; -moz-background-inline-policy: each-box; background-inline-policy: each-box;">
|
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: border-box; background-origin: padding-box; margin: 7px 4px 2px 18px; border: 6px transparent solid; border-width: 2px 10px 15px 2px; box-decoration-break: clone;">
|
||||||
blah<br>
|
blah<br>
|
||||||
blah<br>
|
blah<br>
|
||||||
blah
|
blah
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body style="line-height: 3; width: 500px; height: 250px;">
|
<body style="line-height: 3; width: 500px; height: 250px;">
|
||||||
|
|
||||||
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-clip: padding; background-origin: content-box; background-origin: content; border: medium transparent solid; border-width: 7px 4px 2px 18px; padding: 2px 10px 15px 2px; -moz-background-inline-policy: each-box; background-inline-policy: each-box;">
|
<span style="background: url(repeatable-diagonal-gradient.png); background-clip: padding-box; background-origin: content-box; border: medium transparent solid; border-width: 7px 4px 2px 18px; padding: 2px 10px 15px 2px; box-decoration-break: clone;">
|
||||||
blah<br>
|
blah<br>
|
||||||
blah<br>
|
blah<br>
|
||||||
blah
|
blah
|
||||||
|
|
|
@ -595,9 +595,8 @@ skip-if(B2G) == 367247-l-scroll.html 367247-l-auto.html
|
||||||
!= 367612-1g.html 367612-1-ref.html
|
!= 367612-1g.html 367612-1-ref.html
|
||||||
skip-if(B2G) random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == 368020-1.html 368020-1-ref.html
|
skip-if(B2G) random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == 368020-1.html 368020-1-ref.html
|
||||||
== 368020-2.html 368020-2-ref.html
|
== 368020-2.html 368020-2-ref.html
|
||||||
fails == 368020-3.html 368020-3-ref.html # bug 368085
|
== 368020-3.html 368020-3-ref.html
|
||||||
fails == 368020-4.html 368020-4-ref.html # bug 368085
|
pref(layout.css.box-decoration-break.enabled,true) == 368020-5.html 368020-5-ref.html
|
||||||
== 368020-5.html 368020-5-ref.html
|
|
||||||
== 368155-1.xhtml 368155-1-ref.xhtml
|
== 368155-1.xhtml 368155-1-ref.xhtml
|
||||||
asserts(4) == 368155-negative-margins-1.html 368155-negative-margins-1-ref.html # bug 387205 / bug 457397
|
asserts(4) == 368155-negative-margins-1.html 368155-negative-margins-1-ref.html # bug 387205 / bug 457397
|
||||||
# we can't test this because there's antialiasing involved, and our comparison
|
# we can't test this because there's antialiasing involved, and our comparison
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
|
||||||
|
span {
|
||||||
|
line-height:4em;
|
||||||
|
font-family:monospace;
|
||||||
|
padding: 3px 5px 7px 11px;
|
||||||
|
background-color: #0F0;
|
||||||
|
margin: 13px 17px 19px 23px;
|
||||||
|
border-left:13px dashed pink;
|
||||||
|
border-top:7px dashed blue;
|
||||||
|
border-right:3px dashed black;
|
||||||
|
border-bottom:1px dashed blue;
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 17px;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 17px;
|
||||||
|
margin-left:0;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 17px;
|
||||||
|
padding-right:0;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
margin-right:0;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-left:0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:10px">
|
||||||
|
|
||||||
|
<table border=1 cellpadding=10><tr>
|
||||||
|
<td><span class="o0"><b> a </b></span><br><span class="o0"><b> b </b></span><br><span class="o0"><b> c </b></span></td>
|
||||||
|
<td><span class="o10"><b> a </b></span><br><span class="o10"><b> b </b></span><br><span class="o10"><b> c </b></span></td>
|
||||||
|
<td><span class="o10x"><b> a </b></span><br><span class="o10x"><b> b </b></span><br><span class="o10x"><b> c </b></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table border=1 cellpadding=10><tr>
|
||||||
|
<td><span class="so0"><b> a </b></span><br><span class="so0"><b> b </b></span><br><span class="so0"><b> c </b></span></td>
|
||||||
|
<td><span class="so10"><b> a </b></span><br><span class="so10"><b> b </b></span><br><span class="so10"><b> c </b></span></td>
|
||||||
|
<td><span class="so10x"><b> a </b></span><br><span class="so10x"><b> b </b></span><br><span class="so10x"><b> c </b></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,71 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<link rel="help" href="http://dev.w3.org/csswg/css-break/#break-decoration">
|
||||||
|
<link rel="match" href="box-decoration-break-1-ref.html">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
|
||||||
|
span {
|
||||||
|
box-decoration-break:clone;
|
||||||
|
|
||||||
|
line-height:4em;
|
||||||
|
font-family:monospace;
|
||||||
|
padding: 3px 5px 7px 11px;
|
||||||
|
background-color: #0F0;
|
||||||
|
margin: 13px 17px 19px 23px;
|
||||||
|
border-left:13px dashed pink;
|
||||||
|
border-top:7px dashed blue;
|
||||||
|
border-right:3px dashed black;
|
||||||
|
border-bottom:1px dashed blue;
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 17px;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 17px;
|
||||||
|
margin-left:0;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 17px;
|
||||||
|
padding-right:0;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
margin-right:0;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-left:0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:10px">
|
||||||
|
|
||||||
|
<table border=1 cellpadding=10><tr>
|
||||||
|
<td><span class="o0"><b> a <br> b <br> c </b></span></td>
|
||||||
|
<td><span class="o10"><b> a <br> b <br> c </b></span></td>
|
||||||
|
<td><span class="o10x"><b> a <br> b <br> c </b></span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table border=1 cellpadding=10><tr>
|
||||||
|
<td><span class="so0"><b> a <br> b <br> c </b></span><br></td>
|
||||||
|
<td><span class="so10"><b> a <br> b <br> c </b></span><br></td>
|
||||||
|
<td><span class="so10x"><b> a <br> b <br> c </b></span><br></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,135 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Testcase for border-image + box-decoration-break</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=988653">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style type="text/css">
|
||||||
|
@font-face {
|
||||||
|
font-family: DejaVuSansMono;
|
||||||
|
src: url(../fonts/DejaVuSansMono.woff),url(DejaVuSansMono.woff);
|
||||||
|
}
|
||||||
|
* { font-family: DejaVuSansMono; }
|
||||||
|
|
||||||
|
html,body {
|
||||||
|
color:black; background-color:white; font-size:16px; padding:0; padding-left:10px; margin:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,.b.clone {
|
||||||
|
border: 5px solid red;
|
||||||
|
border-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD%2FgAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoUlEQVR42u3bwQ0AIAgEwcOmtXttgScmsxWQCTyp3EysJo61IliwYMGCBUuwYMGCBQuWYMGCBQsWLMGCBQsWLFiCBQsWLFiwBAsWLFiwYAkWLFiwYMESLFiwYMGCpXaVka%2BsO8dmOUNYggULFixYsAQLFixYsGAJFixYsGDBEixYsGDBgiVYsGDBggVLsGDBggULlmDBggULFizBggUL1t89N%2FYEtBGStpoAAAAASUVORK5CYII%3D) 10 10 repeat;
|
||||||
|
border-image-outset: 7px 3px 5px 9px;
|
||||||
|
}
|
||||||
|
.b {
|
||||||
|
border: 5px solid transparent;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
.b.clone {
|
||||||
|
background: pink;
|
||||||
|
height:28px;
|
||||||
|
}
|
||||||
|
.col3 .b.clone {
|
||||||
|
height:32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.columns {
|
||||||
|
-moz-columns: 2;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
background: grey;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.col3 {
|
||||||
|
-moz-columns: 3;
|
||||||
|
}
|
||||||
|
.vbreak { height:65px; width:41px; }
|
||||||
|
.h { width:30px;height:30px; background:grey; }
|
||||||
|
.m { margin-left:15px; }
|
||||||
|
.col3 .vbreak { height:115px; }
|
||||||
|
x { display:inline-block; width:31px; height:18px; line-height:1; }
|
||||||
|
y { display:inline-block; width:47px; height:18px; line-height:1; }
|
||||||
|
pos1 { position:absolute; top:50px; width:700px; }
|
||||||
|
pos2 { position:absolute; top:150px; width:700px; }
|
||||||
|
pos3 { position:absolute; top:380px; width:700px; }
|
||||||
|
pos4 { position:absolute; top:510px; width:700px; }
|
||||||
|
|
||||||
|
b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10 {position:absolute;}
|
||||||
|
c1,c2,c3,c4,c5,c6,c7,c8,c9,c10 {position:absolute; overflow:hidden; z-index:1;}
|
||||||
|
|
||||||
|
|
||||||
|
b1 { top:50px; left:20px; height:65px; width:41px; }
|
||||||
|
c1 { top:0; left:0; height:88px; width:200px; }
|
||||||
|
|
||||||
|
b2 { top:-38px; left:128px; height:66px; width:41px; }
|
||||||
|
c2 { top:50px; left:0; height:61px; width:200px; }
|
||||||
|
|
||||||
|
b3 { top:50px; left:240px; height:115px; width:41px; }
|
||||||
|
c3 { top:0; left:0; height:92px; width:600px; }
|
||||||
|
|
||||||
|
b4 { top:-42px; left:312px; height:115px; width:41px; }
|
||||||
|
c4 { top:50px; left:0; height:42px; width:600px; }
|
||||||
|
|
||||||
|
b5 { top:-84px; left:384px; height:116px; width:41px; }
|
||||||
|
c5 { top:50px; left:0; height:100px; width:600px; }
|
||||||
|
|
||||||
|
b6 { top:148px; left:20px; height:19px; z-index:1; }
|
||||||
|
m6 { top:135px; left:56px; height:55px; width:100px; background:white; z-index:2; }
|
||||||
|
|
||||||
|
b7 { top:30px; left:-36px; width:78px; height:19px; }
|
||||||
|
c7 { top:170px; left:20px; height:300px; width:200px; }
|
||||||
|
|
||||||
|
b8 { top:30px; left:77px; width:125px; height:19px; }
|
||||||
|
m8 { top:15px; left:113px; width:125px; height:55px; background:white; }
|
||||||
|
c8 { top:170px; left:20px; height:300px; width:600px; }
|
||||||
|
|
||||||
|
b9 { top:30px; left:-36px; width:125px; height:19px; }
|
||||||
|
c9 { top:222px; left:20px; height:300px; width:47px; }
|
||||||
|
|
||||||
|
b10 { top:30px; left:-83px; width:125px; height:19px; }
|
||||||
|
c10 { top:274px; left:20px; height:300px; width:156px; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<c1><b1></b1></c1>
|
||||||
|
<c2><b2></b2></c2>
|
||||||
|
<c3><b3></b3></c3>
|
||||||
|
<c4><b4></b4></c4>
|
||||||
|
<c5><b5></b5></c5>
|
||||||
|
<b6><x></x><y></y><br></b6><m6></m6>
|
||||||
|
<c7><b7><x></x><y></y></b7></c7>
|
||||||
|
<c8><b8><x></x><y></y><y></y></b8><m8></m8></c8>
|
||||||
|
<c9><b9><x></x><y></y><y></y></b9></c9>
|
||||||
|
<c10><b10><x></x><y></y><y></y></b10></c10>
|
||||||
|
<pre>box-decoration-break:slice</pre>
|
||||||
|
|
||||||
|
<pos1>
|
||||||
|
<div class="columns"><div class="b vbreak slice"></div></div>
|
||||||
|
<div class="columns col3"><div class="b vbreak slice"></div></div>
|
||||||
|
</pos1>
|
||||||
|
|
||||||
|
<pos2>
|
||||||
|
<span class="b slice"><x></x><div class="h"></div><y></y></span>
|
||||||
|
<span class="b slice m"><x></x><div class="h"></div><y></y><div class="h"></div><y></y></span>
|
||||||
|
|
||||||
|
<pre>box-decoration-break:clone</pre>
|
||||||
|
</pos2>
|
||||||
|
|
||||||
|
<pos3>
|
||||||
|
<div class="columns"><div class="b vbreak clone"></div><div class="b vbreak clone"></div></div>
|
||||||
|
<div class="columns col3"><div class="b vbreak clone"></div><div class="b vbreak clone"></div><div class="b vbreak clone"></div></div>
|
||||||
|
</pos3>
|
||||||
|
|
||||||
|
<pos4>
|
||||||
|
<span class="b clone"><x></x></span><div class="h"></div><span class="b clone"><y></y></span>
|
||||||
|
<span class="b clone m"><x></x></span><div class="h"></div><span class="b clone m"><y></y></span><div class="h"></div><span class="b clone m"><y></y></span>
|
||||||
|
</pos4>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Testcase for border-image + box-decoration-break</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=988653">
|
||||||
|
<link rel="help" href="http://dev.w3.org/csswg/css-break/#break-decoration">
|
||||||
|
<link rel="match" href="box-decoration-break-border-image-ref.html">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style type="text/css">
|
||||||
|
@font-face {
|
||||||
|
font-family: DejaVuSansMono;
|
||||||
|
src: url(../fonts/DejaVuSansMono.woff),url(DejaVuSansMono.woff);
|
||||||
|
}
|
||||||
|
* { font-family: DejaVuSansMono; }
|
||||||
|
|
||||||
|
html,body {
|
||||||
|
color:black; background-color:white; font-size:16px; padding:0; padding-left:10px; margin:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.b {
|
||||||
|
border: 5px solid red;
|
||||||
|
border-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD%2FgAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoUlEQVR42u3bwQ0AIAgEwcOmtXttgScmsxWQCTyp3EysJo61IliwYMGCBUuwYMGCBQuWYMGCBQsWLMGCBQsWLFiCBQsWLFiwBAsWLFiwYAkWLFiwYMESLFiwYMGCpXaVka%2BsO8dmOUNYggULFixYsAQLFixYsGAJFixYsGDBEixYsGDBgiVYsGDBggVLsGDBggULlmDBggULFizBggUL1t89N%2FYEtBGStpoAAAAASUVORK5CYII%3D) 10 10 repeat;
|
||||||
|
background: pink;
|
||||||
|
border-image-outset: 7px 3px 5px 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.columns {
|
||||||
|
-moz-columns: 2;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
background: grey;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
.col3 {
|
||||||
|
-moz-columns: 3;
|
||||||
|
}
|
||||||
|
.vbreak { height:65px; width:41px; }
|
||||||
|
.h { width:30px;height:30px; background:grey; }
|
||||||
|
.m { margin-left:15px; }
|
||||||
|
.col3 .vbreak { height:115px; }
|
||||||
|
.clone { box-decoration-break:clone; }
|
||||||
|
.slice { box-decoration-break:slice; }
|
||||||
|
x { display:inline-block; width:31px; height:18px; line-height:1; }
|
||||||
|
y { display:inline-block; width:47px; height:18px; line-height:1; }
|
||||||
|
pos1 { position:absolute; top:50px; width:700px; }
|
||||||
|
pos2 { position:absolute; top:150px; width:700px; }
|
||||||
|
pos3 { position:absolute; top:380px; width:700px; }
|
||||||
|
pos4 { position:absolute; top:510px; width:700px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre>box-decoration-break:slice</pre>
|
||||||
|
|
||||||
|
<pos1>
|
||||||
|
<div class="columns"><div class="b vbreak slice"></div></div>
|
||||||
|
<div class="columns col3"><div class="b vbreak slice"></div></div>
|
||||||
|
</pos1>
|
||||||
|
|
||||||
|
<pos2>
|
||||||
|
<span class="b slice" style="border-style:dashed;"><x></x><div class="h"></div><y></y></span>
|
||||||
|
<span class="b slice m" style="border-style:dashed;"><x></x><div class="h"></div><y></y><div class="h"></div><y></y></span>
|
||||||
|
|
||||||
|
<pre>box-decoration-break:clone</pre>
|
||||||
|
</pos2>
|
||||||
|
|
||||||
|
<pos3>
|
||||||
|
<div class="columns"><div class="b vbreak clone"></div></div>
|
||||||
|
<div class="columns col3"><div class="b vbreak clone"></div></div>
|
||||||
|
</pos3>
|
||||||
|
|
||||||
|
<pos4>
|
||||||
|
<span class="b clone" style="border-style:dashed;"><x></x><div class="h"></div><y></y></span>
|
||||||
|
<span class="b clone m" style="border-style:dashed;"><x></x><div class="h"></div><y></y><div class="h"></div><y></y></span>
|
||||||
|
</pos4>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,132 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone with inset box-shadow</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
span { border:3px dashed pink; margin:0 1em; line-height:4em; }
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family:monospace;
|
||||||
|
padding:1em 1em;
|
||||||
|
background-image: url(green-circle-alpha-32x32.png);
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.p0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.sp0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m b { visibility:hidden; }
|
||||||
|
.m { box-shadow:none; background:none; border-style:solid; border-radius:0; border-color:transparent; }
|
||||||
|
.m.o0, .m.o10, .m.o10x, .m.p0, .m.p10, .m.p10x { border-bottom-color: black; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:49px 50px;">
|
||||||
|
|
||||||
|
<div style="position:relative">
|
||||||
|
<table border=1 cellpadding=10><tr><td>
|
||||||
|
<span class="o0"><b> a </b></span><br><span class="o0"><b> b </b></span><br><span class="o0"><b> c </b></span><br>
|
||||||
|
<span class="o10"><b> a </b></span><br><span class="o10"><b> b </b></span><br><span class="o10"><b> c </b></span><br>
|
||||||
|
<span class="o10x"><b> a </b></span><br><span class="o10x"><b> b </b></span><br><span class="o10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="p0"><b> a </b></span><br><span class="p0"><b> b </b></span><br></span><span class="p0"><b> c </b></span><br>
|
||||||
|
<span class="p10"><b> a </b></span><br><span class="p10"><b> b </b></span><br><span class="p10"><b> c </b></span><br>
|
||||||
|
<span class="p10x"><b> a </b></span><br><span class="p10x"><b> b </b></span><br><span class="p10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="so0"><b> a </b></span><br><span class="so0"><b> b </b></span><br><span class="so0"><b> c </b></span><br>
|
||||||
|
<span class="so10"><b> a </b></span><br><span class="so10"><b> b </b></span><br><span class="so10"><b> c </b></span><br>
|
||||||
|
<span class="so10x"><b> a </b></span><br><span class="so10x"><b> b </b></span><br><span class="so10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="sp0"><b> a </b></span><br><span class="sp0"><b> b </b></span><br><span class="sp0"><b> c </b></span><br>
|
||||||
|
<span class="sp10"><b> a </b></span><br><span class="sp10"><b> b </b></span><br><span class="sp10"><b> c </b></span><br>
|
||||||
|
<span class="sp10x"><b> a </b></span><br><span class="sp10x"><b> b </b></span><br><span class="sp10x"><b> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="position:absolute; top:0px;left:0;">
|
||||||
|
<!-- mask out 1px of outer edge of the rounded borders at some places due to rounding errors -->
|
||||||
|
<table border=1 cellpadding=10><tr><td>
|
||||||
|
<span class="m o0"><b> a </b></span><br><span class="m o0"><b> b </b></span><br><span class="m o0"><b> c </b></span><br>
|
||||||
|
<span class="m o10"><b> a </b></span><br><span class="m o10"><b> b </b></span><br><span class="m o10"><b> c </b></span><br>
|
||||||
|
<span class="m o10x"><b> a </b></span><br><span class="m o10x"><b> b </b></span><br><span class="m o10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m p0"><b> a </b></span><br><span class="m p0"><b> b </b></span><br></span><span class="m p0"><b> c </b></span><br>
|
||||||
|
<span class="m p10"><b> a </b></span><br><span class="m p10"><b> b </b></span><br><span class="m p10"><b> c </b></span><br>
|
||||||
|
<span class="m p10x"><b> a </b></span><br><span class="m p10x"><b> b </b></span><br><span class="m p10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m so0"><b> a </b></span><br><span class="m so0"><b> b </b></span><br><span class="m so0"><b> c </b></span><br>
|
||||||
|
<span class="m so10"><b> a </b></span><br><span class="m so10"><b> b </b></span><br><span class="m so10"><b> c </b></span><br>
|
||||||
|
<span class="m so10x"><b> a </b></span><br><span class="m so10x"><b> b </b></span><br><span class="m so10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m sp0"><b> a </b></span><br><span class="m sp0"><b> b </b></span><br><span class="m sp0"><b> c </b></span><br>
|
||||||
|
<span class="m sp10"><b> a </b></span><br><span class="m sp10"><b> b </b></span><br><span class="m sp10"><b> c </b></span><br>
|
||||||
|
<span class="m sp10x"><b> a </b></span><br><span class="m sp10x"><b> b </b></span><br><span class="m sp10x"><b> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone with inset box-shadow</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<link rel="help" href="http://dev.w3.org/csswg/css-break/#break-decoration">
|
||||||
|
<link rel="match" href="box-decoration-break-with-inset-box-shadow-1-ref.html">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
span { border:3px dashed pink; margin:0 1em; line-height:4em; box-decoration-break:clone; }
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family:monospace;
|
||||||
|
padding:1em 1em;
|
||||||
|
background-image: url(green-circle-alpha-32x32.png);
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.p0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: inset 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.sp0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: inset 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m b { visibility:hidden; }
|
||||||
|
.m { box-shadow:none; background:none; border-style:solid; border-radius:0; border-color:transparent; }
|
||||||
|
.m.o0, .m.o10, .m.o10x, .m.p0, .m.p10, .m.p10x { border-bottom-color: black; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:49px 50px;">
|
||||||
|
|
||||||
|
<div style="position:relative">
|
||||||
|
<table border=1 cellpadding=10><tr><td>
|
||||||
|
<span class="o0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="o10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="o10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="p0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="p10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="p10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="so0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="so10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="so10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="sp0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="sp10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="sp10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="position:absolute; top:0px;left:0;">
|
||||||
|
<!-- mask out 1px of outer edge of the rounded borders at some places due to rounding errors -->
|
||||||
|
<table border=1 cellpadding=10><tr><td>
|
||||||
|
<span class="m o0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m o10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m o10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m p0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m p10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m p10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m so0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m so10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m so10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m sp0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m sp10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m sp10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone with outset box-shadow</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
span { border:3px dashed pink; line-height:80px; }
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family:monospace;
|
||||||
|
padding:1em 1em;
|
||||||
|
background-image: url(green-circle-alpha-32x32.png);
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.p0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.sp0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m b { visibility:hidden; }
|
||||||
|
.m { box-shadow:none; background:none; border-style:solid; border-radius:0; border-color:transparent; }
|
||||||
|
.m.o0, .m.o10, .m.o10x, .m.p0, .m.p10, .m.p10x { border-bottom-color: black; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:49px 50px;">
|
||||||
|
|
||||||
|
<div style="position:relative">
|
||||||
|
<table border=1 cellpadding=50 ><tr><td>
|
||||||
|
<span class="o0"><b> a </b></span><br><span class="o0"><b> b </b></span><br><span class="o0"><b> c </b></span><br>
|
||||||
|
<span class="o10"><b> a </b></span><br><span class="o10"><b> b </b></span><br><span class="o10"><b> c </b></span><br>
|
||||||
|
<span class="o10x"><b> a </b></span><br><span class="o10x"><b> b </b></span><br><span class="o10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="p0"><b> a </b></span><br><span class="p0"><b> b </b></span><br><span class="p0"><b> c </b></span><br>
|
||||||
|
<span class="p10"><b> a </b></span><br><span class="p10"><b> b </b></span><br><span class="p10"><b> c </b></span><br>
|
||||||
|
<span class="p10x"><b> a </b></span><br><span class="p10x"><b> b </b></span><br><span class="p10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="so0"><b> a </b></span><br><span class="so0"><b> b </b></span><br><span class="so0"><b> c </b></span><br>
|
||||||
|
<span class="so10"><b> a </b></span><br><span class="so10"><b> b </b></span><br><span class="so10"><b> c </b></span><br>
|
||||||
|
<span class="so10x"><b> a </b></span><br><span class="so10x"><b> b </b></span><br><span class="so10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="sp0"><b> a </b></span><br><span class="sp0"><b> b </b></span><br><span class="sp0"><b> c </b></span><br>
|
||||||
|
<span class="sp10"><b> a </b></span><br><span class="sp10"><b> b </b></span><br><span class="sp10"><b> c </b></span><br>
|
||||||
|
<span class="sp10x"><b> a </b></span><br><span class="sp10x"><b> b </b></span><br><span class="sp10x"><b> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="position:absolute; top:0px;left:0;">
|
||||||
|
<!-- mask out 1px of outer edge of the rounded borders at some places due to rounding errors -->
|
||||||
|
<table border=1 cellpadding=50 ><tr><td>
|
||||||
|
<span class="m o0"><b> a </b></span><br><span class="m o0"><b> b </b></span><br><span class="m o0"><b> c </b></span><br>
|
||||||
|
<span class="m o10"><b> a </b></span><br><span class="m o10"><b> b </b></span><br><span class="m o10"><b> c </b></span><br>
|
||||||
|
<span class="m o10x"><b> a </b></span><br><span class="m o10x"><b> b </b></span><br><span class="m o10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m p0"><b> a </b></span><br><span class="m p0"><b> b </b></span><br><span class="m p0"><b> c </b></span><br>
|
||||||
|
<span class="m p10"><b> a </b></span><br><span class="m p10"><b> b </b></span><br><span class="m p10"><b> c </b></span><br>
|
||||||
|
<span class="m p10x"><b> a </b></span><br><span class="m p10x"><b> b </b></span><br><span class="m p10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m so0"><b> a </b></span><br><span class="m so0"><b> b </b></span><br><span class="m so0"><b> c </b></span><br>
|
||||||
|
<span class="m so10"><b> a </b></span><br><span class="m so10"><b> b </b></span><br><span class="m so10"><b> c </b></span><br>
|
||||||
|
<span class="m so10x"><b> a </b></span><br><span class="m so10x"><b> b </b></span><br><span class="m so10x"><b> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m sp0"><b> a </b></span><br><span class="m sp0"><b> b </b></span><br><span class="m sp0"><b> c </b></span><br>
|
||||||
|
<span class="m sp10"><b> a </b></span><br><span class="m sp10"><b> b </b></span><br><span class="m sp10"><b> c </b></span><br>
|
||||||
|
<span class="m sp10x"><b> a </b></span><br><span class="m sp10x"><b> b </b></span><br><span class="m sp10x"><b> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Testing box-decoration-break:clone with outset box-shadow</title>
|
||||||
|
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613659">
|
||||||
|
<link rel="help" href="http://dev.w3.org/csswg/css-break/#break-decoration">
|
||||||
|
<link rel="match" href="box-decoration-break-with-outset-box-shadow-1-ref.html">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
span { border:3px dashed pink; line-height:80px; box-decoration-break:clone; }
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family:monospace;
|
||||||
|
padding:1em 1em;
|
||||||
|
background-image: url(green-circle-alpha-32x32.png);
|
||||||
|
}
|
||||||
|
.o0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.o10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.p0 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10 {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.p10x {
|
||||||
|
border-radius: 12px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.so0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.so10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
box-shadow: 0px 0px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
.sp0 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 0px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10 {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 10px #00F;
|
||||||
|
}
|
||||||
|
.sp10x {
|
||||||
|
border-radius: 0px;
|
||||||
|
-webkit-box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
box-shadow: 15px 9px 7px 0px #00F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m b { visibility:hidden; }
|
||||||
|
.m { box-shadow:none; background:none; border-style:solid; border-radius:0; border-color:transparent; }
|
||||||
|
.m.o0, .m.o10, .m.o10x, .m.p0, .m.p10, .m.p10x { border-bottom-color: black; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body style="margin:49px 50px;">
|
||||||
|
|
||||||
|
<div style="position:relative">
|
||||||
|
<table border=1 cellpadding=50 ><tr><td>
|
||||||
|
<span class="o0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="o10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="o10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="p0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="p10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="p10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="so0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="so10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="so10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="sp0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="sp10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="sp10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="position:absolute; top:0px;left:0;">
|
||||||
|
<!-- mask out 1px of outer edge of the rounded borders at some places due to rounding errors -->
|
||||||
|
<table border=1 cellpadding=50 ><tr><td>
|
||||||
|
<span class="m o0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m o10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m o10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m p0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m p10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m p10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m so0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m so10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m so10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td><td>
|
||||||
|
<span class="m sp0"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m sp10"><b> a <br> b <br> c </b></span><br>
|
||||||
|
<span class="m sp10x"><b> a <br> b <br> c </b></span><br>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 396 B |
|
@ -0,0 +1,5 @@
|
||||||
|
pref(layout.css.box-decoration-break.enabled,true) == box-decoration-break-1.html box-decoration-break-1-ref.html
|
||||||
|
|
||||||
|
fuzzy(1,20) pref(layout.css.box-decoration-break.enabled,true) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html
|
||||||
|
fuzzy(16,460) pref(layout.css.box-decoration-break.enabled,true) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html
|
||||||
|
random-if(!gtk2Widget) pref(layout.css.box-decoration-break.enabled,true) HTTP(..) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html
|
|
@ -56,6 +56,9 @@ include css-animations/reftest.list
|
||||||
# blending/
|
# blending/
|
||||||
include css-blending/reftest.list
|
include css-blending/reftest.list
|
||||||
|
|
||||||
|
# Tests for the css-break spec
|
||||||
|
include css-break/reftest.list
|
||||||
|
|
||||||
# css calc() tests
|
# css calc() tests
|
||||||
include css-calc/reftest.list
|
include css-calc/reftest.list
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,6 @@ CSS_KEY(border-box, border_box)
|
||||||
CSS_KEY(both, both)
|
CSS_KEY(both, both)
|
||||||
CSS_KEY(bottom, bottom)
|
CSS_KEY(bottom, bottom)
|
||||||
CSS_KEY(bottom-outside, bottom_outside)
|
CSS_KEY(bottom-outside, bottom_outside)
|
||||||
CSS_KEY(bounding-box, bounding_box)
|
|
||||||
CSS_KEY(break-all, break_all)
|
CSS_KEY(break-all, break_all)
|
||||||
CSS_KEY(break-word, break_word)
|
CSS_KEY(break-word, break_word)
|
||||||
CSS_KEY(brightness, brightness)
|
CSS_KEY(brightness, brightness)
|
||||||
|
@ -208,6 +207,7 @@ CSS_KEY(circle, circle)
|
||||||
CSS_KEY(cjk-decimal, cjk_decimal)
|
CSS_KEY(cjk-decimal, cjk_decimal)
|
||||||
CSS_KEY(cjk-ideographic, cjk_ideographic)
|
CSS_KEY(cjk-ideographic, cjk_ideographic)
|
||||||
CSS_KEY(clip, clip)
|
CSS_KEY(clip, clip)
|
||||||
|
CSS_KEY(clone, clone)
|
||||||
CSS_KEY(close-quote, close_quote)
|
CSS_KEY(close-quote, close_quote)
|
||||||
CSS_KEY(closest-corner, closest_corner)
|
CSS_KEY(closest-corner, closest_corner)
|
||||||
CSS_KEY(closest-side, closest_side)
|
CSS_KEY(closest-side, closest_side)
|
||||||
|
@ -257,7 +257,6 @@ CSS_KEY(double, double)
|
||||||
CSS_KEY(double-struck, double_struck)
|
CSS_KEY(double-struck, double_struck)
|
||||||
CSS_KEY(drop-shadow, drop_shadow)
|
CSS_KEY(drop-shadow, drop_shadow)
|
||||||
CSS_KEY(e-resize, e_resize)
|
CSS_KEY(e-resize, e_resize)
|
||||||
CSS_KEY(each-box, each_box)
|
|
||||||
CSS_KEY(ease, ease)
|
CSS_KEY(ease, ease)
|
||||||
CSS_KEY(ease-in, ease_in)
|
CSS_KEY(ease-in, ease_in)
|
||||||
CSS_KEY(ease-in-out, ease_in_out)
|
CSS_KEY(ease-in-out, ease_in_out)
|
||||||
|
@ -496,6 +495,7 @@ CSS_KEY(skew, skew)
|
||||||
CSS_KEY(skewx, skewx)
|
CSS_KEY(skewx, skewx)
|
||||||
CSS_KEY(skewy, skewy)
|
CSS_KEY(skewy, skewy)
|
||||||
CSS_KEY(slashed-zero, slashed_zero)
|
CSS_KEY(slashed-zero, slashed_zero)
|
||||||
|
CSS_KEY(slice, slice)
|
||||||
CSS_KEY(small, small)
|
CSS_KEY(small, small)
|
||||||
CSS_KEY(small-caps, small_caps)
|
CSS_KEY(small-caps, small_caps)
|
||||||
CSS_KEY(small-caption, small_caption)
|
CSS_KEY(small-caption, small_caption)
|
||||||
|
|
|
@ -274,10 +274,6 @@
|
||||||
// 'text-shadow' (see above) and 'box-shadow' (which is like the
|
// 'text-shadow' (see above) and 'box-shadow' (which is like the
|
||||||
// border properties).
|
// border properties).
|
||||||
|
|
||||||
// We include '-moz-background-inline-policy' (css3-background's
|
|
||||||
// 'background-break') in both as a background property, although this
|
|
||||||
// is somewhat questionable.
|
|
||||||
|
|
||||||
CSS_PROP_DISPLAY(
|
CSS_PROP_DISPLAY(
|
||||||
-moz-appearance,
|
-moz-appearance,
|
||||||
appearance,
|
appearance,
|
||||||
|
@ -537,18 +533,6 @@ CSS_PROP_BACKGROUND(
|
||||||
nullptr,
|
nullptr,
|
||||||
CSS_PROP_NO_OFFSET,
|
CSS_PROP_NO_OFFSET,
|
||||||
eStyleAnimType_None)
|
eStyleAnimType_None)
|
||||||
CSS_PROP_BACKGROUND(
|
|
||||||
-moz-background-inline-policy,
|
|
||||||
_moz_background_inline_policy,
|
|
||||||
CSS_PROP_DOMPROP_PREFIXED(BackgroundInlinePolicy),
|
|
||||||
CSS_PROPERTY_PARSE_VALUE |
|
|
||||||
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
|
|
||||||
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
|
|
||||||
"",
|
|
||||||
VARIANT_HK,
|
|
||||||
kBackgroundInlinePolicyKTable,
|
|
||||||
CSS_PROP_NO_OFFSET,
|
|
||||||
eStyleAnimType_None)
|
|
||||||
CSS_PROP_BACKGROUND(
|
CSS_PROP_BACKGROUND(
|
||||||
background-blend-mode,
|
background-blend-mode,
|
||||||
background_blend_mode,
|
background_blend_mode,
|
||||||
|
@ -1365,6 +1349,16 @@ CSS_PROP_POSITION(
|
||||||
nullptr,
|
nullptr,
|
||||||
offsetof(nsStylePosition, mOffset),
|
offsetof(nsStylePosition, mOffset),
|
||||||
eStyleAnimType_Sides_Bottom)
|
eStyleAnimType_Sides_Bottom)
|
||||||
|
CSS_PROP_BORDER(
|
||||||
|
box-decoration-break,
|
||||||
|
box_decoration_break,
|
||||||
|
BoxDecorationBreak,
|
||||||
|
CSS_PROPERTY_PARSE_VALUE,
|
||||||
|
"layout.css.box-decoration-break.enabled",
|
||||||
|
VARIANT_HK,
|
||||||
|
kBoxDecorationBreakKTable,
|
||||||
|
CSS_PROP_NO_OFFSET,
|
||||||
|
eStyleAnimType_None)
|
||||||
CSS_PROP_BORDER(
|
CSS_PROP_BORDER(
|
||||||
box-shadow,
|
box-shadow,
|
||||||
box_shadow,
|
box_shadow,
|
||||||
|
|
|
@ -676,13 +676,6 @@ const KTableValue nsCSSProps::kBackgroundAttachmentKTable[] = {
|
||||||
eCSSKeyword_UNKNOWN,-1
|
eCSSKeyword_UNKNOWN,-1
|
||||||
};
|
};
|
||||||
|
|
||||||
const KTableValue nsCSSProps::kBackgroundInlinePolicyKTable[] = {
|
|
||||||
eCSSKeyword_each_box, NS_STYLE_BG_INLINE_POLICY_EACH_BOX,
|
|
||||||
eCSSKeyword_continuous, NS_STYLE_BG_INLINE_POLICY_CONTINUOUS,
|
|
||||||
eCSSKeyword_bounding_box, NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX,
|
|
||||||
eCSSKeyword_UNKNOWN,-1
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(NS_STYLE_BG_CLIP_BORDER == NS_STYLE_BG_ORIGIN_BORDER &&
|
static_assert(NS_STYLE_BG_CLIP_BORDER == NS_STYLE_BG_ORIGIN_BORDER &&
|
||||||
NS_STYLE_BG_CLIP_PADDING == NS_STYLE_BG_ORIGIN_PADDING &&
|
NS_STYLE_BG_CLIP_PADDING == NS_STYLE_BG_ORIGIN_PADDING &&
|
||||||
NS_STYLE_BG_CLIP_CONTENT == NS_STYLE_BG_ORIGIN_CONTENT,
|
NS_STYLE_BG_CLIP_CONTENT == NS_STYLE_BG_ORIGIN_CONTENT,
|
||||||
|
@ -796,6 +789,12 @@ const KTableValue nsCSSProps::kBoxPropSourceKTable[] = {
|
||||||
eCSSKeyword_UNKNOWN,-1
|
eCSSKeyword_UNKNOWN,-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const KTableValue nsCSSProps::kBoxDecorationBreakKTable[] = {
|
||||||
|
eCSSKeyword_slice, NS_STYLE_BOX_DECORATION_BREAK_SLICE,
|
||||||
|
eCSSKeyword_clone, NS_STYLE_BOX_DECORATION_BREAK_CLONE,
|
||||||
|
eCSSKeyword_UNKNOWN,-1
|
||||||
|
};
|
||||||
|
|
||||||
const KTableValue nsCSSProps::kBoxShadowTypeKTable[] = {
|
const KTableValue nsCSSProps::kBoxShadowTypeKTable[] = {
|
||||||
eCSSKeyword_inset, NS_STYLE_BOX_SHADOW_INSET,
|
eCSSKeyword_inset, NS_STYLE_BOX_SHADOW_INSET,
|
||||||
eCSSKeyword_UNKNOWN,-1
|
eCSSKeyword_UNKNOWN,-1
|
||||||
|
|
|
@ -506,7 +506,6 @@ public:
|
||||||
static const KTableValue kBackfaceVisibilityKTable[];
|
static const KTableValue kBackfaceVisibilityKTable[];
|
||||||
static const KTableValue kTransformStyleKTable[];
|
static const KTableValue kTransformStyleKTable[];
|
||||||
static const KTableValue kBackgroundAttachmentKTable[];
|
static const KTableValue kBackgroundAttachmentKTable[];
|
||||||
static const KTableValue kBackgroundInlinePolicyKTable[];
|
|
||||||
static const KTableValue kBackgroundOriginKTable[];
|
static const KTableValue kBackgroundOriginKTable[];
|
||||||
static const KTableValue kBackgroundPositionKTable[];
|
static const KTableValue kBackgroundPositionKTable[];
|
||||||
static const KTableValue kBackgroundRepeatKTable[];
|
static const KTableValue kBackgroundRepeatKTable[];
|
||||||
|
@ -520,6 +519,7 @@ public:
|
||||||
static const KTableValue kBorderStyleKTable[];
|
static const KTableValue kBorderStyleKTable[];
|
||||||
static const KTableValue kBorderWidthKTable[];
|
static const KTableValue kBorderWidthKTable[];
|
||||||
static const KTableValue kBoxAlignKTable[];
|
static const KTableValue kBoxAlignKTable[];
|
||||||
|
static const KTableValue kBoxDecorationBreakKTable[];
|
||||||
static const KTableValue kBoxDirectionKTable[];
|
static const KTableValue kBoxDirectionKTable[];
|
||||||
static const KTableValue kBoxOrientKTable[];
|
static const KTableValue kBoxOrientKTable[];
|
||||||
static const KTableValue kBoxPackKTable[];
|
static const KTableValue kBoxPackKTable[];
|
||||||
|
|
|
@ -2073,16 +2073,6 @@ nsComputedDOMStyle::DoGetBackgroundImage()
|
||||||
return valueList;
|
return valueList;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSSValue*
|
|
||||||
nsComputedDOMStyle::DoGetBackgroundInlinePolicy()
|
|
||||||
{
|
|
||||||
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
|
|
||||||
val->SetIdent(nsCSSProps::ValueToKeywordEnum(
|
|
||||||
StyleBackground()->mBackgroundInlinePolicy,
|
|
||||||
nsCSSProps::kBackgroundInlinePolicyKTable));
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSSValue*
|
CSSValue*
|
||||||
nsComputedDOMStyle::DoGetBackgroundBlendMode()
|
nsComputedDOMStyle::DoGetBackgroundBlendMode()
|
||||||
{
|
{
|
||||||
|
@ -2980,6 +2970,16 @@ nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
|
||||||
return valueList;
|
return valueList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSSValue*
|
||||||
|
nsComputedDOMStyle::DoGetBoxDecorationBreak()
|
||||||
|
{
|
||||||
|
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||||
|
val->SetIdent(
|
||||||
|
nsCSSProps::ValueToKeywordEnum(StyleBorder()->mBoxDecorationBreak,
|
||||||
|
nsCSSProps::kBoxDecorationBreakKTable));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
CSSValue*
|
CSSValue*
|
||||||
nsComputedDOMStyle::DoGetBoxShadow()
|
nsComputedDOMStyle::DoGetBoxShadow()
|
||||||
{
|
{
|
||||||
|
|
|
@ -222,6 +222,7 @@ private:
|
||||||
|
|
||||||
/* Box properties */
|
/* Box properties */
|
||||||
mozilla::dom::CSSValue* DoGetBoxAlign();
|
mozilla::dom::CSSValue* DoGetBoxAlign();
|
||||||
|
mozilla::dom::CSSValue* DoGetBoxDecorationBreak();
|
||||||
mozilla::dom::CSSValue* DoGetBoxDirection();
|
mozilla::dom::CSSValue* DoGetBoxDirection();
|
||||||
mozilla::dom::CSSValue* DoGetBoxFlex();
|
mozilla::dom::CSSValue* DoGetBoxFlex();
|
||||||
mozilla::dom::CSSValue* DoGetBoxOrdinalGroup();
|
mozilla::dom::CSSValue* DoGetBoxOrdinalGroup();
|
||||||
|
@ -283,7 +284,6 @@ private:
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundPosition();
|
mozilla::dom::CSSValue* DoGetBackgroundPosition();
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundRepeat();
|
mozilla::dom::CSSValue* DoGetBackgroundRepeat();
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundClip();
|
mozilla::dom::CSSValue* DoGetBackgroundClip();
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundInlinePolicy();
|
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundBlendMode();
|
mozilla::dom::CSSValue* DoGetBackgroundBlendMode();
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundOrigin();
|
mozilla::dom::CSSValue* DoGetBackgroundOrigin();
|
||||||
mozilla::dom::CSSValue* DoGetBackgroundSize();
|
mozilla::dom::CSSValue* DoGetBackgroundSize();
|
||||||
|
|
|
@ -230,7 +230,6 @@ COMPUTED_STYLE_PROP(z_index, ZIndex)
|
||||||
\* ******************************* */
|
\* ******************************* */
|
||||||
|
|
||||||
COMPUTED_STYLE_PROP(appearance, Appearance)
|
COMPUTED_STYLE_PROP(appearance, Appearance)
|
||||||
COMPUTED_STYLE_PROP(_moz_background_inline_policy, BackgroundInlinePolicy)
|
|
||||||
COMPUTED_STYLE_PROP(binding, Binding)
|
COMPUTED_STYLE_PROP(binding, Binding)
|
||||||
COMPUTED_STYLE_PROP(border_bottom_colors, BorderBottomColors)
|
COMPUTED_STYLE_PROP(border_bottom_colors, BorderBottomColors)
|
||||||
COMPUTED_STYLE_PROP(border_left_colors, BorderLeftColors)
|
COMPUTED_STYLE_PROP(border_left_colors, BorderLeftColors)
|
||||||
|
|
|
@ -6239,14 +6239,6 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
|
||||||
uint8_t(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount,
|
uint8_t(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount,
|
||||||
bg->mClipCount, maxItemCount, rebuild, canStoreInRuleTree);
|
bg->mClipCount, maxItemCount, rebuild, canStoreInRuleTree);
|
||||||
|
|
||||||
// background-inline-policy: enum, inherit, initial
|
|
||||||
SetDiscrete(*aRuleData->ValueForBackgroundInlinePolicy(),
|
|
||||||
bg->mBackgroundInlinePolicy,
|
|
||||||
canStoreInRuleTree,
|
|
||||||
SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
|
|
||||||
parentBG->mBackgroundInlinePolicy,
|
|
||||||
NS_STYLE_BG_INLINE_POLICY_CONTINUOUS, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
// background-blend-mode: enum, inherit, initial [list]
|
// background-blend-mode: enum, inherit, initial [list]
|
||||||
SetBackgroundList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
|
SetBackgroundList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
|
||||||
bg->mLayers,
|
bg->mLayers,
|
||||||
|
@ -6445,6 +6437,13 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
|
||||||
{
|
{
|
||||||
COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder)
|
COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder)
|
||||||
|
|
||||||
|
// box-decoration-break: enum, inherit, initial
|
||||||
|
SetDiscrete(*aRuleData->ValueForBoxDecorationBreak(),
|
||||||
|
border->mBoxDecorationBreak, canStoreInRuleTree,
|
||||||
|
SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
|
||||||
|
parentBorder->mBoxDecorationBreak,
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE, 0, 0, 0, 0);
|
||||||
|
|
||||||
// box-shadow: none, list, inherit, initial
|
// box-shadow: none, list, inherit, initial
|
||||||
const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow();
|
const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow();
|
||||||
switch (boxShadowValue->GetUnit()) {
|
switch (boxShadowValue->GetUnit()) {
|
||||||
|
|
|
@ -117,6 +117,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
||||||
#define NS_STYLE_BOX_PACK_END 2
|
#define NS_STYLE_BOX_PACK_END 2
|
||||||
#define NS_STYLE_BOX_PACK_JUSTIFY 3
|
#define NS_STYLE_BOX_PACK_JUSTIFY 3
|
||||||
|
|
||||||
|
// box-decoration-break
|
||||||
|
#define NS_STYLE_BOX_DECORATION_BREAK_SLICE 0
|
||||||
|
#define NS_STYLE_BOX_DECORATION_BREAK_CLONE 1
|
||||||
|
|
||||||
// box-direction
|
// box-direction
|
||||||
#define NS_STYLE_BOX_DIRECTION_NORMAL 0
|
#define NS_STYLE_BOX_DIRECTION_NORMAL 0
|
||||||
#define NS_STYLE_BOX_DIRECTION_REVERSE 1
|
#define NS_STYLE_BOX_DIRECTION_REVERSE 1
|
||||||
|
|
|
@ -388,6 +388,7 @@ nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
|
||||||
mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
|
mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
|
||||||
mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
|
mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
|
||||||
mFloatEdge(NS_STYLE_FLOAT_EDGE_CONTENT),
|
mFloatEdge(NS_STYLE_FLOAT_EDGE_CONTENT),
|
||||||
|
mBoxDecorationBreak(NS_STYLE_BOX_DECORATION_BREAK_SLICE),
|
||||||
mComputedBorder(0, 0, 0, 0)
|
mComputedBorder(0, 0, 0, 0)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsStyleBorder);
|
MOZ_COUNT_CTOR(nsStyleBorder);
|
||||||
|
@ -439,6 +440,7 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
|
||||||
mBorderImageRepeatH(aSrc.mBorderImageRepeatH),
|
mBorderImageRepeatH(aSrc.mBorderImageRepeatH),
|
||||||
mBorderImageRepeatV(aSrc.mBorderImageRepeatV),
|
mBorderImageRepeatV(aSrc.mBorderImageRepeatV),
|
||||||
mFloatEdge(aSrc.mFloatEdge),
|
mFloatEdge(aSrc.mFloatEdge),
|
||||||
|
mBoxDecorationBreak(aSrc.mBoxDecorationBreak),
|
||||||
mComputedBorder(aSrc.mComputedBorder),
|
mComputedBorder(aSrc.mComputedBorder),
|
||||||
mBorder(aSrc.mBorder),
|
mBorder(aSrc.mBorder),
|
||||||
mTwipsPerPixel(aSrc.mTwipsPerPixel)
|
mTwipsPerPixel(aSrc.mTwipsPerPixel)
|
||||||
|
@ -528,7 +530,8 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
|
||||||
GetComputedBorder() != aOther.GetComputedBorder() ||
|
GetComputedBorder() != aOther.GetComputedBorder() ||
|
||||||
mFloatEdge != aOther.mFloatEdge ||
|
mFloatEdge != aOther.mFloatEdge ||
|
||||||
mBorderImageOutset != aOther.mBorderImageOutset ||
|
mBorderImageOutset != aOther.mBorderImageOutset ||
|
||||||
(shadowDifference & nsChangeHint_NeedReflow))
|
(shadowDifference & nsChangeHint_NeedReflow) ||
|
||||||
|
mBoxDecorationBreak != aOther.mBoxDecorationBreak)
|
||||||
return NS_STYLE_HINT_REFLOW;
|
return NS_STYLE_HINT_REFLOW;
|
||||||
|
|
||||||
NS_FOR_CSS_SIDES(ix) {
|
NS_FOR_CSS_SIDES(ix) {
|
||||||
|
@ -1968,7 +1971,6 @@ nsStyleBackground::nsStyleBackground()
|
||||||
, mSizeCount(1)
|
, mSizeCount(1)
|
||||||
, mBlendModeCount(1)
|
, mBlendModeCount(1)
|
||||||
, mBackgroundColor(NS_RGBA(0, 0, 0, 0))
|
, mBackgroundColor(NS_RGBA(0, 0, 0, 0))
|
||||||
, mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS)
|
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsStyleBackground);
|
MOZ_COUNT_CTOR(nsStyleBackground);
|
||||||
Layer *onlyLayer = mLayers.AppendElement();
|
Layer *onlyLayer = mLayers.AppendElement();
|
||||||
|
@ -1987,7 +1989,6 @@ nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
|
||||||
, mBlendModeCount(aSource.mBlendModeCount)
|
, mBlendModeCount(aSource.mBlendModeCount)
|
||||||
, mLayers(aSource.mLayers) // deep copy
|
, mLayers(aSource.mLayers) // deep copy
|
||||||
, mBackgroundColor(aSource.mBackgroundColor)
|
, mBackgroundColor(aSource.mBackgroundColor)
|
||||||
, mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy)
|
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsStyleBackground);
|
MOZ_COUNT_CTOR(nsStyleBackground);
|
||||||
// If the deep copy of mLayers failed, truncate the counts.
|
// If the deep copy of mLayers failed, truncate the counts.
|
||||||
|
@ -2045,9 +2046,7 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasVisualDifference ||
|
if (hasVisualDifference || mBackgroundColor != aOther.mBackgroundColor)
|
||||||
mBackgroundColor != aOther.mBackgroundColor ||
|
|
||||||
mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy)
|
|
||||||
return NS_STYLE_HINT_VISUAL;
|
return NS_STYLE_HINT_VISUAL;
|
||||||
|
|
||||||
return NS_STYLE_HINT_NONE;
|
return NS_STYLE_HINT_NONE;
|
||||||
|
|
|
@ -539,11 +539,6 @@ struct nsStyleBackground {
|
||||||
|
|
||||||
nscolor mBackgroundColor; // [reset]
|
nscolor mBackgroundColor; // [reset]
|
||||||
|
|
||||||
// FIXME: This (now background-break in css3-background) should
|
|
||||||
// probably move into a different struct so that everything in
|
|
||||||
// nsStyleBackground is set by the background shorthand.
|
|
||||||
uint8_t mBackgroundInlinePolicy; // [reset] See nsStyleConsts.h
|
|
||||||
|
|
||||||
// True if this background is completely transparent.
|
// True if this background is completely transparent.
|
||||||
bool IsTransparent() const;
|
bool IsTransparent() const;
|
||||||
|
|
||||||
|
@ -986,6 +981,7 @@ public:
|
||||||
uint8_t mBorderImageRepeatH; // [reset] see nsStyleConsts.h
|
uint8_t mBorderImageRepeatH; // [reset] see nsStyleConsts.h
|
||||||
uint8_t mBorderImageRepeatV; // [reset]
|
uint8_t mBorderImageRepeatV; // [reset]
|
||||||
uint8_t mFloatEdge; // [reset]
|
uint8_t mFloatEdge; // [reset]
|
||||||
|
uint8_t mBoxDecorationBreak; // [reset] see nsStyleConsts.h
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// mComputedBorder holds the CSS2.1 computed border-width values.
|
// mComputedBorder holds the CSS2.1 computed border-width values.
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -139,10 +139,6 @@ isnot(e.style.background, "", "should have background shorthand (size:100% auto)
|
||||||
e.setAttribute("style", "background: red; background-size: auto 100%");
|
e.setAttribute("style", "background: red; background-size: auto 100%");
|
||||||
isnot(e.style.background, "", "should have background shorthand (size:auto 100%)");
|
isnot(e.style.background, "", "should have background shorthand (size:auto 100%)");
|
||||||
|
|
||||||
// Test background-inline-policy not interacting with the background shorthand.
|
|
||||||
e.setAttribute("style", "background: red; -moz-background-inline-policy: each-box");
|
|
||||||
isnot(e.style.background, "", "should have background shorthand (-moz-background-inline-policy not relevant)");
|
|
||||||
|
|
||||||
// Check that we only serialize background when the lists (of layers) for
|
// Check that we only serialize background when the lists (of layers) for
|
||||||
// the subproperties are the same length.
|
// the subproperties are the same length.
|
||||||
e.setAttribute("style", "background-clip: border-box, padding-box, border-box; background-origin: border-box, padding-box, padding-box; background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
|
e.setAttribute("style", "background-clip: border-box, padding-box, border-box; background-origin: border-box, padding-box, padding-box; background-size: cover, auto, contain; background-color: blue; background-image: url(404.png), none, url(404-2.png); background-attachment: fixed, scroll, scroll; background-position: top left, center, 30px 50px; background-repeat: repeat-x, repeat, no-repeat");
|
||||||
|
|
|
@ -550,6 +550,11 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
int
|
int
|
||||||
nsTableCellFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableCellFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
@ -1103,7 +1108,10 @@ nsBCTableCellFrame::GetUsedBorder() const
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ bool
|
/* virtual */ bool
|
||||||
nsBCTableCellFrame::GetBorderRadii(nscoord aRadii[8]) const
|
nsBCTableCellFrame::GetBorderRadii(const nsSize& aFrameSize,
|
||||||
|
const nsSize& aBorderArea,
|
||||||
|
int aSkipSides,
|
||||||
|
nscoord aRadii[8]) const
|
||||||
{
|
{
|
||||||
NS_FOR_CSS_HALF_CORNERS(corner) {
|
NS_FOR_CSS_HALF_CORNERS(corner) {
|
||||||
aRadii[corner] = 0;
|
aRadii[corner] = 0;
|
||||||
|
|
|
@ -298,7 +298,10 @@ public:
|
||||||
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE;
|
virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE;
|
||||||
virtual bool GetBorderRadii(nscoord aRadii[8]) const MOZ_OVERRIDE;
|
virtual bool GetBorderRadii(const nsSize& aFrameSize,
|
||||||
|
const nsSize& aBorderArea,
|
||||||
|
int aSkipSides,
|
||||||
|
nscoord aRadii[8]) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
// Get the *inner half of the border only*, in twips.
|
// Get the *inner half of the border only*, in twips.
|
||||||
virtual nsMargin* GetBorderWidth(nsMargin& aBorder) const MOZ_OVERRIDE;
|
virtual nsMargin* GetBorderWidth(nsMargin& aBorder) const MOZ_OVERRIDE;
|
||||||
|
|
|
@ -343,6 +343,11 @@ nsTableColGroupFrame::RemoveFrame(ChildListID aListID,
|
||||||
int
|
int
|
||||||
nsTableColGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableColGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= 1 << LOGICAL_SIDE_B_START;
|
skip |= 1 << LOGICAL_SIDE_B_START;
|
||||||
|
|
|
@ -1409,6 +1409,11 @@ nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
|
||||||
int
|
int
|
||||||
nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
// frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto
|
// frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto
|
||||||
// account for pagination
|
// account for pagination
|
||||||
|
|
|
@ -605,6 +605,11 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
int
|
int
|
||||||
nsTableRowFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableRowFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
|
|
@ -256,6 +256,11 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
int
|
int
|
||||||
nsTableRowGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableRowGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
|
|
@ -1900,6 +1900,9 @@ pref("layout.css.variables.enabled", true);
|
||||||
// Is support for CSS overflow-clip-box enabled for non-UA sheets?
|
// Is support for CSS overflow-clip-box enabled for non-UA sheets?
|
||||||
pref("layout.css.overflow-clip-box.enabled", false);
|
pref("layout.css.overflow-clip-box.enabled", false);
|
||||||
|
|
||||||
|
// Is support for CSS box-decoration-break enabled?
|
||||||
|
pref("layout.css.box-decoration-break.enabled", false);
|
||||||
|
|
||||||
// pref for which side vertical scrollbars should be on
|
// pref for which side vertical scrollbars should be on
|
||||||
// 0 = end-side in UI direction
|
// 0 = end-side in UI direction
|
||||||
// 1 = end-side in document/content direction
|
// 1 = end-side in document/content direction
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче