mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c
This commit is contained in:
commit
b2af114078
@ -62,8 +62,9 @@ let gGestureSupport = {
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "MozSwipeGestureStart":
|
||||
aEvent.preventDefault();
|
||||
this._setupSwipeGesture(aEvent);
|
||||
if (this._setupSwipeGesture(aEvent)) {
|
||||
aEvent.preventDefault();
|
||||
}
|
||||
break;
|
||||
case "MozSwipeGestureUpdate":
|
||||
aEvent.preventDefault();
|
||||
@ -179,23 +180,43 @@ let gGestureSupport = {
|
||||
*
|
||||
* @param aEvent
|
||||
* The swipe gesture start event.
|
||||
* @return true if swipe gestures could successfully be set up, false
|
||||
* othwerwise.
|
||||
*/
|
||||
_setupSwipeGesture: function GS__setupSwipeGesture(aEvent) {
|
||||
if (!this._swipeNavigatesHistory(aEvent))
|
||||
return;
|
||||
if (!this._swipeNavigatesHistory(aEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let isVerticalSwipe = false;
|
||||
if (gHistorySwipeAnimation.active) {
|
||||
if (aEvent.direction == aEvent.DIRECTION_UP) {
|
||||
if (content.pageYOffset > 0) {
|
||||
return false;
|
||||
}
|
||||
isVerticalSwipe = true;
|
||||
} else if (aEvent.direction == aEvent.DIRECTION_DOWN) {
|
||||
if (content.pageYOffset < content.scrollMaxY) {
|
||||
return false;
|
||||
}
|
||||
isVerticalSwipe = true;
|
||||
}
|
||||
}
|
||||
|
||||
let canGoBack = gHistorySwipeAnimation.canGoBack();
|
||||
let canGoForward = gHistorySwipeAnimation.canGoForward();
|
||||
let isLTR = gHistorySwipeAnimation.isLTR;
|
||||
|
||||
if (canGoBack)
|
||||
if (canGoBack) {
|
||||
aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_LEFT :
|
||||
aEvent.DIRECTION_RIGHT;
|
||||
if (canGoForward)
|
||||
}
|
||||
if (canGoForward) {
|
||||
aEvent.allowedDirections |= isLTR ? aEvent.DIRECTION_RIGHT :
|
||||
aEvent.DIRECTION_LEFT;
|
||||
}
|
||||
|
||||
gHistorySwipeAnimation.startAnimation();
|
||||
gHistorySwipeAnimation.startAnimation(isVerticalSwipe);
|
||||
|
||||
this._doUpdate = function GS__doUpdate(aEvent) {
|
||||
gHistorySwipeAnimation.updateAnimation(aEvent.delta);
|
||||
@ -207,6 +228,8 @@ let gGestureSupport = {
|
||||
this._doUpdate = function (aEvent) {};
|
||||
this._doEnd = function (aEvent) {};
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -552,8 +575,10 @@ let gHistorySwipeAnimation = {
|
||||
this._startingIndex = -1;
|
||||
this._historyIndex = -1;
|
||||
this._boxWidth = -1;
|
||||
this._boxHeight = -1;
|
||||
this._maxSnapshots = this._getMaxSnapshots();
|
||||
this._lastSwipeDir = "";
|
||||
this._direction = "horizontal";
|
||||
|
||||
// We only want to activate history swipe animations if we store snapshots.
|
||||
// If we don't store any, we handle horizontal swipes without animations.
|
||||
@ -584,14 +609,28 @@ let gHistorySwipeAnimation = {
|
||||
/**
|
||||
* Starts the swipe animation and handles fast swiping (i.e. a swipe animation
|
||||
* is already in progress when a new one is initiated).
|
||||
*
|
||||
* @param aIsVerticalSwipe
|
||||
* Whether we're dealing with a vertical swipe or not.
|
||||
*/
|
||||
startAnimation: function HSA_startAnimation() {
|
||||
startAnimation: function HSA_startAnimation(aIsVerticalSwipe) {
|
||||
this._direction = aIsVerticalSwipe ? "vertical" : "horizontal";
|
||||
|
||||
if (this.isAnimationRunning()) {
|
||||
gBrowser.stop();
|
||||
this._lastSwipeDir = "RELOAD"; // just ensure that != ""
|
||||
this._canGoBack = this.canGoBack();
|
||||
this._canGoForward = this.canGoForward();
|
||||
this._handleFastSwiping();
|
||||
// If this is a horizontal scroll, or if this is a vertical scroll that
|
||||
// was started while a horizontal scroll was still running, handle it as
|
||||
// as a fast swipe. In the case of the latter scenario, this allows us to
|
||||
// start the vertical animation without first loading the final page, or
|
||||
// taking another snapshot. If vertical scrolls are initiated repeatedly
|
||||
// without prior horizontal scroll we skip this and restart the animation
|
||||
// from 0.
|
||||
if (this._direction == "horizontal" || this._lastSwipeDir != "") {
|
||||
gBrowser.stop();
|
||||
this._lastSwipeDir = "RELOAD"; // just ensure that != ""
|
||||
this._canGoBack = this.canGoBack();
|
||||
this._canGoForward = this.canGoForward();
|
||||
this._handleFastSwiping();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._startingIndex = gBrowser.webNavigation.sessionHistory.index;
|
||||
@ -623,19 +662,24 @@ let gHistorySwipeAnimation = {
|
||||
* swipe gesture.
|
||||
*/
|
||||
updateAnimation: function HSA_updateAnimation(aVal) {
|
||||
if (!this.isAnimationRunning())
|
||||
if (!this.isAnimationRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We use the following value to decrease the bounce effect when swiping
|
||||
// back/forward past the browsing history. This value was determined
|
||||
// experimentally.
|
||||
// We use the following value to decrease the bounce effect when scrolling
|
||||
// to the top or bottom of the page, or when swiping back/forward past the
|
||||
// browsing history. This value was determined experimentally.
|
||||
let dampValue = 4;
|
||||
if ((aVal >= 0 && this.isLTR) ||
|
||||
(aVal <= 0 && !this.isLTR)) {
|
||||
if (this._direction == "vertical") {
|
||||
this._prevBox.collapsed = true;
|
||||
this._nextBox.collapsed = true;
|
||||
this._positionBox(this._curBox, -1 * aVal / dampValue);
|
||||
} else if ((aVal >= 0 && this.isLTR) ||
|
||||
(aVal <= 0 && !this.isLTR)) {
|
||||
let tempDampValue = 1;
|
||||
if (this._canGoBack)
|
||||
if (this._canGoBack) {
|
||||
this._prevBox.collapsed = false;
|
||||
else {
|
||||
} else {
|
||||
tempDampValue = dampValue;
|
||||
this._prevBox.collapsed = true;
|
||||
}
|
||||
@ -647,11 +691,7 @@ let gHistorySwipeAnimation = {
|
||||
|
||||
// The forward page should be pushed offscreen all the way to the right.
|
||||
this._positionBox(this._nextBox, 1);
|
||||
}
|
||||
else {
|
||||
if (aVal < -1)
|
||||
aVal = -1; // Cap value to avoid sliding the page further than allowed.
|
||||
|
||||
} else {
|
||||
// The intention is to go forward. If there is a page to go forward to,
|
||||
// it should slide in from the right (LTR) or left (RTL).
|
||||
// Otherwise, the current page should slide to the left (LTR) or
|
||||
@ -663,8 +703,7 @@ let gHistorySwipeAnimation = {
|
||||
let offset = this.isLTR ? 1 : -1;
|
||||
this._positionBox(this._curBox, 0);
|
||||
this._positionBox(this._nextBox, offset + aVal);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this._prevBox.collapsed = true;
|
||||
this._positionBox(this._curBox, aVal / dampValue);
|
||||
}
|
||||
@ -835,7 +874,9 @@ let gHistorySwipeAnimation = {
|
||||
"box");
|
||||
this._container.appendChild(this._nextBox);
|
||||
|
||||
this._boxWidth = this._curBox.getBoundingClientRect().width; // cache width
|
||||
// Cache width and height.
|
||||
this._boxWidth = this._curBox.getBoundingClientRect().width;
|
||||
this._boxHeight = this._curBox.getBoundingClientRect().height;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -849,6 +890,7 @@ let gHistorySwipeAnimation = {
|
||||
this._container.parentNode.removeChild(this._container);
|
||||
this._container = null;
|
||||
this._boxWidth = -1;
|
||||
this._boxHeight = -1;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -876,7 +918,14 @@ let gHistorySwipeAnimation = {
|
||||
* The position (in X coordinates) to move the box element to.
|
||||
*/
|
||||
_positionBox: function HSA__positionBox(aBox, aPosition) {
|
||||
aBox.style.transform = "translateX(" + this._boxWidth * aPosition + "px)";
|
||||
let transform = "";
|
||||
|
||||
if (this._direction == "vertical")
|
||||
transform = "translateY(" + this._boxHeight * aPosition + "px)";
|
||||
else
|
||||
transform = "translateX(" + this._boxWidth * aPosition + "px)";
|
||||
|
||||
aBox.style.transform = transform;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -108,6 +108,11 @@ CATEGORIES = {
|
||||
'short': 'Potpourri',
|
||||
'long': 'Potent potables and assorted snacks.',
|
||||
'priority': 10,
|
||||
},
|
||||
'disabled': {
|
||||
'short': 'Disabled',
|
||||
'long': 'These commands are unavailable for your current context, run "mach <command>" to see why.',
|
||||
'priority': 0,
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,8 +172,9 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
||||
|
||||
def populate_context(context):
|
||||
context.state_dir = state_dir
|
||||
context.topdir = topsrcdir
|
||||
|
||||
mach = mach.main.Mach(topsrcdir)
|
||||
mach = mach.main.Mach(os.getcwd())
|
||||
mach.populate_context_handler = populate_context
|
||||
|
||||
for category, meta in CATEGORIES.items():
|
||||
|
@ -1,489 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
'''jarmaker.py provides a python class to package up chrome content by
|
||||
processing jar.mn files.
|
||||
|
||||
See the documentation for jar.mn on MDC for further details on the format.
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import errno
|
||||
import re
|
||||
import logging
|
||||
from time import localtime
|
||||
from MozZipFile import ZipFile
|
||||
from cStringIO import StringIO
|
||||
|
||||
from mozbuild.util import (
|
||||
lock_file,
|
||||
PushbackIter,
|
||||
)
|
||||
|
||||
from Preprocessor import Preprocessor
|
||||
from mozbuild.action.buildlist import addEntriesToListFile
|
||||
if sys.platform == "win32":
|
||||
from ctypes import windll, WinError
|
||||
CreateHardLink = windll.kernel32.CreateHardLinkA
|
||||
|
||||
__all__ = ['JarMaker']
|
||||
|
||||
class ZipEntry:
|
||||
'''Helper class for jar output.
|
||||
|
||||
This class defines a simple file-like object for a zipfile.ZipEntry
|
||||
so that we can consecutively write to it and then close it.
|
||||
This methods hooks into ZipFile.writestr on close().
|
||||
'''
|
||||
def __init__(self, name, zipfile):
|
||||
self._zipfile = zipfile
|
||||
self._name = name
|
||||
self._inner = StringIO()
|
||||
|
||||
def write(self, content):
|
||||
'Append the given content to this zip entry'
|
||||
self._inner.write(content)
|
||||
return
|
||||
|
||||
def close(self):
|
||||
'The close method writes the content back to the zip file.'
|
||||
self._zipfile.writestr(self._name, self._inner.getvalue())
|
||||
|
||||
def getModTime(aPath):
|
||||
if not os.path.isfile(aPath):
|
||||
return 0
|
||||
mtime = os.stat(aPath).st_mtime
|
||||
return localtime(mtime)
|
||||
|
||||
|
||||
class JarMaker(object):
|
||||
'''JarMaker reads jar.mn files and process those into jar files or
|
||||
flat directories, along with chrome.manifest files.
|
||||
'''
|
||||
|
||||
ignore = re.compile('\s*(\#.*)?$')
|
||||
jarline = re.compile('(?:(?P<jarfile>[\w\d.\-\_\\\/]+).jar\:)|(?:\s*(\#.*)?)\s*$')
|
||||
relsrcline = re.compile('relativesrcdir\s+(?P<relativesrcdir>.+?):')
|
||||
regline = re.compile('\%\s+(.*)$')
|
||||
entryre = '(?P<optPreprocess>\*)?(?P<optOverwrite>\+?)\s+'
|
||||
entryline = re.compile(entryre + '(?P<output>[\w\d.\-\_\\\/\+\@]+)\s*(\((?P<locale>\%?)(?P<source>[\w\d.\-\_\\\/\@]+)\))?\s*$')
|
||||
|
||||
def __init__(self, outputFormat = 'flat', useJarfileManifest = True,
|
||||
useChromeManifest = False):
|
||||
self.outputFormat = outputFormat
|
||||
self.useJarfileManifest = useJarfileManifest
|
||||
self.useChromeManifest = useChromeManifest
|
||||
self.pp = Preprocessor()
|
||||
self.topsourcedir = None
|
||||
self.sourcedirs = []
|
||||
self.localedirs = None
|
||||
self.l10nbase = None
|
||||
self.l10nmerge = None
|
||||
self.relativesrcdir = None
|
||||
self.rootManifestAppId = None
|
||||
|
||||
def getCommandLineParser(self):
|
||||
'''Get a optparse.OptionParser for jarmaker.
|
||||
|
||||
This OptionParser has the options for jarmaker as well as
|
||||
the options for the inner PreProcessor.
|
||||
'''
|
||||
# HACK, we need to unescape the string variables we get,
|
||||
# the perl versions didn't grok strings right
|
||||
p = self.pp.getCommandLineParser(unescapeDefines = True)
|
||||
p.add_option('-f', type="choice", default="jar",
|
||||
choices=('jar', 'flat', 'symlink'),
|
||||
help="fileformat used for output", metavar="[jar, flat, symlink]")
|
||||
p.add_option('-v', action="store_true", dest="verbose",
|
||||
help="verbose output")
|
||||
p.add_option('-q', action="store_false", dest="verbose",
|
||||
help="verbose output")
|
||||
p.add_option('-e', action="store_true",
|
||||
help="create chrome.manifest instead of jarfile.manifest")
|
||||
p.add_option('--both-manifests', action="store_true",
|
||||
dest="bothManifests",
|
||||
help="create chrome.manifest and jarfile.manifest")
|
||||
p.add_option('-s', type="string", action="append", default=[],
|
||||
help="source directory")
|
||||
p.add_option('-t', type="string",
|
||||
help="top source directory")
|
||||
p.add_option('-c', '--l10n-src', type="string", action="append",
|
||||
help="localization directory")
|
||||
p.add_option('--l10n-base', type="string", action="store",
|
||||
help="base directory to be used for localization (requires relativesrcdir)")
|
||||
p.add_option('--locale-mergedir', type="string", action="store",
|
||||
help="base directory to be used for l10n-merge (requires l10n-base and relativesrcdir)")
|
||||
p.add_option('--relativesrcdir', type="string",
|
||||
help="relativesrcdir to be used for localization")
|
||||
p.add_option('-j', type="string",
|
||||
help="jarfile directory")
|
||||
p.add_option('--root-manifest-entry-appid', type="string",
|
||||
help="add an app id specific root chrome manifest entry.")
|
||||
return p
|
||||
|
||||
def processIncludes(self, includes):
|
||||
'''Process given includes with the inner PreProcessor.
|
||||
|
||||
Only use this for #defines, the includes shouldn't generate
|
||||
content.
|
||||
'''
|
||||
self.pp.out = StringIO()
|
||||
for inc in includes:
|
||||
self.pp.do_include(inc)
|
||||
includesvalue = self.pp.out.getvalue()
|
||||
if includesvalue:
|
||||
logging.info("WARNING: Includes produce non-empty output")
|
||||
self.pp.out = None
|
||||
pass
|
||||
|
||||
def finalizeJar(self, jarPath, chromebasepath, register,
|
||||
doZip=True):
|
||||
'''Helper method to write out the chrome registration entries to
|
||||
jarfile.manifest or chrome.manifest, or both.
|
||||
|
||||
The actual file processing is done in updateManifest.
|
||||
'''
|
||||
# rewrite the manifest, if entries given
|
||||
if not register:
|
||||
return
|
||||
|
||||
chromeManifest = os.path.join(os.path.dirname(jarPath),
|
||||
'..', 'chrome.manifest')
|
||||
|
||||
if self.useJarfileManifest:
|
||||
self.updateManifest(jarPath + '.manifest', chromebasepath.format(''),
|
||||
register)
|
||||
addEntriesToListFile(chromeManifest, ['manifest chrome/{0}.manifest'
|
||||
.format(os.path.basename(jarPath))])
|
||||
if self.useChromeManifest:
|
||||
self.updateManifest(chromeManifest, chromebasepath.format('chrome/'),
|
||||
register)
|
||||
|
||||
# If requested, add a root chrome manifest entry (assumed to be in the parent directory
|
||||
# of chromeManifest) with the application specific id. In cases where we're building
|
||||
# lang packs, the root manifest must know about application sub directories.
|
||||
if self.rootManifestAppId:
|
||||
rootChromeManifest = os.path.join(os.path.normpath(os.path.dirname(chromeManifest)),
|
||||
'..', 'chrome.manifest')
|
||||
rootChromeManifest = os.path.normpath(rootChromeManifest)
|
||||
chromeDir = os.path.basename(os.path.dirname(os.path.normpath(chromeManifest)))
|
||||
logging.info("adding '%s' entry to root chrome manifest appid=%s" % (chromeDir, self.rootManifestAppId))
|
||||
addEntriesToListFile(rootChromeManifest, ['manifest %s/chrome.manifest application=%s' % (chromeDir, self.rootManifestAppId)])
|
||||
|
||||
def updateManifest(self, manifestPath, chromebasepath, register):
|
||||
'''updateManifest replaces the % in the chrome registration entries
|
||||
with the given chrome base path, and updates the given manifest file.
|
||||
'''
|
||||
lock = lock_file(manifestPath + '.lck')
|
||||
try:
|
||||
myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
|
||||
register.iterkeys()))
|
||||
manifestExists = os.path.isfile(manifestPath)
|
||||
mode = (manifestExists and 'r+b') or 'wb'
|
||||
mf = open(manifestPath, mode)
|
||||
if manifestExists:
|
||||
# import previous content into hash, ignoring empty ones and comments
|
||||
imf = re.compile('(#.*)?$')
|
||||
for l in re.split('[\r\n]+', mf.read()):
|
||||
if imf.match(l):
|
||||
continue
|
||||
myregister[l] = None
|
||||
mf.seek(0)
|
||||
for k in myregister.iterkeys():
|
||||
mf.write(k + os.linesep)
|
||||
mf.close()
|
||||
finally:
|
||||
lock = None
|
||||
|
||||
def makeJar(self, infile, jardir):
|
||||
'''makeJar is the main entry point to JarMaker.
|
||||
|
||||
It takes the input file, the output directory, the source dirs and the
|
||||
top source dir as argument, and optionally the l10n dirs.
|
||||
'''
|
||||
# making paths absolute, guess srcdir if file and add to sourcedirs
|
||||
_normpath = lambda p: os.path.normpath(os.path.abspath(p))
|
||||
self.topsourcedir = _normpath(self.topsourcedir)
|
||||
self.sourcedirs = [_normpath(p) for p in self.sourcedirs]
|
||||
if self.localedirs:
|
||||
self.localedirs = [_normpath(p) for p in self.localedirs]
|
||||
elif self.relativesrcdir:
|
||||
self.localedirs = self.generateLocaleDirs(self.relativesrcdir)
|
||||
if isinstance(infile, basestring):
|
||||
logging.info("processing " + infile)
|
||||
self.sourcedirs.append(_normpath(os.path.dirname(infile)))
|
||||
pp = self.pp.clone()
|
||||
pp.out = StringIO()
|
||||
pp.do_include(infile)
|
||||
lines = PushbackIter(pp.out.getvalue().splitlines())
|
||||
try:
|
||||
while True:
|
||||
l = lines.next()
|
||||
m = self.jarline.match(l)
|
||||
if not m:
|
||||
raise RuntimeError(l)
|
||||
if m.group('jarfile') is None:
|
||||
# comment
|
||||
continue
|
||||
self.processJarSection(m.group('jarfile'), lines, jardir)
|
||||
except StopIteration:
|
||||
# we read the file
|
||||
pass
|
||||
return
|
||||
|
||||
def generateLocaleDirs(self, relativesrcdir):
|
||||
if os.path.basename(relativesrcdir) == 'locales':
|
||||
# strip locales
|
||||
l10nrelsrcdir = os.path.dirname(relativesrcdir)
|
||||
else:
|
||||
l10nrelsrcdir = relativesrcdir
|
||||
locdirs = []
|
||||
# generate locales dirs, merge, l10nbase, en-US
|
||||
if self.l10nmerge:
|
||||
locdirs.append(os.path.join(self.l10nmerge, l10nrelsrcdir))
|
||||
if self.l10nbase:
|
||||
locdirs.append(os.path.join(self.l10nbase, l10nrelsrcdir))
|
||||
if self.l10nmerge or not self.l10nbase:
|
||||
# add en-US if we merge, or if it's not l10n
|
||||
locdirs.append(os.path.join(self.topsourcedir, relativesrcdir, 'en-US'))
|
||||
return locdirs
|
||||
|
||||
def processJarSection(self, jarfile, lines, jardir):
|
||||
'''Internal method called by makeJar to actually process a section
|
||||
of a jar.mn file.
|
||||
|
||||
jarfile is the basename of the jarfile or the directory name for
|
||||
flat output, lines is a PushbackIter of the lines of jar.mn,
|
||||
the remaining options are carried over from makeJar.
|
||||
'''
|
||||
|
||||
# chromebasepath is used for chrome registration manifests
|
||||
# {0} is getting replaced with chrome/ for chrome.manifest, and with
|
||||
# an empty string for jarfile.manifest
|
||||
chromebasepath = '{0}' + os.path.basename(jarfile)
|
||||
if self.outputFormat == 'jar':
|
||||
chromebasepath = 'jar:' + chromebasepath + '.jar!'
|
||||
chromebasepath += '/'
|
||||
|
||||
jarfile = os.path.join(jardir, jarfile)
|
||||
jf = None
|
||||
if self.outputFormat == 'jar':
|
||||
#jar
|
||||
jarfilepath = jarfile + '.jar'
|
||||
try:
|
||||
os.makedirs(os.path.dirname(jarfilepath))
|
||||
except OSError as error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
jf = ZipFile(jarfilepath, 'a', lock = True)
|
||||
outHelper = self.OutputHelper_jar(jf)
|
||||
else:
|
||||
outHelper = getattr(self, 'OutputHelper_' + self.outputFormat)(jarfile)
|
||||
register = {}
|
||||
# This loop exits on either
|
||||
# - the end of the jar.mn file
|
||||
# - an line in the jar.mn file that's not part of a jar section
|
||||
# - on an exception raised, close the jf in that case in a finally
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
l = lines.next()
|
||||
except StopIteration:
|
||||
# we're done with this jar.mn, and this jar section
|
||||
self.finalizeJar(jarfile, chromebasepath, register)
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
# reraise the StopIteration for makeJar
|
||||
raise
|
||||
if self.ignore.match(l):
|
||||
continue
|
||||
m = self.relsrcline.match(l)
|
||||
if m:
|
||||
relativesrcdir = m.group('relativesrcdir')
|
||||
self.localedirs = self.generateLocaleDirs(relativesrcdir)
|
||||
continue
|
||||
m = self.regline.match(l)
|
||||
if m:
|
||||
rline = m.group(1)
|
||||
register[rline] = 1
|
||||
continue
|
||||
m = self.entryline.match(l)
|
||||
if not m:
|
||||
# neither an entry line nor chrome reg, this jar section is done
|
||||
self.finalizeJar(jarfile, chromebasepath, register)
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
lines.pushback(l)
|
||||
return
|
||||
self._processEntryLine(m, outHelper, jf)
|
||||
finally:
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
return
|
||||
|
||||
def _processEntryLine(self, m, outHelper, jf):
|
||||
out = m.group('output')
|
||||
src = m.group('source') or os.path.basename(out)
|
||||
# pick the right sourcedir -- l10n, topsrc or src
|
||||
if m.group('locale'):
|
||||
src_base = self.localedirs
|
||||
elif src.startswith('/'):
|
||||
# path/in/jar/file_name.xul (/path/in/sourcetree/file_name.xul)
|
||||
# refers to a path relative to topsourcedir, use that as base
|
||||
# and strip the leading '/'
|
||||
src_base = [self.topsourcedir]
|
||||
src = src[1:]
|
||||
else:
|
||||
# use srcdirs and the objdir (current working dir) for relative paths
|
||||
src_base = self.sourcedirs + [os.getcwd()]
|
||||
# check if the source file exists
|
||||
realsrc = None
|
||||
for _srcdir in src_base:
|
||||
if os.path.isfile(os.path.join(_srcdir, src)):
|
||||
realsrc = os.path.join(_srcdir, src)
|
||||
break
|
||||
if realsrc is None:
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
raise RuntimeError('File "{0}" not found in {1}'
|
||||
.format(src, ', '.join(src_base)))
|
||||
if m.group('optPreprocess'):
|
||||
outf = outHelper.getOutput(out)
|
||||
inf = open(realsrc)
|
||||
pp = self.pp.clone()
|
||||
if src[-4:] == '.css':
|
||||
pp.setMarker('%')
|
||||
pp.out = outf
|
||||
pp.do_include(inf)
|
||||
pp.warnUnused(realsrc)
|
||||
outf.close()
|
||||
inf.close()
|
||||
return
|
||||
# copy or symlink if newer or overwrite
|
||||
if (m.group('optOverwrite')
|
||||
or (getModTime(realsrc) >
|
||||
outHelper.getDestModTime(m.group('output')))):
|
||||
if self.outputFormat == 'symlink':
|
||||
outHelper.symlink(realsrc, out)
|
||||
return
|
||||
outf = outHelper.getOutput(out)
|
||||
# open in binary mode, this can be images etc
|
||||
inf = open(realsrc, 'rb')
|
||||
outf.write(inf.read())
|
||||
outf.close()
|
||||
inf.close()
|
||||
|
||||
|
||||
class OutputHelper_jar(object):
|
||||
'''Provide getDestModTime and getOutput for a given jarfile.
|
||||
'''
|
||||
def __init__(self, jarfile):
|
||||
self.jarfile = jarfile
|
||||
def getDestModTime(self, aPath):
|
||||
try :
|
||||
info = self.jarfile.getinfo(aPath)
|
||||
return info.date_time
|
||||
except:
|
||||
return 0
|
||||
def getOutput(self, name):
|
||||
return ZipEntry(name, self.jarfile)
|
||||
|
||||
class OutputHelper_flat(object):
|
||||
'''Provide getDestModTime and getOutput for a given flat
|
||||
output directory. The helper method ensureDirFor is used by
|
||||
the symlink subclass.
|
||||
'''
|
||||
def __init__(self, basepath):
|
||||
self.basepath = basepath
|
||||
def getDestModTime(self, aPath):
|
||||
return getModTime(os.path.join(self.basepath, aPath))
|
||||
def getOutput(self, name):
|
||||
out = self.ensureDirFor(name)
|
||||
# remove previous link or file
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return open(out, 'wb')
|
||||
def ensureDirFor(self, name):
|
||||
out = os.path.join(self.basepath, name)
|
||||
outdir = os.path.dirname(out)
|
||||
if not os.path.isdir(outdir):
|
||||
try:
|
||||
os.makedirs(outdir)
|
||||
except OSError as error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
return out
|
||||
|
||||
class OutputHelper_symlink(OutputHelper_flat):
|
||||
'''Subclass of OutputHelper_flat that provides a helper for
|
||||
creating a symlink including creating the parent directories.
|
||||
'''
|
||||
def symlink(self, src, dest):
|
||||
out = self.ensureDirFor(dest)
|
||||
# remove previous link or file
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
if sys.platform != "win32":
|
||||
os.symlink(src, out)
|
||||
else:
|
||||
# On Win32, use ctypes to create a hardlink
|
||||
rv = CreateHardLink(out, src, None)
|
||||
if rv == 0:
|
||||
raise WinError()
|
||||
|
||||
def main():
|
||||
jm = JarMaker()
|
||||
p = jm.getCommandLineParser()
|
||||
(options, args) = p.parse_args()
|
||||
jm.processIncludes(options.I)
|
||||
jm.outputFormat = options.f
|
||||
jm.sourcedirs = options.s
|
||||
jm.topsourcedir = options.t
|
||||
if options.e:
|
||||
jm.useChromeManifest = True
|
||||
jm.useJarfileManifest = False
|
||||
if options.bothManifests:
|
||||
jm.useChromeManifest = True
|
||||
jm.useJarfileManifest = True
|
||||
if options.l10n_base:
|
||||
if not options.relativesrcdir:
|
||||
p.error('relativesrcdir required when using l10n-base')
|
||||
if options.l10n_src:
|
||||
p.error('both l10n-src and l10n-base are not supported')
|
||||
jm.l10nbase = options.l10n_base
|
||||
jm.relativesrcdir = options.relativesrcdir
|
||||
jm.l10nmerge = options.locale_mergedir
|
||||
if jm.l10nmerge and not os.path.isdir(jm.l10nmerge):
|
||||
logging.warning("WARNING: --locale-mergedir passed, but '%s' does not "
|
||||
"exist. Ignore this message if the locale is complete.")
|
||||
elif options.locale_mergedir:
|
||||
p.error('l10n-base required when using locale-mergedir')
|
||||
jm.localedirs = options.l10n_src
|
||||
if options.root_manifest_entry_appid:
|
||||
jm.rootManifestAppId = options.root_manifest_entry_appid
|
||||
noise = logging.INFO
|
||||
if options.verbose is not None:
|
||||
noise = (options.verbose and logging.DEBUG) or logging.WARN
|
||||
if sys.version_info[:2] > (2,3):
|
||||
logging.basicConfig(format = "%(message)s")
|
||||
else:
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(noise)
|
||||
topsrc = options.t
|
||||
topsrc = os.path.normpath(os.path.abspath(topsrc))
|
||||
if not args:
|
||||
infile = sys.stdin
|
||||
else:
|
||||
infile, = args
|
||||
jm.makeJar(infile, options.j)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -352,7 +352,6 @@ DEFINES += -DSTATIC_EXPORTABLE_JS_API
|
||||
endif
|
||||
endif
|
||||
|
||||
# Flags passed to JarMaker.py
|
||||
MAKE_JARS_FLAGS = \
|
||||
-t $(topsrcdir) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
|
@ -1451,10 +1451,10 @@ endif
|
||||
endif
|
||||
|
||||
libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
|
||||
$(call py_action,jar_maker,\
|
||||
$(QUIET) -j $(FINAL_TARGET)/chrome \
|
||||
$(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
|
||||
$(JAR_MANIFEST)
|
||||
$(JAR_MANIFEST))
|
||||
|
||||
endif
|
||||
endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/EventTarget.h" // for base class
|
||||
#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
|
||||
#include "mozilla/dom/DOMString.h"
|
||||
|
||||
// Including 'windows.h' will #define GetClassInfo to something else.
|
||||
#ifdef XP_WIN
|
||||
@ -1483,9 +1484,11 @@ public:
|
||||
*/
|
||||
uint32_t Length() const;
|
||||
|
||||
void GetNodeName(nsAString& aNodeName) const
|
||||
void GetNodeName(mozilla::dom::DOMString& aNodeName)
|
||||
{
|
||||
aNodeName = NodeName();
|
||||
const nsString& nodeName = NodeName();
|
||||
aNodeName.SetStringBuffer(nsStringBuffer::FromString(nodeName),
|
||||
nodeName.Length());
|
||||
}
|
||||
void GetBaseURI(nsAString& aBaseURI) const;
|
||||
bool HasChildNodes() const
|
||||
@ -1536,9 +1539,15 @@ public:
|
||||
mNodeInfo->GetPrefix(aPrefix);
|
||||
}
|
||||
#endif
|
||||
void GetLocalName(nsAString& aLocalName)
|
||||
void GetLocalName(mozilla::dom::DOMString& aLocalName)
|
||||
{
|
||||
aLocalName = mNodeInfo->LocalName();
|
||||
const nsString& localName = LocalName();
|
||||
if (localName.IsVoid()) {
|
||||
aLocalName.SetNull();
|
||||
} else {
|
||||
aLocalName.SetStringBuffer(nsStringBuffer::FromString(localName),
|
||||
localName.Length());
|
||||
}
|
||||
}
|
||||
// HasAttributes is defined inline in Element.h.
|
||||
bool HasAttributes() const;
|
||||
@ -1756,7 +1765,7 @@ ToCanonicalSupports(nsINode* aPointer)
|
||||
#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(...) \
|
||||
NS_IMETHOD GetNodeName(nsAString& aNodeName) __VA_ARGS__ \
|
||||
{ \
|
||||
nsINode::GetNodeName(aNodeName); \
|
||||
aNodeName = nsINode::NodeName(); \
|
||||
return NS_OK; \
|
||||
} \
|
||||
NS_IMETHOD GetNodeValue(nsAString& aNodeValue) __VA_ARGS__ \
|
||||
@ -1858,7 +1867,7 @@ ToCanonicalSupports(nsINode* aPointer)
|
||||
} \
|
||||
NS_IMETHOD GetLocalName(nsAString& aLocalName) __VA_ARGS__ \
|
||||
{ \
|
||||
nsINode::GetLocalName(aLocalName); \
|
||||
aLocalName = nsINode::LocalName(); \
|
||||
return NS_OK; \
|
||||
} \
|
||||
using nsINode::HasAttributes; \
|
||||
|
@ -282,6 +282,13 @@ public:
|
||||
uint16_t ReadyState();
|
||||
|
||||
// request
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
|
||||
{
|
||||
Open(aMethod, aUrl, true,
|
||||
mozilla::dom::Optional<nsAString>(),
|
||||
mozilla::dom::Optional<nsAString>(),
|
||||
aRv);
|
||||
}
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
|
||||
const mozilla::dom::Optional<nsAString>& aUser,
|
||||
const mozilla::dom::Optional<nsAString>& aPassword,
|
||||
|
@ -27,11 +27,15 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
is(doc.doctype.internalSubset, null, "internalSubset should be null!");
|
||||
isElement(doc.documentElement, "html");
|
||||
isElement(doc.documentElement.firstChild, "head");
|
||||
is(doc.documentElement.firstChild.childNodes.length, 1);
|
||||
isElement(doc.documentElement.firstChild.firstChild, "title");
|
||||
// Doesn't always work out in WebKit.
|
||||
ok(doc.documentElement.firstChild.firstChild.firstChild, "Need a text node.");
|
||||
is(doc.documentElement.firstChild.firstChild.firstChild.data, expectedtitle);
|
||||
if (title !== undefined) {
|
||||
is(doc.documentElement.firstChild.childNodes.length, 1);
|
||||
isElement(doc.documentElement.firstChild.firstChild, "title");
|
||||
// Doesn't always work out in WebKit.
|
||||
ok(doc.documentElement.firstChild.firstChild.firstChild, "Need a text node.");
|
||||
is(doc.documentElement.firstChild.firstChild.firstChild.data, expectedtitle);
|
||||
} else {
|
||||
is(doc.documentElement.firstChild.childNodes.length, 0);
|
||||
}
|
||||
isElement(doc.documentElement.lastChild, "body");
|
||||
is(doc.documentElement.lastChild.childNodes.length, 0);
|
||||
((!title || title.indexOf("\f") === -1) ? is : todo_is)
|
||||
@ -41,7 +45,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
}
|
||||
checkDoc("", "", "");
|
||||
checkDoc(null, "null", "null");
|
||||
checkDoc(undefined, "undefined", "undefined");
|
||||
checkDoc(undefined, "", "");
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz");
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz");
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz");
|
||||
|
@ -269,6 +269,56 @@ struct DeltaValues
|
||||
double deltaY;
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
/* nsScrollbarsForWheel */
|
||||
/******************************************************************/
|
||||
|
||||
class nsScrollbarsForWheel {
|
||||
public:
|
||||
static void PrepareToScrollText(nsEventStateManager* aESM,
|
||||
nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent);
|
||||
static void SetActiveScrollTarget(nsIScrollableFrame* aScrollTarget);
|
||||
// Hide all scrollbars (both mActiveOwner's and mActivatedScrollTargets')
|
||||
static void MayInactivate();
|
||||
static void Inactivate();
|
||||
static bool IsActive();
|
||||
static void OwnWheelTransaction(bool aOwn);
|
||||
|
||||
protected:
|
||||
static const size_t kNumberOfTargets = 4;
|
||||
static const DeltaValues directions[kNumberOfTargets];
|
||||
static nsWeakFrame sActiveOwner;
|
||||
static nsWeakFrame sActivatedScrollTargets[kNumberOfTargets];
|
||||
static bool sHadWheelStart;
|
||||
static bool sOwnWheelTransaction;
|
||||
|
||||
|
||||
/**
|
||||
* These two methods are called upon NS_WHEEL_START/NS_WHEEL_STOP events
|
||||
* to show/hide the right scrollbars.
|
||||
*/
|
||||
static void TemporarilyActivateAllPossibleScrollTargets(
|
||||
nsEventStateManager* aESM,
|
||||
nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent);
|
||||
static void DeactivateAllTemporarilyActivatedScrollTargets();
|
||||
};
|
||||
|
||||
const DeltaValues nsScrollbarsForWheel::directions[kNumberOfTargets] = {
|
||||
DeltaValues(-1, 0), DeltaValues(+1, 0), DeltaValues(0, -1), DeltaValues(0, +1)
|
||||
};
|
||||
nsWeakFrame nsScrollbarsForWheel::sActiveOwner = nullptr;
|
||||
nsWeakFrame nsScrollbarsForWheel::sActivatedScrollTargets[kNumberOfTargets] = {
|
||||
nullptr, nullptr, nullptr, nullptr
|
||||
};
|
||||
bool nsScrollbarsForWheel::sHadWheelStart = false;
|
||||
bool nsScrollbarsForWheel::sOwnWheelTransaction = false;
|
||||
|
||||
/******************************************************************/
|
||||
/* nsMouseWheelTransaction */
|
||||
/******************************************************************/
|
||||
|
||||
class nsMouseWheelTransaction {
|
||||
public:
|
||||
static nsIFrame* GetTargetFrame() { return sTargetFrame; }
|
||||
@ -277,11 +327,13 @@ public:
|
||||
// Be careful, UpdateTransaction may fire a DOM event, therefore, the target
|
||||
// frame might be destroyed in the event handler.
|
||||
static bool UpdateTransaction(WheelEvent* aEvent);
|
||||
static void MayEndTransaction();
|
||||
static void EndTransaction();
|
||||
static void OnEvent(WidgetEvent* aEvent);
|
||||
static void Shutdown();
|
||||
static uint32_t GetTimeoutTime();
|
||||
|
||||
static void OwnScrollbars(bool aOwn);
|
||||
|
||||
static DeltaValues AccelerateWheelDelta(WheelEvent* aEvent,
|
||||
bool aAllowScrollSpeedOverride);
|
||||
@ -299,12 +351,14 @@ protected:
|
||||
static int32_t GetAccelerationFactor();
|
||||
static DeltaValues OverrideSystemScrollSpeed(WheelEvent* aEvent);
|
||||
static double ComputeAcceleratedWheelDelta(double aDelta, int32_t aFactor);
|
||||
static bool OutOfTime(uint32_t aBaseTime, uint32_t aThreshold);
|
||||
|
||||
static nsWeakFrame sTargetFrame;
|
||||
static uint32_t sTime; // in milliseconds
|
||||
static uint32_t sMouseMoved; // in milliseconds
|
||||
static nsITimer* sTimer;
|
||||
static int32_t sScrollSeriesCounter;
|
||||
static bool sOwnScrollbars;
|
||||
};
|
||||
|
||||
nsWeakFrame nsMouseWheelTransaction::sTargetFrame(nullptr);
|
||||
@ -312,13 +366,7 @@ uint32_t nsMouseWheelTransaction::sTime = 0;
|
||||
uint32_t nsMouseWheelTransaction::sMouseMoved = 0;
|
||||
nsITimer* nsMouseWheelTransaction::sTimer = nullptr;
|
||||
int32_t nsMouseWheelTransaction::sScrollSeriesCounter = 0;
|
||||
|
||||
static bool
|
||||
OutOfTime(uint32_t aBaseTime, uint32_t aThreshold)
|
||||
{
|
||||
uint32_t now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||
return (now - aBaseTime > aThreshold);
|
||||
}
|
||||
bool nsMouseWheelTransaction::sOwnScrollbars = false;
|
||||
|
||||
static bool
|
||||
CanScrollInRange(nscoord aMin, nscoord aValue, nscoord aMax, double aDirection)
|
||||
@ -328,20 +376,33 @@ CanScrollInRange(nscoord aMin, nscoord aValue, nscoord aMax, double aDirection)
|
||||
}
|
||||
|
||||
static bool
|
||||
CanScrollOn(nsIScrollableFrame* aScrollFrame, double aDeltaX, double aDeltaY)
|
||||
CanScrollOn(nsIScrollableFrame* aScrollFrame, double aDirectionX, double aDirectionY)
|
||||
{
|
||||
MOZ_ASSERT(aScrollFrame);
|
||||
NS_ASSERTION(aDeltaX || aDeltaY,
|
||||
NS_ASSERTION(aDirectionX || aDirectionY,
|
||||
"One of the delta values must be non-zero at least");
|
||||
|
||||
nsPoint scrollPt = aScrollFrame->GetScrollPosition();
|
||||
nsRect scrollRange = aScrollFrame->GetScrollRange();
|
||||
uint32_t directions = aScrollFrame->GetPerceivedScrollingDirections();
|
||||
|
||||
return (aDeltaX && (directions & nsIScrollableFrame::HORIZONTAL) &&
|
||||
CanScrollInRange(scrollRange.x, scrollPt.x, scrollRange.XMost(), aDeltaX)) ||
|
||||
(aDeltaY && (directions & nsIScrollableFrame::VERTICAL) &&
|
||||
CanScrollInRange(scrollRange.y, scrollPt.y, scrollRange.YMost(), aDeltaY));
|
||||
return (aDirectionX && (directions & nsIScrollableFrame::HORIZONTAL) &&
|
||||
CanScrollInRange(scrollRange.x, scrollPt.x, scrollRange.XMost(), aDirectionX)) ||
|
||||
(aDirectionY && (directions & nsIScrollableFrame::VERTICAL) &&
|
||||
CanScrollInRange(scrollRange.y, scrollPt.y, scrollRange.YMost(), aDirectionY));
|
||||
}
|
||||
|
||||
bool
|
||||
nsMouseWheelTransaction::OutOfTime(uint32_t aBaseTime, uint32_t aThreshold)
|
||||
{
|
||||
uint32_t now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
||||
return (now - aBaseTime > aThreshold);
|
||||
}
|
||||
|
||||
void
|
||||
nsMouseWheelTransaction::OwnScrollbars(bool aOwn)
|
||||
{
|
||||
sOwnScrollbars = aOwn;
|
||||
}
|
||||
|
||||
void
|
||||
@ -349,6 +410,9 @@ nsMouseWheelTransaction::BeginTransaction(nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(!sTargetFrame, "previous transaction is not finished!");
|
||||
MOZ_ASSERT(aEvent->message == NS_WHEEL_WHEEL,
|
||||
"Transaction must be started with a wheel event");
|
||||
nsScrollbarsForWheel::OwnWheelTransaction(false);
|
||||
sTargetFrame = aTargetFrame;
|
||||
sScrollSeriesCounter = 0;
|
||||
if (!UpdateTransaction(aEvent)) {
|
||||
@ -385,6 +449,16 @@ nsMouseWheelTransaction::UpdateTransaction(WheelEvent* aEvent)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsMouseWheelTransaction::MayEndTransaction()
|
||||
{
|
||||
if (!sOwnScrollbars && nsScrollbarsForWheel::IsActive()) {
|
||||
nsScrollbarsForWheel::OwnWheelTransaction(true);
|
||||
} else {
|
||||
EndTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsMouseWheelTransaction::EndTransaction()
|
||||
{
|
||||
@ -392,6 +466,11 @@ nsMouseWheelTransaction::EndTransaction()
|
||||
sTimer->Cancel();
|
||||
sTargetFrame = nullptr;
|
||||
sScrollSeriesCounter = 0;
|
||||
if (sOwnScrollbars) {
|
||||
sOwnScrollbars = false;
|
||||
nsScrollbarsForWheel::OwnWheelTransaction(false);
|
||||
nsScrollbarsForWheel::Inactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -415,7 +494,7 @@ nsMouseWheelTransaction::OnEvent(WidgetEvent* aEvent)
|
||||
OutOfTime(sMouseMoved, GetIgnoreMoveDelayTime())) {
|
||||
// Terminate the current mousewheel transaction if the mouse moved more
|
||||
// than ignoremovedelay milliseconds ago
|
||||
EndTransaction();
|
||||
MayEndTransaction();
|
||||
}
|
||||
return;
|
||||
case NS_MOUSE_MOVE:
|
||||
@ -426,7 +505,7 @@ nsMouseWheelTransaction::OnEvent(WidgetEvent* aEvent)
|
||||
nsIntPoint pt = GetScreenPoint(static_cast<WidgetGUIEvent*>(aEvent));
|
||||
nsIntRect r = sTargetFrame->GetScreenRectExternal();
|
||||
if (!r.Contains(pt)) {
|
||||
EndTransaction();
|
||||
MayEndTransaction();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -475,8 +554,9 @@ nsMouseWheelTransaction::OnFailToScrollTarget()
|
||||
}
|
||||
// The target frame might be destroyed in the event handler, at that time,
|
||||
// we need to finish the current transaction
|
||||
if (!sTargetFrame)
|
||||
if (!sTargetFrame) {
|
||||
EndTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -491,7 +571,7 @@ nsMouseWheelTransaction::OnTimeout(nsITimer* aTimer, void* aClosure)
|
||||
nsIFrame* frame = sTargetFrame;
|
||||
// We need to finish current transaction before DOM event firing. Because
|
||||
// the next DOM event might create strange situation for us.
|
||||
EndTransaction();
|
||||
MayEndTransaction();
|
||||
|
||||
if (Preferences::GetBool("test.mousescroll", false)) {
|
||||
// This event is used for automated tests, see bug 442774.
|
||||
@ -625,6 +705,127 @@ nsMouseWheelTransaction::OverrideSystemScrollSpeed(WheelEvent* aEvent)
|
||||
return NS_FAILED(rv) ? DeltaValues(aEvent) : overriddenDeltaValues;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* nsScrollbarsForWheel */
|
||||
/******************************************************************/
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::PrepareToScrollText(
|
||||
nsEventStateManager* aESM,
|
||||
nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent)
|
||||
{
|
||||
if (aEvent->message == NS_WHEEL_START) {
|
||||
nsMouseWheelTransaction::OwnScrollbars(false);
|
||||
if (!IsActive()) {
|
||||
TemporarilyActivateAllPossibleScrollTargets(aESM, aTargetFrame, aEvent);
|
||||
sHadWheelStart = true;
|
||||
}
|
||||
} else {
|
||||
DeactivateAllTemporarilyActivatedScrollTargets();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::SetActiveScrollTarget(nsIScrollableFrame* aScrollTarget)
|
||||
{
|
||||
if (!sHadWheelStart) {
|
||||
return;
|
||||
}
|
||||
nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(aScrollTarget);
|
||||
if (!scrollbarOwner) {
|
||||
return;
|
||||
}
|
||||
sHadWheelStart = false;
|
||||
sActiveOwner = do_QueryFrame(aScrollTarget);
|
||||
scrollbarOwner->ScrollbarActivityStarted();
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::MayInactivate()
|
||||
{
|
||||
if (!sOwnWheelTransaction && nsMouseWheelTransaction::GetTargetFrame()) {
|
||||
nsMouseWheelTransaction::OwnScrollbars(true);
|
||||
} else {
|
||||
Inactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::Inactivate()
|
||||
{
|
||||
nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sActiveOwner);
|
||||
if (scrollbarOwner) {
|
||||
scrollbarOwner->ScrollbarActivityStopped();
|
||||
}
|
||||
sActiveOwner = nullptr;
|
||||
DeactivateAllTemporarilyActivatedScrollTargets();
|
||||
if (sOwnWheelTransaction) {
|
||||
sOwnWheelTransaction = false;
|
||||
nsMouseWheelTransaction::OwnScrollbars(false);
|
||||
nsMouseWheelTransaction::EndTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsScrollbarsForWheel::IsActive()
|
||||
{
|
||||
if (sActiveOwner) {
|
||||
return true;
|
||||
}
|
||||
for (size_t i = 0; i < kNumberOfTargets; ++i) {
|
||||
if (sActivatedScrollTargets[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::OwnWheelTransaction(bool aOwn)
|
||||
{
|
||||
sOwnWheelTransaction = aOwn;
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets(
|
||||
nsEventStateManager* aESM,
|
||||
nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent)
|
||||
{
|
||||
for (size_t i = 0; i < kNumberOfTargets; i++) {
|
||||
const DeltaValues *dir = &directions[i];
|
||||
nsWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
|
||||
MOZ_ASSERT(!*scrollTarget, "scroll target still temporarily activated!");
|
||||
nsIScrollableFrame* target =
|
||||
aESM->ComputeScrollTarget(aTargetFrame, dir->deltaX, dir->deltaY, aEvent,
|
||||
nsEventStateManager::COMPUTE_DEFAULT_ACTION_TARGET);
|
||||
if (target) {
|
||||
nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(target);
|
||||
if (scrollbarOwner) {
|
||||
nsIFrame* targetFrame = do_QueryFrame(target);
|
||||
*scrollTarget = targetFrame;
|
||||
scrollbarOwner->ScrollbarActivityStarted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsScrollbarsForWheel::DeactivateAllTemporarilyActivatedScrollTargets()
|
||||
{
|
||||
for (size_t i = 0; i < kNumberOfTargets; i++) {
|
||||
nsWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
|
||||
if (*scrollTarget) {
|
||||
nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(*scrollTarget);
|
||||
if (scrollbarOwner) {
|
||||
scrollbarOwner->ScrollbarActivityStopped();
|
||||
}
|
||||
*scrollTarget = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* nsEventStateManager */
|
||||
/******************************************************************/
|
||||
@ -977,13 +1178,20 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
break;
|
||||
case NS_WHEEL_WHEEL:
|
||||
case NS_WHEEL_START:
|
||||
case NS_WHEEL_STOP:
|
||||
{
|
||||
NS_ASSERTION(aEvent->mFlags.mIsTrusted,
|
||||
"Untrusted wheel event shouldn't be here");
|
||||
|
||||
nsIContent* content = GetFocusedContent();
|
||||
if (content)
|
||||
if (content) {
|
||||
mCurrentTargetContent = content;
|
||||
}
|
||||
|
||||
if (aEvent->message != NS_WHEEL_WHEEL) {
|
||||
break;
|
||||
}
|
||||
|
||||
WheelEvent* wheelEvent = static_cast<WheelEvent*>(aEvent);
|
||||
WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
|
||||
@ -2545,6 +2753,20 @@ nsIScrollableFrame*
|
||||
nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
WheelEvent* aEvent,
|
||||
ComputeScrollTargetOptions aOptions)
|
||||
{
|
||||
return ComputeScrollTarget(aTargetFrame, aEvent->deltaX, aEvent->deltaY,
|
||||
aEvent, aOptions);
|
||||
}
|
||||
|
||||
// Overload ComputeScrollTarget method to allow passing "test" dx and dy when looking
|
||||
// for which scrollbarowners to activate when two finger down on trackpad
|
||||
// and before any actual motion
|
||||
nsIScrollableFrame*
|
||||
nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
double aDirectionX,
|
||||
double aDirectionY,
|
||||
WheelEvent* aEvent,
|
||||
ComputeScrollTargetOptions aOptions)
|
||||
{
|
||||
if (aOptions & PREFER_MOUSE_WHEEL_TRANSACTION) {
|
||||
// If the user recently scrolled with the mousewheel, then they probably
|
||||
@ -2569,14 +2791,14 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
// If the event doesn't cause scroll actually, we cannot find scroll target
|
||||
// because we check if the event can cause scroll actually on each found
|
||||
// scrollable frame.
|
||||
if (!aEvent->deltaX && !aEvent->deltaY) {
|
||||
if (!aDirectionX && !aDirectionY) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool checkIfScrollableX =
|
||||
aEvent->deltaX && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
|
||||
aDirectionX && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
|
||||
bool checkIfScrollableY =
|
||||
aEvent->deltaY && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
|
||||
aDirectionY && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
|
||||
|
||||
nsIScrollableFrame* frameToScroll = nullptr;
|
||||
nsIFrame* scrollFrame =
|
||||
@ -2604,8 +2826,7 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
|
||||
// For default action, we should climb up the tree if cannot scroll it
|
||||
// by the event actually.
|
||||
bool canScroll = CanScrollOn(frameToScroll,
|
||||
aEvent->deltaX, aEvent->deltaY);
|
||||
bool canScroll = CanScrollOn(frameToScroll, aDirectionX, aDirectionY);
|
||||
// Comboboxes need special care.
|
||||
nsIComboboxControlFrame* comboBox = do_QueryFrame(scrollFrame);
|
||||
if (comboBox) {
|
||||
@ -3170,25 +3391,44 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NS_WHEEL_STOP:
|
||||
{
|
||||
MOZ_ASSERT(aEvent->mFlags.mIsTrusted);
|
||||
nsScrollbarsForWheel::MayInactivate();
|
||||
}
|
||||
break;
|
||||
case NS_WHEEL_WHEEL:
|
||||
case NS_WHEEL_START:
|
||||
{
|
||||
MOZ_ASSERT(aEvent->mFlags.mIsTrusted);
|
||||
|
||||
if (*aStatus == nsEventStatus_eConsumeNoDefault) {
|
||||
nsScrollbarsForWheel::Inactivate();
|
||||
break;
|
||||
}
|
||||
|
||||
WheelEvent* wheelEvent = static_cast<WheelEvent*>(aEvent);
|
||||
switch (WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent)) {
|
||||
case WheelPrefs::ACTION_SCROLL: {
|
||||
if (!wheelEvent->deltaX && !wheelEvent->deltaY) {
|
||||
break;
|
||||
}
|
||||
// For scrolling of default action, we should honor the mouse wheel
|
||||
// transaction.
|
||||
|
||||
nsScrollbarsForWheel::PrepareToScrollText(this, aTargetFrame, wheelEvent);
|
||||
|
||||
if (aEvent->message != NS_WHEEL_WHEEL ||
|
||||
(!wheelEvent->deltaX && !wheelEvent->deltaY)) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollTarget =
|
||||
ComputeScrollTarget(aTargetFrame, wheelEvent,
|
||||
COMPUTE_DEFAULT_ACTION_TARGET);
|
||||
|
||||
nsScrollbarsForWheel::SetActiveScrollTarget(scrollTarget);
|
||||
|
||||
if (!scrollTarget) {
|
||||
wheelEvent->mViewPortIsOverscrolled = true;
|
||||
}
|
||||
wheelEvent->overflowDeltaX = wheelEvent->deltaX;
|
||||
wheelEvent->overflowDeltaY = wheelEvent->deltaY;
|
||||
WheelPrefs::GetInstance()->
|
||||
@ -3197,6 +3437,7 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
DoScrollText(scrollTarget, wheelEvent);
|
||||
} else {
|
||||
nsMouseWheelTransaction::EndTransaction();
|
||||
nsScrollbarsForWheel::Inactivate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ class nsEventStateManager : public nsSupportsWeakReference,
|
||||
public nsIObserver
|
||||
{
|
||||
friend class nsMouseWheelTransaction;
|
||||
friend class nsScrollbarsForWheel;
|
||||
public:
|
||||
|
||||
typedef mozilla::TimeStamp TimeStamp;
|
||||
@ -557,6 +558,12 @@ protected:
|
||||
mozilla::WheelEvent* aEvent,
|
||||
ComputeScrollTargetOptions aOptions);
|
||||
|
||||
nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
double aDirectionX,
|
||||
double aDirectionY,
|
||||
mozilla::WheelEvent* aEvent,
|
||||
ComputeScrollTargetOptions aOptions);
|
||||
|
||||
/**
|
||||
* GetScrollAmount() returns the scroll amount in app uints of one line or
|
||||
* one page. If the wheel event scrolls a page, returns the page width and
|
||||
|
@ -18,10 +18,9 @@
|
||||
#include "js/RootingAPI.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h" // for nsRefPtr member variables
|
||||
#include "mozilla/dom/DOMString.h"
|
||||
#include "mozilla/dom/OwningNonNull.h"
|
||||
|
||||
class nsWrapperCache;
|
||||
@ -90,133 +89,6 @@ protected:
|
||||
mutable nsCOMPtr<nsISupports> mGlobalObjectRef;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class for representing string return values. This can be either passed to
|
||||
* callees that have an nsString or nsAString out param or passed to a callee
|
||||
* that actually knows about this class and can work with it. Such a callee may
|
||||
* call SetStringBuffer on this object, but only if it plans to keep holding a
|
||||
* strong ref to the stringbuffer!
|
||||
*
|
||||
* The proper way to store a value in this class is to either to do nothing
|
||||
* (which leaves this as an empty string), to call SetStringBuffer with a
|
||||
* non-null stringbuffer, to call SetNull(), or to call AsAString() and set the
|
||||
* value in the resulting nsString. These options are mutually exclusive!
|
||||
* Don't do more than one of them.
|
||||
*
|
||||
* The proper way to extract a value is to check IsNull(). If not null, then
|
||||
* check HasStringBuffer(). If that's true, check for a zero length, and if the
|
||||
* length is nonzero call StringBuffer(). If the length is zero this is the
|
||||
* empty string. If HasStringBuffer() returns false, call AsAString() and get
|
||||
* the value from that.
|
||||
*/
|
||||
class MOZ_STACK_CLASS DOMString {
|
||||
public:
|
||||
DOMString()
|
||||
: mStringBuffer(nullptr)
|
||||
, mLength(0)
|
||||
, mIsNull(false)
|
||||
{}
|
||||
~DOMString()
|
||||
{
|
||||
MOZ_ASSERT(mString.empty() || !mStringBuffer,
|
||||
"Shouldn't have both present!");
|
||||
}
|
||||
|
||||
operator nsString&()
|
||||
{
|
||||
return AsAString();
|
||||
}
|
||||
|
||||
nsString& AsAString()
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?");
|
||||
MOZ_ASSERT(!mIsNull, "We're already set as null");
|
||||
if (mString.empty()) {
|
||||
mString.construct();
|
||||
}
|
||||
return mString.ref();
|
||||
}
|
||||
|
||||
bool HasStringBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(mString.empty() || !mStringBuffer,
|
||||
"Shouldn't have both present!");
|
||||
MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
|
||||
return mString.empty();
|
||||
}
|
||||
|
||||
// Get the stringbuffer. This can only be called if HasStringBuffer()
|
||||
// returned true and StringBufferLength() is nonzero. If that's true, it will
|
||||
// never return null.
|
||||
nsStringBuffer* StringBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
|
||||
MOZ_ASSERT(HasStringBuffer(),
|
||||
"Don't ask for the stringbuffer if we don't have it");
|
||||
MOZ_ASSERT(StringBufferLength() != 0, "Why are you asking for this?");
|
||||
MOZ_ASSERT(mStringBuffer,
|
||||
"If our length is nonzero, we better have a stringbuffer.");
|
||||
return mStringBuffer;
|
||||
}
|
||||
|
||||
// Get the length of the stringbuffer. Can only be called if
|
||||
// HasStringBuffer().
|
||||
uint32_t StringBufferLength() const
|
||||
{
|
||||
MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer");
|
||||
return mLength;
|
||||
}
|
||||
|
||||
void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(mString.empty(), "We already have a string?");
|
||||
MOZ_ASSERT(!mIsNull, "We're already set as null");
|
||||
MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
|
||||
MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
|
||||
mStringBuffer = aStringBuffer;
|
||||
mLength = aLength;
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
|
||||
MOZ_ASSERT(mString.empty(), "Should have no string if null");
|
||||
mIsNull = true;
|
||||
}
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer || mString.empty(),
|
||||
"How could we have a stringbuffer and a nonempty string?");
|
||||
return mIsNull || (!mString.empty() && mString.ref().IsVoid());
|
||||
}
|
||||
|
||||
void ToString(nsAString& aString)
|
||||
{
|
||||
if (IsNull()) {
|
||||
SetDOMStringToNull(aString);
|
||||
} else if (HasStringBuffer()) {
|
||||
if (StringBufferLength() == 0) {
|
||||
aString.Truncate();
|
||||
} else {
|
||||
StringBuffer()->ToString(StringBufferLength(), aString);
|
||||
}
|
||||
} else {
|
||||
aString = AsAString();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// We need to be able to act like a string as needed
|
||||
Maybe<nsAutoString> mString;
|
||||
|
||||
// For callees that know we exist, we can be a stringbuffer/length/null-flag
|
||||
// triple.
|
||||
nsStringBuffer* mStringBuffer;
|
||||
uint32_t mLength;
|
||||
bool mIsNull;
|
||||
};
|
||||
|
||||
// Class for representing optional arguments.
|
||||
template<typename T, typename InternalType>
|
||||
class Optional_base
|
||||
@ -621,4 +493,4 @@ struct ParentObject {
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_BindingDeclarations_h__
|
||||
#endif // mozilla_dom_BindingDeclarations_h__
|
||||
|
@ -2703,8 +2703,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
# A helper function for wrapping up the template body for
|
||||
# possibly-nullable objecty stuff
|
||||
def wrapObjectTemplate(templateBody, type, codeToSetNull, failureCode=None):
|
||||
if isNullOrUndefined:
|
||||
assert type.nullable()
|
||||
if isNullOrUndefined and type.nullable():
|
||||
# Just ignore templateBody and set ourselves to null.
|
||||
# Note that we don't have to worry about default values
|
||||
# here either, since we already examined this value.
|
||||
@ -3321,9 +3320,6 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||
"Default": "eStringify",
|
||||
"EmptyString": "eEmpty",
|
||||
"Null": "eNull",
|
||||
# For Missing it doesn't matter what we use here, since we'll never
|
||||
# call ConvertJSValueToString on undefined in that case.
|
||||
"Missing": "eStringify"
|
||||
}
|
||||
if type.nullable():
|
||||
# For nullable strings null becomes a null string.
|
||||
@ -3843,11 +3839,8 @@ class CGArgumentConverter(CGThing):
|
||||
"args[${index}]"
|
||||
).substitute(replacer)
|
||||
self.replacementVariables["mutableVal"] = self.replacementVariables["val"]
|
||||
if argument.treatUndefinedAs == "Missing":
|
||||
haveValueCheck = "args.hasDefined(${index})"
|
||||
else:
|
||||
haveValueCheck = "${index} < args.length()"
|
||||
haveValueCheck = string.Template(haveValueCheck).substitute(replacer)
|
||||
haveValueCheck = string.Template(
|
||||
"args.hasDefined(${index})").substitute(replacer)
|
||||
self.replacementVariables["haveValue"] = haveValueCheck
|
||||
self.descriptorProvider = descriptorProvider
|
||||
if self.argument.optional and not self.argument.defaultValue:
|
||||
@ -4988,15 +4981,6 @@ class CGMethodCall(CGThing):
|
||||
CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
|
||||
return
|
||||
|
||||
# We don't handle [TreatUndefinedAs=Missing] arguments in overload
|
||||
# resolution yet.
|
||||
for (_, sigArgs) in signatures:
|
||||
for arg in sigArgs:
|
||||
if arg.treatUndefinedAs == "Missing":
|
||||
raise TypeError("No support for [TreatUndefinedAs=Missing] "
|
||||
"handling in overload resolution yet: %s" %
|
||||
arg.location)
|
||||
|
||||
# Need to find the right overload
|
||||
maxArgCount = method.maxArgCount
|
||||
allowedArgCounts = method.allowedArgCounts
|
||||
@ -5086,22 +5070,30 @@ class CGMethodCall(CGThing):
|
||||
else:
|
||||
failureCode = None
|
||||
type = distinguishingType(signature)
|
||||
# The argument at index distinguishingIndex can't possibly
|
||||
# be unset here, because we've already checked that argc is
|
||||
# large enough that we can examine this argument.
|
||||
# The argument at index distinguishingIndex can't possibly be
|
||||
# unset here, because we've already checked that argc is large
|
||||
# enough that we can examine this argument. But note that we
|
||||
# still want to claim that optional arguments are optional, in
|
||||
# case undefined was passed in.
|
||||
argIsOptional = (distinguishingArgument(signature).optional and
|
||||
not distinguishingArgument(signature).defaultValue)
|
||||
testCode = instantiateJSToNativeConversion(
|
||||
getJSToNativeConversionInfo(type, descriptor,
|
||||
failureCode=failureCode,
|
||||
isDefinitelyObject=isDefinitelyObject,
|
||||
isNullOrUndefined=isNullOrUndefined,
|
||||
isOptional=argIsOptional,
|
||||
sourceDescription=(argDesc % (distinguishingIndex + 1))),
|
||||
{
|
||||
"declName" : "arg%d" % distinguishingIndex,
|
||||
"holderName" : ("arg%d" % distinguishingIndex) + "_holder",
|
||||
"val" : distinguishingArg,
|
||||
"mutableVal" : distinguishingArg,
|
||||
"obj" : "obj"
|
||||
})
|
||||
"obj" : "obj",
|
||||
"haveValue": "args.hasDefined(%d)" % distinguishingIndex
|
||||
},
|
||||
checkForValue=argIsOptional
|
||||
)
|
||||
caseBody.append(CGIndenter(testCode, indent));
|
||||
# If we got this far, we know we unwrapped to the right
|
||||
# C++ type, so just do the call. Start conversion with
|
||||
@ -5111,24 +5103,76 @@ class CGMethodCall(CGThing):
|
||||
getPerSignatureCall(signature, distinguishingIndex + 1),
|
||||
indent))
|
||||
|
||||
# First check for null or undefined. That means looking for
|
||||
def hasConditionalConversion(type):
|
||||
"""
|
||||
Return whether the argument conversion for this type will be
|
||||
conditional on the type of incoming JS value. For example, for
|
||||
interface types the conversion is conditional on the incoming
|
||||
value being isObject().
|
||||
|
||||
For the types for which this returns false, we do not have to
|
||||
output extra isUndefined() or isNullOrUndefined() cases, because
|
||||
null/undefined values will just fall through into our
|
||||
unconditional conversion.
|
||||
"""
|
||||
if type.isString() or type.isEnum():
|
||||
return False
|
||||
if type.isBoolean():
|
||||
distinguishingTypes = (distinguishingType(s) for s in
|
||||
possibleSignatures)
|
||||
return any(t.isString() or t.isEnum() or t.isNumeric()
|
||||
for t in distinguishingTypes)
|
||||
if type.isNumeric():
|
||||
distinguishingTypes = (distinguishingType(s) for s in
|
||||
possibleSignatures)
|
||||
return any(t.isString() or t.isEnum()
|
||||
for t in distinguishingTypes)
|
||||
return True
|
||||
|
||||
def needsNullOrUndefinedCase(type):
|
||||
"""
|
||||
Return true if the type needs a special isNullOrUndefined() case
|
||||
"""
|
||||
return ((type.nullable() and
|
||||
hasConditionalConversion(type)) or
|
||||
type.isDictionary())
|
||||
|
||||
# First check for undefined and optional distinguishing arguments
|
||||
# and output a special branch for that case. Note that we don't
|
||||
# use distinguishingArgument here because we actualy want to
|
||||
# exclude variadic arguments. Also note that we skip this check if
|
||||
# we plan to output a isNullOrUndefined() special case for this
|
||||
# argument anyway, since that will subsume our isUndefined() check.
|
||||
# This is safe, because there can be at most one nullable
|
||||
# distinguishing argument, so if we're it we'll definitely get
|
||||
# picked up by the nullable handling. Also, we can skip this check
|
||||
# if the argument has an unconditional conversion later on.
|
||||
undefSigs = [s for s in possibleSignatures if
|
||||
distinguishingIndex < len(s[1]) and
|
||||
s[1][distinguishingIndex].optional and
|
||||
hasConditionalConversion(s[1][distinguishingIndex].type) and
|
||||
not needsNullOrUndefinedCase(s[1][distinguishingIndex].type)]
|
||||
# Can't have multiple signatures with an optional argument at the
|
||||
# same index.
|
||||
assert len(undefSigs) < 2
|
||||
if len(undefSigs) > 0:
|
||||
caseBody.append(CGGeneric("if (%s.isUndefined()) {" %
|
||||
distinguishingArg))
|
||||
tryCall(undefSigs[0], 2, isNullOrUndefined=True)
|
||||
caseBody.append(CGGeneric("}"))
|
||||
|
||||
# Next, check for null or undefined. That means looking for
|
||||
# nullable arguments at the distinguishing index and outputting a
|
||||
# separate branch for them. But if the nullable argument is a
|
||||
# primitive, string, or enum, we don't need to do that. The reason
|
||||
# separate branch for them. But if the nullable argument has an
|
||||
# unconditional conversion, we don't need to do that. The reason
|
||||
# for that is that at most one argument at the distinguishing index
|
||||
# is nullable (since two nullable arguments are not
|
||||
# distinguishable), and all the argument types other than
|
||||
# primitive/string/enum end up inside isObject() checks. So if our
|
||||
# nullable is a primitive/string/enum it's safe to not output the
|
||||
# extra branch: we'll fall through to conversion for those types,
|
||||
# which correctly handles null as needed, because isObject() will be
|
||||
# false for null and undefined.
|
||||
# distinguishable), and null/undefined values will always fall
|
||||
# through to the unconditional conversion we have, if any, since
|
||||
# they will fail whatever the conditions on the input value are for
|
||||
# our other conversions.
|
||||
nullOrUndefSigs = [s for s in possibleSignatures
|
||||
if ((distinguishingType(s).nullable() and not
|
||||
distinguishingType(s).isString() and not
|
||||
distinguishingType(s).isEnum() and not
|
||||
distinguishingType(s).isPrimitive()) or
|
||||
distinguishingType(s).isDictionary())]
|
||||
if needsNullOrUndefinedCase(distinguishingType(s))]
|
||||
# Can't have multiple nullable types here
|
||||
assert len(nullOrUndefSigs) < 2
|
||||
if len(nullOrUndefSigs) > 0:
|
||||
|
149
dom/bindings/DOMString.h
Normal file
149
dom/bindings/DOMString.h
Normal file
@ -0,0 +1,149 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_DOMString_h
|
||||
#define mozilla_dom_DOMString_h
|
||||
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsDOMString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* A class for representing string return values. This can be either passed to
|
||||
* callees that have an nsString or nsAString out param or passed to a callee
|
||||
* that actually knows about this class and can work with it. Such a callee may
|
||||
* call SetStringBuffer on this object, but only if it plans to keep holding a
|
||||
* strong ref to the stringbuffer!
|
||||
*
|
||||
* The proper way to store a value in this class is to either to do nothing
|
||||
* (which leaves this as an empty string), to call SetStringBuffer with a
|
||||
* non-null stringbuffer, to call SetNull(), or to call AsAString() and set the
|
||||
* value in the resulting nsString. These options are mutually exclusive!
|
||||
* Don't do more than one of them.
|
||||
*
|
||||
* The proper way to extract a value is to check IsNull(). If not null, then
|
||||
* check HasStringBuffer(). If that's true, check for a zero length, and if the
|
||||
* length is nonzero call StringBuffer(). If the length is zero this is the
|
||||
* empty string. If HasStringBuffer() returns false, call AsAString() and get
|
||||
* the value from that.
|
||||
*/
|
||||
class MOZ_STACK_CLASS DOMString {
|
||||
public:
|
||||
DOMString()
|
||||
: mStringBuffer(nullptr)
|
||||
, mLength(0)
|
||||
, mIsNull(false)
|
||||
{}
|
||||
~DOMString()
|
||||
{
|
||||
MOZ_ASSERT(mString.empty() || !mStringBuffer,
|
||||
"Shouldn't have both present!");
|
||||
}
|
||||
|
||||
operator nsString&()
|
||||
{
|
||||
return AsAString();
|
||||
}
|
||||
|
||||
nsString& AsAString()
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?");
|
||||
MOZ_ASSERT(!mIsNull, "We're already set as null");
|
||||
if (mString.empty()) {
|
||||
mString.construct();
|
||||
}
|
||||
return mString.ref();
|
||||
}
|
||||
|
||||
bool HasStringBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(mString.empty() || !mStringBuffer,
|
||||
"Shouldn't have both present!");
|
||||
MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
|
||||
return mString.empty();
|
||||
}
|
||||
|
||||
// Get the stringbuffer. This can only be called if HasStringBuffer()
|
||||
// returned true and StringBufferLength() is nonzero. If that's true, it will
|
||||
// never return null.
|
||||
nsStringBuffer* StringBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first");
|
||||
MOZ_ASSERT(HasStringBuffer(),
|
||||
"Don't ask for the stringbuffer if we don't have it");
|
||||
MOZ_ASSERT(StringBufferLength() != 0, "Why are you asking for this?");
|
||||
MOZ_ASSERT(mStringBuffer,
|
||||
"If our length is nonzero, we better have a stringbuffer.");
|
||||
return mStringBuffer;
|
||||
}
|
||||
|
||||
// Get the length of the stringbuffer. Can only be called if
|
||||
// HasStringBuffer().
|
||||
uint32_t StringBufferLength() const
|
||||
{
|
||||
MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer");
|
||||
return mLength;
|
||||
}
|
||||
|
||||
void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength)
|
||||
{
|
||||
MOZ_ASSERT(mString.empty(), "We already have a string?");
|
||||
MOZ_ASSERT(!mIsNull, "We're already set as null");
|
||||
MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?");
|
||||
MOZ_ASSERT(aStringBuffer, "Why are we getting null?");
|
||||
mStringBuffer = aStringBuffer;
|
||||
mLength = aLength;
|
||||
}
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null");
|
||||
MOZ_ASSERT(mString.empty(), "Should have no string if null");
|
||||
mIsNull = true;
|
||||
}
|
||||
|
||||
bool IsNull() const
|
||||
{
|
||||
MOZ_ASSERT(!mStringBuffer || mString.empty(),
|
||||
"How could we have a stringbuffer and a nonempty string?");
|
||||
return mIsNull || (!mString.empty() && mString.ref().IsVoid());
|
||||
}
|
||||
|
||||
void ToString(nsAString& aString)
|
||||
{
|
||||
if (IsNull()) {
|
||||
SetDOMStringToNull(aString);
|
||||
} else if (HasStringBuffer()) {
|
||||
if (StringBufferLength() == 0) {
|
||||
aString.Truncate();
|
||||
} else {
|
||||
StringBuffer()->ToString(StringBufferLength(), aString);
|
||||
}
|
||||
} else {
|
||||
aString = AsAString();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// We need to be able to act like a string as needed
|
||||
Maybe<nsAutoString> mString;
|
||||
|
||||
// For callees that know we exist, we can be a stringbuffer/length/null-flag
|
||||
// triple.
|
||||
nsStringBuffer* mStringBuffer;
|
||||
uint32_t mLength;
|
||||
bool mIsNull;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_DOMString_h
|
@ -81,11 +81,6 @@ public:
|
||||
return !Equals(aOtherNullable);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return !mIsNull;
|
||||
}
|
||||
|
||||
// Make it possible to use a const Nullable of an array type with other
|
||||
// array types.
|
||||
template<typename U>
|
||||
|
@ -19,6 +19,7 @@ EXPORTS.mozilla.dom += [
|
||||
'CallbackObject.h',
|
||||
'DOMJSClass.h',
|
||||
'DOMJSProxyHandler.h',
|
||||
'DOMString.h',
|
||||
'Date.h',
|
||||
'Errors.msg',
|
||||
'Exceptions.h',
|
||||
|
@ -401,12 +401,7 @@ class IDLObjectWithIdentifier(IDLObject):
|
||||
if isDictionaryMember:
|
||||
raise WebIDLError("[TreatUndefinedAs] is not allowed for "
|
||||
"dictionary members", [self.location])
|
||||
if value == 'Missing':
|
||||
if not isOptional:
|
||||
raise WebIDLError("[TreatUndefinedAs=Missing] is only "
|
||||
"allowed on optional arguments",
|
||||
[self.location])
|
||||
elif value == 'Null':
|
||||
if value == 'Null':
|
||||
if not self.type.isDOMString():
|
||||
raise WebIDLError("[TreatUndefinedAs=Null] is only "
|
||||
"allowed on arguments or "
|
||||
@ -426,8 +421,8 @@ class IDLObjectWithIdentifier(IDLObject):
|
||||
[self.location])
|
||||
else:
|
||||
raise WebIDLError("[TreatUndefinedAs] must take the "
|
||||
"identifiers EmptyString or Null or "
|
||||
"Missing", [self.location])
|
||||
"identifiers EmptyString or Null",
|
||||
[self.location])
|
||||
self.treatUndefinedAs = value
|
||||
else:
|
||||
unhandledAttrs.append(attr)
|
||||
@ -3143,15 +3138,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
|
||||
def finish(self, scope):
|
||||
for overload in self._overloads:
|
||||
inOptionalArguments = False
|
||||
variadicArgument = None
|
||||
|
||||
arguments = overload.arguments
|
||||
for (idx, argument) in enumerate(arguments):
|
||||
if argument.isComplete():
|
||||
continue
|
||||
|
||||
argument.complete(scope)
|
||||
if not argument.isComplete():
|
||||
argument.complete(scope)
|
||||
assert argument.type.isComplete()
|
||||
|
||||
if (argument.type.isDictionary() or
|
||||
@ -3161,7 +3153,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
# end of the list or followed by optional arguments must be
|
||||
# optional.
|
||||
if (not argument.optional and
|
||||
(idx == len(arguments) - 1 or arguments[idx+1].optional)):
|
||||
all(arg.optional for arg in arguments[idx+1:])):
|
||||
raise WebIDLError("Dictionary argument or union "
|
||||
"argument containing a dictionary "
|
||||
"not followed by a required argument "
|
||||
@ -3179,13 +3171,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Variadic argument is not last argument",
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Non-optional argument after optional "
|
||||
"arguments",
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
if argument.variadic:
|
||||
variadicArgument = argument
|
||||
|
||||
@ -3230,7 +3215,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
return [overload for overload in self._overloads if
|
||||
len(overload.arguments) == argc or
|
||||
(len(overload.arguments) > argc and
|
||||
overload.arguments[argc].optional) or
|
||||
all(arg.optional for arg in overload.arguments[argc:])) or
|
||||
(len(overload.arguments) < argc and
|
||||
len(overload.arguments) > 0 and
|
||||
overload.arguments[-1].variadic)]
|
||||
@ -4060,21 +4045,6 @@ class Parser(Tokenizer):
|
||||
raise WebIDLError("stringifier must have DOMString return type",
|
||||
[self.getLocation(p, 2)])
|
||||
|
||||
inOptionalArguments = False
|
||||
variadicArgument = False
|
||||
for argument in arguments:
|
||||
# Only the last argument can be variadic
|
||||
if variadicArgument:
|
||||
raise WebIDLError("Only the last argument can be variadic",
|
||||
[variadicArgument.location])
|
||||
# Once we see an optional argument, there can't be any non-optional
|
||||
# arguments.
|
||||
if inOptionalArguments and not argument.optional:
|
||||
raise WebIDLError("Cannot have a non-optional argument following an optional argument",
|
||||
[argument.location])
|
||||
inOptionalArguments = argument.optional
|
||||
variadicArgument = argument if argument.variadic else None
|
||||
|
||||
# identifier might be None. This is only permitted for special methods.
|
||||
if not identifier:
|
||||
if not getter and not setter and not creator and \
|
||||
|
@ -171,6 +171,23 @@ def WebIDLTest(parser, harness):
|
||||
|
||||
harness.ok(threw, "Dictionary arg followed by optional arg must be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
dictionary A {
|
||||
};
|
||||
interface X {
|
||||
void doFoo(A arg1, optional long arg2, long arg3);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(not threw,
|
||||
"Dictionary arg followed by non-optional arg doesn't have to be optional")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
|
@ -11,9 +11,9 @@ def WebIDLTest(parser, harness):
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw,
|
||||
"Should have thrown on non-optional argument following optional "
|
||||
"argument.")
|
||||
harness.ok(not threw,
|
||||
"Should not have thrown on non-optional argument following "
|
||||
"optional argument.")
|
||||
|
||||
parser = parser.reset()
|
||||
parser.parse("""
|
||||
|
@ -11,6 +11,8 @@ def WebIDLTest(parser, harness):
|
||||
void withVariadics(long... numbers);
|
||||
void withVariadics(TestOverloads iface);
|
||||
void withVariadics(long num, TestOverloads iface);
|
||||
void optionalTest();
|
||||
void optionalTest(optional long num1, long num2);
|
||||
};
|
||||
""")
|
||||
|
||||
@ -23,7 +25,7 @@ def WebIDLTest(parser, harness):
|
||||
"Should be an IDLInterface")
|
||||
harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
|
||||
harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
|
||||
harness.check(len(iface.members), 3, "Expect %s members" % 3)
|
||||
harness.check(len(iface.members), 4, "Expect %s members" % 4)
|
||||
|
||||
member = iface.members[0]
|
||||
harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
|
||||
@ -48,3 +50,11 @@ def WebIDLTest(parser, harness):
|
||||
harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
|
||||
harness.check(argument.identifier.name, "arg1", "Argument has the right name")
|
||||
harness.check(str(argument.type), "Long", "Argument has the right type")
|
||||
|
||||
member = iface.members[3]
|
||||
harness.check(len(member.overloadsForArgCount(0)), 1,
|
||||
"Only one overload for no args")
|
||||
harness.check(len(member.overloadsForArgCount(1)), 0,
|
||||
"No overloads for one arg")
|
||||
harness.check(len(member.overloadsForArgCount(2)), 1,
|
||||
"Only one overload for two args")
|
||||
|
@ -1,51 +1,62 @@
|
||||
def WebIDLTest(parser, harness):
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
parser.parse("""
|
||||
interface VariadicConstraints1 {
|
||||
void foo(byte... arg1, byte arg2);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument followed by required "
|
||||
"argument.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
parser.parse("""
|
||||
interface VariadicConstraints2 {
|
||||
void foo(byte... arg1, optional byte arg2);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish();
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument followed by optional "
|
||||
"argument.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
parser.parse("""
|
||||
interface VariadicConstraints3 {
|
||||
void foo(optional byte... arg1);
|
||||
};
|
||||
""")
|
||||
results = parser.finish()
|
||||
|
||||
except:
|
||||
threw = True
|
||||
|
||||
harness.ok(threw, "Should have thrown.")
|
||||
harness.ok(threw,
|
||||
"Should have thrown on variadic argument explicitly flagged as "
|
||||
"optional.")
|
||||
|
||||
parser = parser.reset()
|
||||
threw = False
|
||||
try:
|
||||
results = parser.parse("""
|
||||
parser.parse("""
|
||||
interface VariadicConstraints4 {
|
||||
void foo(byte... arg1 = 0);
|
||||
};
|
||||
""")
|
||||
|
||||
results = parser.finish()
|
||||
except:
|
||||
threw = True
|
||||
|
||||
|
@ -161,9 +161,9 @@ public:
|
||||
void PassByte(int8_t);
|
||||
int8_t ReceiveByte();
|
||||
void PassOptionalByte(const Optional<int8_t>&);
|
||||
void PassOptionalUndefinedMissingByte(const Optional<int8_t>&);
|
||||
void PassOptionalByteBeforeRequired(const Optional<int8_t>&, int8_t);
|
||||
void PassOptionalByteWithDefault(int8_t);
|
||||
void PassOptionalUndefinedMissingByteWithDefault(int8_t);
|
||||
void PassOptionalByteWithDefaultBeforeRequired(int8_t, int8_t);
|
||||
void PassNullableByte(const Nullable<int8_t>&);
|
||||
void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
|
||||
void PassVariadicByte(const Sequence<int8_t>&);
|
||||
@ -410,9 +410,7 @@ public:
|
||||
void PassString(const nsAString&);
|
||||
void PassNullableString(const nsAString&);
|
||||
void PassOptionalString(const Optional<nsAString>&);
|
||||
void PassOptionalUndefinedMissingString(const Optional<nsAString>&);
|
||||
void PassOptionalStringWithDefaultValue(const nsAString&);
|
||||
void PassOptionalUndefinedMissingStringWithDefaultValue(const nsAString&);
|
||||
void PassOptionalNullableString(const Optional<nsAString>&);
|
||||
void PassOptionalNullableStringWithDefaultValue(const nsAString&);
|
||||
void PassVariadicString(const Sequence<nsString>&);
|
||||
@ -631,6 +629,22 @@ public:
|
||||
void Overload7(const nsCString&);
|
||||
void Overload8(int32_t);
|
||||
void Overload8(TestInterface&);
|
||||
void Overload9(const Nullable<int32_t>&);
|
||||
void Overload9(const nsAString&);
|
||||
void Overload10(const Nullable<int32_t>&);
|
||||
void Overload10(JSContext*, JS::Handle<JSObject*>);
|
||||
void Overload11(int32_t);
|
||||
void Overload11(const nsAString&);
|
||||
void Overload12(int32_t);
|
||||
void Overload12(const Nullable<bool>&);
|
||||
void Overload13(const Nullable<int32_t>&);
|
||||
void Overload13(bool);
|
||||
void Overload14(const Optional<int32_t>&);
|
||||
void Overload14(TestInterface&);
|
||||
void Overload15(int32_t);
|
||||
void Overload15(const Optional<NonNull<TestInterface> >&);
|
||||
void Overload16(int32_t);
|
||||
void Overload16(const Optional<TestInterface*>&);
|
||||
|
||||
// Variadic handling
|
||||
void PassVariadicThirdArg(const nsAString&, int32_t,
|
||||
|
@ -118,9 +118,9 @@ interface TestInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -365,9 +365,7 @@ interface TestInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -581,6 +579,22 @@ interface TestInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
|
||||
|
@ -23,9 +23,9 @@ interface TestExampleInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -263,9 +263,7 @@ interface TestExampleInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -478,6 +476,22 @@ interface TestExampleInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
|
||||
|
@ -35,9 +35,9 @@ interface TestJSImplInterface {
|
||||
void passByte(byte arg);
|
||||
byte receiveByte();
|
||||
void passOptionalByte(optional byte arg);
|
||||
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
|
||||
void passOptionalByteBeforeRequired(optional byte arg1, byte arg2);
|
||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
|
||||
void passOptionalByteWithDefaultBeforeRequired(optional byte arg1 = 0, byte arg2);
|
||||
void passNullableByte(byte? arg);
|
||||
void passOptionalNullableByte(optional byte? arg);
|
||||
void passVariadicByte(byte... arg);
|
||||
@ -285,9 +285,7 @@ interface TestJSImplInterface {
|
||||
void passString(DOMString arg);
|
||||
void passNullableString(DOMString? arg);
|
||||
void passOptionalString(optional DOMString arg);
|
||||
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
|
||||
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
|
||||
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
|
||||
void passOptionalNullableString(optional DOMString? arg);
|
||||
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
|
||||
void passVariadicString(DOMString... arg);
|
||||
@ -506,6 +504,22 @@ interface TestJSImplInterface {
|
||||
void overload7(ByteString arg);
|
||||
void overload8(long arg);
|
||||
void overload8(TestJSImplInterface arg);
|
||||
void overload9(long? arg);
|
||||
void overload9(DOMString arg);
|
||||
void overload10(long? arg);
|
||||
void overload10(object arg);
|
||||
void overload11(long arg);
|
||||
void overload11(DOMString? arg);
|
||||
void overload12(long arg);
|
||||
void overload12(boolean? arg);
|
||||
void overload13(long? arg);
|
||||
void overload13(boolean arg);
|
||||
void overload14(optional long arg);
|
||||
void overload14(TestInterface arg);
|
||||
void overload15(long arg);
|
||||
void overload15(optional TestInterface arg);
|
||||
void overload16(long arg);
|
||||
void overload16(optional TestInterface? arg);
|
||||
|
||||
// Variadic handling
|
||||
void passVariadicThirdArg(DOMString arg1, long arg2, TestJSImplInterface... arg3);
|
||||
|
@ -18,17 +18,21 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
assert_equals(doc.doctype.systemId, "")
|
||||
assert_equals(doc.documentElement.localName, "html")
|
||||
assert_equals(doc.documentElement.firstChild.localName, "head")
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 1)
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.localName, "title")
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.firstChild.data,
|
||||
expectedtitle)
|
||||
if (title !== undefined) {
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 1)
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.localName, "title")
|
||||
assert_equals(doc.documentElement.firstChild.firstChild.firstChild.data,
|
||||
expectedtitle)
|
||||
} else {
|
||||
assert_equals(doc.documentElement.firstChild.childNodes.length, 0)
|
||||
}
|
||||
assert_equals(doc.documentElement.lastChild.localName, "body")
|
||||
assert_equals(doc.documentElement.lastChild.childNodes.length, 0)
|
||||
})
|
||||
}
|
||||
checkDoc("", "", "")
|
||||
checkDoc(null, "null", "null")
|
||||
checkDoc(undefined, "undefined", "undefined")
|
||||
checkDoc(undefined, "", "")
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
|
||||
|
@ -12,7 +12,7 @@ function checkDoc(title, expectedtitle, normalizedtitle) {
|
||||
}
|
||||
checkDoc("", "", "")
|
||||
checkDoc(null, "null", "null")
|
||||
checkDoc(undefined, "undefined", "undefined")
|
||||
checkDoc(undefined, "", "")
|
||||
checkDoc("foo bar baz", "foo bar baz", "foo bar baz")
|
||||
checkDoc("foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz")
|
||||
checkDoc("foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz")
|
||||
|
@ -2802,7 +2802,7 @@ QuotaManager::FindSynchronizedOp(const nsACString& aPattern,
|
||||
for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
const nsAutoPtr<SynchronizedOp>& currentOp = mSynchronizedOps[index];
|
||||
if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) &&
|
||||
(!currentOp->mPersistenceType ||
|
||||
(currentOp->mPersistenceType.IsNull() ||
|
||||
currentOp->mPersistenceType == aPersistenceType) &&
|
||||
(!currentOp->mId || currentOp->mId == aId)) {
|
||||
return currentOp;
|
||||
@ -3067,7 +3067,7 @@ QuotaManager::CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||
uint32_t index;
|
||||
for (index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (!op->mPersistenceType ||
|
||||
if (op->mPersistenceType.IsNull() ||
|
||||
op->mPersistenceType.Value() == PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (op->mOriginOrPattern.IsPattern() &&
|
||||
!originCollection.ContainsPattern(op->mOriginOrPattern)) {
|
||||
@ -3078,7 +3078,7 @@ QuotaManager::CollectOriginsForEviction(uint64_t aMinSizeToBeFreed,
|
||||
|
||||
for (index = 0; index < mSynchronizedOps.Length(); index++) {
|
||||
nsAutoPtr<SynchronizedOp>& op = mSynchronizedOps[index];
|
||||
if (!op->mPersistenceType ||
|
||||
if (op->mPersistenceType.IsNull() ||
|
||||
op->mPersistenceType.Value() == PERSISTENCE_TYPE_TEMPORARY) {
|
||||
if (op->mOriginOrPattern.IsOrigin() &&
|
||||
!originCollection.ContainsOrigin(op->mOriginOrPattern)) {
|
||||
|
@ -74,7 +74,7 @@ interface CanvasRenderingContext2D {
|
||||
|
||||
// path API (see also CanvasPathMethods)
|
||||
void beginPath();
|
||||
void fill([TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
void fill(optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED void fill(Path path);
|
||||
void stroke();
|
||||
// NOT IMPLEMENTED void stroke(Path path);
|
||||
@ -84,10 +84,10 @@ interface CanvasRenderingContext2D {
|
||||
// NOT IMPLEMENTED boolean drawCustomFocusRing(Path path, Element element);
|
||||
// NOT IMPLEMENTED void scrollPathIntoView();
|
||||
// NOT IMPLEMENTED void scrollPathIntoView(Path path);
|
||||
void clip([TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
void clip(optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED void clip(Path path);
|
||||
// NOT IMPLEMENTED void resetClip();
|
||||
boolean isPointInPath(unrestricted double x, unrestricted double y, [TreatUndefinedAs=Missing] optional CanvasWindingRule winding = "nonzero");
|
||||
boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasWindingRule winding = "nonzero");
|
||||
// NOT IMPLEMENTED boolean isPointInPath(Path path, unrestricted double x, unrestricted double y);
|
||||
boolean isPointInStroke(double x, double y);
|
||||
|
||||
|
@ -27,22 +27,22 @@ interface Notification : EventTarget {
|
||||
|
||||
attribute EventHandler onclose;
|
||||
|
||||
[Constant]
|
||||
[Pure]
|
||||
readonly attribute DOMString title;
|
||||
|
||||
[Constant]
|
||||
[Pure]
|
||||
readonly attribute NotificationDirection dir;
|
||||
|
||||
[Constant]
|
||||
[Pure]
|
||||
readonly attribute DOMString? lang;
|
||||
|
||||
[Constant]
|
||||
[Pure]
|
||||
readonly attribute DOMString? body;
|
||||
|
||||
[Constant]
|
||||
readonly attribute DOMString? tag;
|
||||
|
||||
[Constant]
|
||||
[Pure]
|
||||
readonly attribute DOMString? icon;
|
||||
|
||||
void close();
|
||||
|
@ -28,9 +28,9 @@ interface Promise {
|
||||
static Promise reject(any value);
|
||||
|
||||
[Creator]
|
||||
Promise then([TreatUndefinedAs=Missing] optional AnyCallback fulfillCallback,
|
||||
[TreatUndefinedAs=Missing] optional AnyCallback rejectCallback);
|
||||
Promise then(optional AnyCallback fulfillCallback,
|
||||
optional AnyCallback rejectCallback);
|
||||
|
||||
[Creator]
|
||||
Promise catch([TreatUndefinedAs=Missing] optional AnyCallback rejectCallback);
|
||||
Promise catch(optional AnyCallback rejectCallback);
|
||||
};
|
||||
|
@ -71,7 +71,9 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
|
||||
|
||||
// request
|
||||
[Throws]
|
||||
void open(ByteString method, DOMString url, optional boolean async = true,
|
||||
void open(ByteString method, DOMString url);
|
||||
[Throws]
|
||||
void open(ByteString method, DOMString url, boolean async,
|
||||
optional DOMString? user, optional DOMString? password);
|
||||
[Throws]
|
||||
void setRequestHeader(ByteString header, ByteString value);
|
||||
|
@ -121,6 +121,11 @@ public:
|
||||
return mStateData.mReadyState;
|
||||
}
|
||||
|
||||
void Open(const nsACString& aMethod, const nsAString& aUrl, ErrorResult& aRv)
|
||||
{
|
||||
Open(aMethod, aUrl, true, Optional<nsAString>(),
|
||||
Optional<nsAString>(), aRv);
|
||||
}
|
||||
void
|
||||
Open(const nsACString& aMethod, const nsAString& aUrl, bool aAsync,
|
||||
const Optional<nsAString>& aUser, const Optional<nsAString>& aPassword,
|
||||
|
@ -62,8 +62,7 @@ NS_IMETHODIMP InsertElementTxn::DoTransaction(void)
|
||||
{
|
||||
nsCOMPtr<nsIContent>nodeAsContent = do_QueryInterface(mNode);
|
||||
nsCOMPtr<nsIContent>parentAsContent = do_QueryInterface(mParent);
|
||||
nsString namestr;
|
||||
mNode->GetNodeName(namestr);
|
||||
nsString namestr = mNode->NodeName();
|
||||
char* nodename = ToNewCString(namestr);
|
||||
printf("%p Do Insert Element of %p <%s> into parent %p at offset %d\n",
|
||||
static_cast<void*>(this),
|
||||
|
@ -269,12 +269,12 @@ void
|
||||
PathCairo::AppendPathToBuilder(PathBuilderCairo *aBuilder, const Matrix *aTransform) const
|
||||
{
|
||||
if (aTransform) {
|
||||
int i = 0;
|
||||
size_t i = 0;
|
||||
while (i < mPathData.size()) {
|
||||
uint32_t pointCount = mPathData[i].header.length - 1;
|
||||
aBuilder->mPathData.push_back(mPathData[i]);
|
||||
i++;
|
||||
for (int c = 0; c < pointCount; c++) {
|
||||
for (uint32_t c = 0; c < pointCount; c++) {
|
||||
cairo_path_data_t data;
|
||||
Point newPoint = *aTransform * Point(mPathData[i].point.x, mPathData[i].point.y);
|
||||
data.point.x = newPoint.x;
|
||||
@ -284,7 +284,7 @@ PathCairo::AppendPathToBuilder(PathBuilderCairo *aBuilder, const Matrix *aTransf
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < mPathData.size(); i++) {
|
||||
for (size_t i = 0; i < mPathData.size(); i++) {
|
||||
aBuilder->mPathData.push_back(mPathData[i]);
|
||||
}
|
||||
}
|
||||
|
@ -61,12 +61,12 @@ struct InefficientNonFlatteningStringHashPolicy
|
||||
#define ZERO_SIZE(gc, mSize) mSize(0),
|
||||
#define COPY_OTHER_SIZE(gc, mSize) mSize(other.mSize),
|
||||
#define ADD_OTHER_SIZE(gc, mSize) mSize += other.mSize;
|
||||
#define ADD_SIZE_TO_N_IF_LIVE_GC_THING(gc, mSize) n += (gc == js::IsLiveGCThing) ? mSize : 0;
|
||||
#define ADD_SIZE_TO_N_IF_LIVE_GC_THING(gc, mSize) n += (gc) ? mSize : 0;
|
||||
|
||||
// Used to annotate which size_t fields measure live GC things and which don't.
|
||||
enum {
|
||||
IsLiveGCThing,
|
||||
NotLiveGCThing
|
||||
NotLiveGCThing = false,
|
||||
IsLiveGCThing = true
|
||||
};
|
||||
|
||||
struct ZoneStatsPod
|
||||
|
@ -352,7 +352,6 @@ DEFINES += -DSTATIC_EXPORTABLE_JS_API
|
||||
endif
|
||||
endif
|
||||
|
||||
# Flags passed to JarMaker.py
|
||||
MAKE_JARS_FLAGS = \
|
||||
-t $(topsrcdir) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
|
@ -1451,10 +1451,10 @@ endif
|
||||
endif
|
||||
|
||||
libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
|
||||
$(call py_action,jar_maker,\
|
||||
$(QUIET) -j $(FINAL_TARGET)/chrome \
|
||||
$(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
|
||||
$(JAR_MANIFEST)
|
||||
$(JAR_MANIFEST))
|
||||
|
||||
endif
|
||||
endif
|
||||
|
@ -454,6 +454,8 @@ frontend::CompileLazyFunction(JSContext *cx, LazyScript *lazy, const jschar *cha
|
||||
script->directlyInsideEval = true;
|
||||
if (lazy->usesArgumentsAndApply())
|
||||
script->usesArgumentsAndApply = true;
|
||||
if (lazy->hasBeenCloned())
|
||||
script->hasBeenCloned = true;
|
||||
|
||||
BytecodeEmitter bce(/* parent = */ nullptr, &parser, pn->pn_funbox, script, options.forEval,
|
||||
/* evalCaller = */ NullPtr(), /* hasGlobalScope = */ true,
|
||||
@ -461,6 +463,9 @@ frontend::CompileLazyFunction(JSContext *cx, LazyScript *lazy, const jschar *cha
|
||||
if (!bce.init())
|
||||
return false;
|
||||
|
||||
if (lazy->treatAsRunOnce())
|
||||
bce.lazyRunOnceLambda = true;
|
||||
|
||||
return EmitFunctionScript(cx, &bce, pn->pn_body);
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter *parent,
|
||||
hasSingletons(false),
|
||||
emittingForInit(false),
|
||||
emittingRunOnceLambda(false),
|
||||
lazyRunOnceLambda(false),
|
||||
insideEval(insideEval),
|
||||
hasGlobalScope(hasGlobalScope),
|
||||
emitterMode(emitterMode)
|
||||
@ -2666,10 +2667,11 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
||||
* the script ends up running multiple times via foo.caller related
|
||||
* shenanigans.
|
||||
*/
|
||||
bool runOnce = bce->parent &&
|
||||
bce->parent->emittingRunOnceLambda &&
|
||||
bool runOnce =
|
||||
bce->isRunOnceLambda() &&
|
||||
!funbox->argumentsHasLocalBinding() &&
|
||||
!funbox->isGenerator();
|
||||
!funbox->isGenerator() &&
|
||||
!funbox->function()->name();
|
||||
if (runOnce) {
|
||||
bce->switchToProlog();
|
||||
if (Emit1(cx, bce, JSOP_RUNONCE) < 0)
|
||||
@ -4788,9 +4790,7 @@ EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
bce->script->compileAndGo &&
|
||||
fun->isInterpreted() &&
|
||||
(bce->checkSingletonContext() ||
|
||||
(!bce->isInLoop() &&
|
||||
bce->parent &&
|
||||
bce->parent->emittingRunOnceLambda));
|
||||
(!bce->isInLoop() && bce->isRunOnceLambda()));
|
||||
if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
|
||||
return false;
|
||||
|
||||
@ -4801,6 +4801,8 @@ EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
scope = bce->sc->asFunctionBox()->function();
|
||||
fun->lazyScript()->setParent(scope, bce->script->sourceObject());
|
||||
}
|
||||
if (bce->emittingRunOnceLambda)
|
||||
fun->lazyScript()->setTreatAsRunOnce();
|
||||
} else {
|
||||
SharedContext *outersc = bce->sc;
|
||||
|
||||
|
@ -124,6 +124,12 @@ struct BytecodeEmitter
|
||||
|
||||
bool emittingRunOnceLambda:1; /* true while emitting a lambda which is only
|
||||
expected to run once. */
|
||||
bool lazyRunOnceLambda:1; /* true while lazily emitting a script for
|
||||
* a lambda which is only expected to run once. */
|
||||
|
||||
bool isRunOnceLambda() {
|
||||
return (parent && parent->emittingRunOnceLambda) || lazyRunOnceLambda;
|
||||
}
|
||||
|
||||
bool insideEval:1; /* True if compiling an eval-expression or a function
|
||||
nested inside an eval. */
|
||||
|
@ -122,25 +122,6 @@ StoreBuffer::MonoTypeBuffer<T>::mark(JSTracer *trc)
|
||||
}
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
class AccumulateEdgesTracer : public JSTracer
|
||||
{
|
||||
EdgeSet *edges;
|
||||
|
||||
static void tracer(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) {
|
||||
AccumulateEdgesTracer *trc = static_cast<AccumulateEdgesTracer *>(jstrc);
|
||||
trc->edges->put(thingp);
|
||||
}
|
||||
|
||||
public:
|
||||
AccumulateEdgesTracer(JSRuntime *rt, EdgeSet *edgesArg) : edges(edgesArg) {
|
||||
JS_TracerInit(this, rt, AccumulateEdgesTracer::tracer);
|
||||
}
|
||||
};
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
/*** RelocatableMonoTypeBuffer ***/
|
||||
|
||||
template <typename T>
|
||||
|
@ -25,8 +25,6 @@
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
class AccumulateEdgesTracer;
|
||||
|
||||
/*
|
||||
* BufferableRef represents an abstract reference for use in the generational
|
||||
* GC's remembered set. Entries in the store buffer that cannot be represented
|
||||
|
@ -2731,8 +2731,10 @@ CanAttachNativeSetProp(HandleObject obj, HandleId id, ConstantOrRegister val,
|
||||
return SetPropertyIC::CanAttachNone;
|
||||
|
||||
// If the object doesn't have the property, we don't know if we can attach
|
||||
// a stub to add the property until we do the VM call to add.
|
||||
if (!shape)
|
||||
// a stub to add the property until we do the VM call to add. If the
|
||||
// property exists as a data property on the prototype, we should add
|
||||
// a new, shadowing property.
|
||||
if (!shape || (obj != holder && shape->hasDefaultSetter() && shape->hasSlot()))
|
||||
return SetPropertyIC::MaybeCanAttachAddSlot;
|
||||
|
||||
if (IsCacheableSetPropCallPropertyOp(obj, holder, shape) ||
|
||||
|
@ -2942,6 +2942,7 @@ LazyScript::LazyScript(JSFunction *fun, void *table, uint32_t numFreeVariables,
|
||||
directlyInsideEval_(false),
|
||||
usesArgumentsAndApply_(false),
|
||||
hasBeenCloned_(false),
|
||||
treatAsRunOnce_(false),
|
||||
begin_(begin),
|
||||
end_(end),
|
||||
lineno_(lineno),
|
||||
|
@ -1183,7 +1183,7 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
uint32_t version_ : 8;
|
||||
|
||||
uint32_t numFreeVariables_ : 24;
|
||||
uint32_t numInnerFunctions_ : 24;
|
||||
uint32_t numInnerFunctions_ : 23;
|
||||
|
||||
uint32_t generatorKindBits_:2;
|
||||
|
||||
@ -1194,6 +1194,7 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
uint32_t directlyInsideEval_:1;
|
||||
uint32_t usesArgumentsAndApply_:1;
|
||||
uint32_t hasBeenCloned_:1;
|
||||
uint32_t treatAsRunOnce_:1;
|
||||
|
||||
// Source location for the script.
|
||||
uint32_t begin_;
|
||||
@ -1310,6 +1311,13 @@ class LazyScript : public gc::BarrieredCell<LazyScript>
|
||||
hasBeenCloned_ = true;
|
||||
}
|
||||
|
||||
bool treatAsRunOnce() const {
|
||||
return treatAsRunOnce_;
|
||||
}
|
||||
void setTreatAsRunOnce() {
|
||||
treatAsRunOnce_ = true;
|
||||
}
|
||||
|
||||
ScriptSource *source() const {
|
||||
return sourceObject()->source();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ function run_test()
|
||||
// Test sync XHR sending
|
||||
cu.evalInSandbox('var createXHR = ' + createXHR.toString(), sb);
|
||||
var res = cu.evalInSandbox('var sync = createXHR("4444/simple"); sync.send(null); sync', sb);
|
||||
checkResults(res);
|
||||
do_check_true(checkResults(res));
|
||||
|
||||
// negative test sync XHR sending (to ensure that the xhr do not have chrome caps, see bug 779821)
|
||||
try {
|
||||
|
@ -77,6 +77,22 @@ nsHTMLScrollFrame::nsHTMLScrollFrame(nsIPresShell* aShell, nsStyleContext* aCont
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLScrollFrame::ScrollbarActivityStarted() const
|
||||
{
|
||||
if (mInner.mScrollbarActivity) {
|
||||
mInner.mScrollbarActivity->ActivityStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLScrollFrame::ScrollbarActivityStopped() const
|
||||
{
|
||||
if (mInner.mScrollbarActivity) {
|
||||
mInner.mScrollbarActivity->ActivityStopped();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLScrollFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
{
|
||||
@ -902,6 +918,22 @@ nsXULScrollFrame::nsXULScrollFrame(nsIPresShell* aShell, nsStyleContext* aContex
|
||||
mInner.mClipAllDescendants = aClipAllDescendants;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULScrollFrame::ScrollbarActivityStarted() const
|
||||
{
|
||||
if (mInner.mScrollbarActivity) {
|
||||
mInner.mScrollbarActivity->ActivityStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXULScrollFrame::ScrollbarActivityStopped() const
|
||||
{
|
||||
if (mInner.mScrollbarActivity) {
|
||||
mInner.mScrollbarActivity->ActivityStopped();
|
||||
}
|
||||
}
|
||||
|
||||
nsMargin
|
||||
nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState)
|
||||
{
|
||||
|
@ -520,6 +520,9 @@ public:
|
||||
return mInner.GetScrollbarBox(aVertical);
|
||||
}
|
||||
|
||||
virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE;
|
||||
virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIScrollableFrame
|
||||
virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE {
|
||||
return mInner.GetScrolledFrame();
|
||||
@ -810,6 +813,9 @@ public:
|
||||
return mInner.GetScrollbarBox(aVertical);
|
||||
}
|
||||
|
||||
virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE;
|
||||
virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE;
|
||||
|
||||
// nsIScrollableFrame
|
||||
virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE {
|
||||
return mInner.GetScrolledFrame();
|
||||
|
@ -23,6 +23,13 @@ public:
|
||||
* if there is no such box.
|
||||
*/
|
||||
virtual nsIFrame* GetScrollbarBox(bool aVertical) = 0;
|
||||
|
||||
/**
|
||||
* Show or hide scrollbars on 2 fingers touch.
|
||||
* Subclasses should call their ScrollbarActivity's corresponding methods.
|
||||
*/
|
||||
virtual void ScrollbarActivityStarted() const = 0;
|
||||
virtual void ScrollbarActivityStopped() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -8,4 +8,5 @@ MODULE = 'layout'
|
||||
|
||||
LIBRARY_NAME = 'gkmedias'
|
||||
|
||||
DIRS += ['webrtc']
|
||||
if CONFIG['MOZ_WEBRTC']:
|
||||
DIRS += ['webrtc']
|
||||
|
@ -4495,6 +4495,22 @@ nsTreeBodyFrame::PostScrollEvent()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::ScrollbarActivityStarted() const
|
||||
{
|
||||
if (mScrollbarActivity) {
|
||||
mScrollbarActivity->ActivityStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::ScrollbarActivityStopped() const
|
||||
{
|
||||
if (mScrollbarActivity) {
|
||||
mScrollbarActivity->ActivityStopped();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::DetachImageListeners()
|
||||
{
|
||||
|
@ -465,6 +465,9 @@ protected:
|
||||
void PostScrollEvent();
|
||||
void FireScrollEvent();
|
||||
|
||||
virtual void ScrollbarActivityStarted() const MOZ_OVERRIDE;
|
||||
virtual void ScrollbarActivityStopped() const MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Clear the pointer to this frame for all nsTreeImageListeners that were
|
||||
* created by this frame.
|
||||
|
55
mach
55
mach
@ -20,31 +20,36 @@ def load_mach(topsrcdir):
|
||||
import mach_bootstrap
|
||||
return mach_bootstrap.bootstrap(topsrcdir)
|
||||
|
||||
# Check whether the current directory is within a mach src or obj dir.
|
||||
for dir_path in ancestors(os.getcwd()):
|
||||
# If we find a "mozinfo.json" file, we are in the objdir.
|
||||
mozinfo_path = os.path.join(dir_path, "mozinfo.json")
|
||||
if os.path.isfile(mozinfo_path):
|
||||
import json
|
||||
info = json.load(open(mozinfo_path))
|
||||
if "mozconfig" in info and "MOZCONFIG" not in os.environ:
|
||||
# If the MOZCONFIG environment variable is not already set, set it
|
||||
# to the value from mozinfo.json. This will tell the build system
|
||||
# to look for a config file at the path in $MOZCONFIG rather than
|
||||
# its default locations.
|
||||
#
|
||||
# Note: subprocess requires native strings in os.environ on Windows
|
||||
os.environ[b"MOZCONFIG"] = str(info["mozconfig"])
|
||||
def main(args):
|
||||
# Check whether the current directory is within a mach src or obj dir.
|
||||
for dir_path in ancestors(os.getcwd()):
|
||||
# If we find a "mozinfo.json" file, we are in the objdir.
|
||||
mozinfo_path = os.path.join(dir_path, 'mozinfo.json')
|
||||
if os.path.isfile(mozinfo_path):
|
||||
import json
|
||||
info = json.load(open(mozinfo_path))
|
||||
if 'mozconfig' in info and 'MOZCONFIG' not in os.environ:
|
||||
# If the MOZCONFIG environment variable is not already set, set it
|
||||
# to the value from mozinfo.json. This will tell the build system
|
||||
# to look for a config file at the path in $MOZCONFIG rather than
|
||||
# its default locations.
|
||||
#
|
||||
# Note: subprocess requires native strings in os.environ on Windows
|
||||
os.environ[b'MOZCONFIG'] = str(info['mozconfig'])
|
||||
|
||||
if "topsrcdir" in info:
|
||||
# Continue searching for mach_bootstrap in the source directory.
|
||||
dir_path = info["topsrcdir"]
|
||||
if 'topsrcdir' in info:
|
||||
# Continue searching for mach_bootstrap in the source directory.
|
||||
dir_path = info['topsrcdir']
|
||||
|
||||
# If we find the mach bootstrap module, we are in the srcdir.
|
||||
mach_path = os.path.join(dir_path, "build/mach_bootstrap.py")
|
||||
if os.path.isfile(mach_path):
|
||||
mach = load_mach(dir_path)
|
||||
sys.exit(mach.run(sys.argv[1:]))
|
||||
# If we find the mach bootstrap module, we are in the srcdir.
|
||||
mach_path = os.path.join(dir_path, 'build/mach_bootstrap.py')
|
||||
if os.path.isfile(mach_path):
|
||||
mach = load_mach(dir_path)
|
||||
sys.exit(mach.run(args[1:]))
|
||||
|
||||
print("Could not run mach: No mach source directory found")
|
||||
sys.exit(1)
|
||||
print('Could not run mach: No mach source directory found.')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
|
@ -20,12 +20,6 @@ include $(topsrcdir)/config/makefiles/makeutils.mk
|
||||
# Separate items of contention
|
||||
tgt-gendir = .deps/generated_$(AB_CD)
|
||||
|
||||
jar-maker = \
|
||||
$(firstword \
|
||||
$(wildcard $(MOZILLA_DIR)/config/JarMaker.py) \
|
||||
$(topsrcdir)/config/JarMaker.py \
|
||||
)
|
||||
|
||||
GENERATED_DIRS += .deps
|
||||
|
||||
ifdef LOCALE_MERGEDIR
|
||||
@ -130,18 +124,17 @@ search-preqs =\
|
||||
$(call mkdir_deps,$(FINAL_TARGET)/chrome) \
|
||||
$(search-jar) \
|
||||
$(search-dir-deps) \
|
||||
$(jar-maker) \
|
||||
$(if $(IS_LANGUAGE_REPACK),FORCE) \
|
||||
$(GLOBAL_DEPS) \
|
||||
$(NULL)
|
||||
|
||||
.PHONY: searchplugins
|
||||
searchplugins: $(search-preqs)
|
||||
$(PYTHON) $(jar-maker) \
|
||||
$(call py_action,jar_maker,\
|
||||
$(QUIET) -j $(FINAL_TARGET)/chrome \
|
||||
-s $(topsrcdir)/$(relativesrcdir)/en-US/searchplugins \
|
||||
-s $(LOCALE_SRCDIR)/searchplugins \
|
||||
$(MAKE_JARS_FLAGS) $(search-jar)
|
||||
$(MAKE_JARS_FLAGS) $(search-jar))
|
||||
$(TOUCH) $@
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -7,9 +7,8 @@ from __future__ import unicode_literals
|
||||
|
||||
class CommandContext(object):
|
||||
"""Holds run-time state so it can easily be passed to command providers."""
|
||||
def __init__(self, topdir=None, cwd=None, settings=None, log_manager=None,
|
||||
def __init__(self, cwd=None, settings=None, log_manager=None,
|
||||
commands=None):
|
||||
self.topdir = topdir
|
||||
self.cwd = cwd
|
||||
self.settings = settings
|
||||
self.log_manager = log_manager
|
||||
|
@ -145,6 +145,7 @@ class CommandAction(argparse.Action):
|
||||
# arguments corresponding to command names. This has the side-effect
|
||||
# that argparse renders it nicely.
|
||||
r = self._mach_registrar
|
||||
disabled_commands = []
|
||||
|
||||
cats = [(k, v[2]) for k, v in r.categories.items()]
|
||||
sorted_cats = sorted(cats, key=itemgetter(1), reverse=True)
|
||||
@ -169,6 +170,9 @@ class CommandAction(argparse.Action):
|
||||
is_filtered = True
|
||||
break
|
||||
if is_filtered:
|
||||
description = handler.description
|
||||
disabled_command = {'command': command, 'description': description}
|
||||
disabled_commands.append(disabled_command)
|
||||
continue
|
||||
|
||||
if group is None:
|
||||
@ -179,6 +183,13 @@ class CommandAction(argparse.Action):
|
||||
group.add_argument(command, help=description,
|
||||
action='store_true')
|
||||
|
||||
if disabled_commands:
|
||||
title, description, _priority = r.categories['disabled']
|
||||
group = parser.add_argument_group(title, description)
|
||||
for c in disabled_commands:
|
||||
group.add_argument(c['command'], help=c['description'],
|
||||
action='store_true')
|
||||
|
||||
parser.print_help()
|
||||
|
||||
def _handle_subcommand_help(self, parser, command):
|
||||
|
@ -289,7 +289,7 @@ To see more help for a specific command, run:
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
def _run(self, argv):
|
||||
context = CommandContext(topdir=self.cwd, cwd=self.cwd,
|
||||
context = CommandContext(cwd=self.cwd,
|
||||
settings=self.settings, log_manager=self.log_manager,
|
||||
commands=Registrar)
|
||||
|
||||
|
15
python/mozbuild/mozbuild/action/jar_maker.py
Normal file
15
python/mozbuild/mozbuild/action/jar_maker.py
Normal file
@ -0,0 +1,15 @@
|
||||
# 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/.
|
||||
|
||||
import sys
|
||||
|
||||
import mozbuild.jar
|
||||
|
||||
|
||||
def main(args):
|
||||
return mozbuild.jar.main(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
@ -172,11 +172,13 @@ class MozbuildObject(ProcessExecutionMixin):
|
||||
# inside an objdir you probably want to perform actions on that objdir,
|
||||
# not another one. This prevents accidental usage of the wrong objdir
|
||||
# when the current objdir is ambiguous.
|
||||
if topobjdir and config_topobjdir \
|
||||
and not samepath(topobjdir, config_topobjdir) \
|
||||
and not samepath(topobjdir, os.path.join(config_topobjdir, "mozilla")):
|
||||
if topobjdir and config_topobjdir:
|
||||
mozilla_dir = os.path.join(config_topobjdir, 'mozilla')
|
||||
if not samepath(topobjdir, config_topobjdir) \
|
||||
and (os.path.exists(mozilla_dir) and not samepath(topobjdir,
|
||||
mozilla_dir)):
|
||||
|
||||
raise ObjdirMismatchException(topobjdir, config_topobjdir)
|
||||
raise ObjdirMismatchException(topobjdir, config_topobjdir)
|
||||
|
||||
topobjdir = topobjdir or config_topobjdir
|
||||
if topobjdir:
|
||||
|
537
python/mozbuild/mozbuild/jar.py
Normal file
537
python/mozbuild/mozbuild/jar.py
Normal file
@ -0,0 +1,537 @@
|
||||
# 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/.
|
||||
|
||||
'''jarmaker.py provides a python class to package up chrome content by
|
||||
processing jar.mn files.
|
||||
|
||||
See the documentation for jar.mn on MDC for further details on the format.
|
||||
'''
|
||||
|
||||
import sys
|
||||
import os
|
||||
import errno
|
||||
import re
|
||||
import logging
|
||||
from time import localtime
|
||||
from MozZipFile import ZipFile
|
||||
from cStringIO import StringIO
|
||||
|
||||
from mozbuild.util import (
|
||||
lock_file,
|
||||
PushbackIter,
|
||||
)
|
||||
|
||||
from Preprocessor import Preprocessor
|
||||
from mozbuild.action.buildlist import addEntriesToListFile
|
||||
if sys.platform == 'win32':
|
||||
from ctypes import windll, WinError
|
||||
CreateHardLink = windll.kernel32.CreateHardLinkA
|
||||
|
||||
__all__ = ['JarMaker']
|
||||
|
||||
|
||||
class ZipEntry(object):
|
||||
'''Helper class for jar output.
|
||||
|
||||
This class defines a simple file-like object for a zipfile.ZipEntry
|
||||
so that we can consecutively write to it and then close it.
|
||||
This methods hooks into ZipFile.writestr on close().
|
||||
'''
|
||||
|
||||
def __init__(self, name, zipfile):
|
||||
self._zipfile = zipfile
|
||||
self._name = name
|
||||
self._inner = StringIO()
|
||||
|
||||
def write(self, content):
|
||||
'''Append the given content to this zip entry'''
|
||||
|
||||
self._inner.write(content)
|
||||
return
|
||||
|
||||
def close(self):
|
||||
'''The close method writes the content back to the zip file.'''
|
||||
|
||||
self._zipfile.writestr(self._name, self._inner.getvalue())
|
||||
|
||||
|
||||
def getModTime(aPath):
|
||||
if not os.path.isfile(aPath):
|
||||
return 0
|
||||
mtime = os.stat(aPath).st_mtime
|
||||
return localtime(mtime)
|
||||
|
||||
|
||||
class JarMaker(object):
|
||||
'''JarMaker reads jar.mn files and process those into jar files or
|
||||
flat directories, along with chrome.manifest files.
|
||||
'''
|
||||
|
||||
ignore = re.compile('\s*(\#.*)?$')
|
||||
jarline = re.compile('(?:(?P<jarfile>[\w\d.\-\_\\\/]+).jar\:)|(?:\s*(\#.*)?)\s*$')
|
||||
relsrcline = re.compile('relativesrcdir\s+(?P<relativesrcdir>.+?):')
|
||||
regline = re.compile('\%\s+(.*)$')
|
||||
entryre = '(?P<optPreprocess>\*)?(?P<optOverwrite>\+?)\s+'
|
||||
entryline = re.compile(entryre
|
||||
+ '(?P<output>[\w\d.\-\_\\\/\+\@]+)\s*(\((?P<locale>\%?)(?P<source>[\w\d.\-\_\\\/\@]+)\))?\s*$'
|
||||
)
|
||||
|
||||
def __init__(self, outputFormat='flat', useJarfileManifest=True,
|
||||
useChromeManifest=False):
|
||||
|
||||
self.outputFormat = outputFormat
|
||||
self.useJarfileManifest = useJarfileManifest
|
||||
self.useChromeManifest = useChromeManifest
|
||||
self.pp = Preprocessor()
|
||||
self.topsourcedir = None
|
||||
self.sourcedirs = []
|
||||
self.localedirs = None
|
||||
self.l10nbase = None
|
||||
self.l10nmerge = None
|
||||
self.relativesrcdir = None
|
||||
self.rootManifestAppId = None
|
||||
|
||||
def getCommandLineParser(self):
|
||||
'''Get a optparse.OptionParser for jarmaker.
|
||||
|
||||
This OptionParser has the options for jarmaker as well as
|
||||
the options for the inner PreProcessor.
|
||||
'''
|
||||
|
||||
# HACK, we need to unescape the string variables we get,
|
||||
# the perl versions didn't grok strings right
|
||||
|
||||
p = self.pp.getCommandLineParser(unescapeDefines=True)
|
||||
p.add_option('-f', type='choice', default='jar',
|
||||
choices=('jar', 'flat', 'symlink'),
|
||||
help='fileformat used for output',
|
||||
metavar='[jar, flat, symlink]',
|
||||
)
|
||||
p.add_option('-v', action='store_true', dest='verbose',
|
||||
help='verbose output')
|
||||
p.add_option('-q', action='store_false', dest='verbose',
|
||||
help='verbose output')
|
||||
p.add_option('-e', action='store_true',
|
||||
help='create chrome.manifest instead of jarfile.manifest'
|
||||
)
|
||||
p.add_option('--both-manifests', action='store_true',
|
||||
dest='bothManifests',
|
||||
help='create chrome.manifest and jarfile.manifest')
|
||||
p.add_option('-s', type='string', action='append', default=[],
|
||||
help='source directory')
|
||||
p.add_option('-t', type='string', help='top source directory')
|
||||
p.add_option('-c', '--l10n-src', type='string', action='append'
|
||||
, help='localization directory')
|
||||
p.add_option('--l10n-base', type='string', action='store',
|
||||
help='base directory to be used for localization (requires relativesrcdir)'
|
||||
)
|
||||
p.add_option('--locale-mergedir', type='string', action='store'
|
||||
,
|
||||
help='base directory to be used for l10n-merge (requires l10n-base and relativesrcdir)'
|
||||
)
|
||||
p.add_option('--relativesrcdir', type='string',
|
||||
help='relativesrcdir to be used for localization')
|
||||
p.add_option('-j', type='string', help='jarfile directory')
|
||||
p.add_option('--root-manifest-entry-appid', type='string',
|
||||
help='add an app id specific root chrome manifest entry.'
|
||||
)
|
||||
return p
|
||||
|
||||
def processIncludes(self, includes):
|
||||
'''Process given includes with the inner PreProcessor.
|
||||
|
||||
Only use this for #defines, the includes shouldn't generate
|
||||
content.
|
||||
'''
|
||||
|
||||
self.pp.out = StringIO()
|
||||
for inc in includes:
|
||||
self.pp.do_include(inc)
|
||||
includesvalue = self.pp.out.getvalue()
|
||||
if includesvalue:
|
||||
logging.info('WARNING: Includes produce non-empty output')
|
||||
self.pp.out = None
|
||||
|
||||
def finalizeJar(self, jarPath, chromebasepath, register, doZip=True):
|
||||
'''Helper method to write out the chrome registration entries to
|
||||
jarfile.manifest or chrome.manifest, or both.
|
||||
|
||||
The actual file processing is done in updateManifest.
|
||||
'''
|
||||
|
||||
# rewrite the manifest, if entries given
|
||||
if not register:
|
||||
return
|
||||
|
||||
chromeManifest = os.path.join(os.path.dirname(jarPath), '..',
|
||||
'chrome.manifest')
|
||||
|
||||
if self.useJarfileManifest:
|
||||
self.updateManifest(jarPath + '.manifest',
|
||||
chromebasepath.format(''), register)
|
||||
addEntriesToListFile(chromeManifest,
|
||||
['manifest chrome/{0}.manifest'.format(os.path.basename(jarPath))])
|
||||
if self.useChromeManifest:
|
||||
self.updateManifest(chromeManifest,
|
||||
chromebasepath.format('chrome/'),
|
||||
register)
|
||||
|
||||
# If requested, add a root chrome manifest entry (assumed to be in the parent directory
|
||||
# of chromeManifest) with the application specific id. In cases where we're building
|
||||
# lang packs, the root manifest must know about application sub directories.
|
||||
|
||||
if self.rootManifestAppId:
|
||||
rootChromeManifest = \
|
||||
os.path.join(os.path.normpath(os.path.dirname(chromeManifest)),
|
||||
'..', 'chrome.manifest')
|
||||
rootChromeManifest = os.path.normpath(rootChromeManifest)
|
||||
chromeDir = \
|
||||
os.path.basename(os.path.dirname(os.path.normpath(chromeManifest)))
|
||||
logging.info("adding '%s' entry to root chrome manifest appid=%s"
|
||||
% (chromeDir, self.rootManifestAppId))
|
||||
addEntriesToListFile(rootChromeManifest,
|
||||
['manifest %s/chrome.manifest application=%s'
|
||||
% (chromeDir,
|
||||
self.rootManifestAppId)])
|
||||
|
||||
def updateManifest(self, manifestPath, chromebasepath, register):
|
||||
'''updateManifest replaces the % in the chrome registration entries
|
||||
with the given chrome base path, and updates the given manifest file.
|
||||
'''
|
||||
|
||||
lock = lock_file(manifestPath + '.lck')
|
||||
try:
|
||||
myregister = dict.fromkeys(map(lambda s: s.replace('%',
|
||||
chromebasepath), register.iterkeys()))
|
||||
manifestExists = os.path.isfile(manifestPath)
|
||||
mode = manifestExists and 'r+b' or 'wb'
|
||||
mf = open(manifestPath, mode)
|
||||
if manifestExists:
|
||||
# import previous content into hash, ignoring empty ones and comments
|
||||
imf = re.compile('(#.*)?$')
|
||||
for l in re.split('[\r\n]+', mf.read()):
|
||||
if imf.match(l):
|
||||
continue
|
||||
myregister[l] = None
|
||||
mf.seek(0)
|
||||
for k in myregister.iterkeys():
|
||||
mf.write(k + os.linesep)
|
||||
mf.close()
|
||||
finally:
|
||||
lock = None
|
||||
|
||||
def makeJar(self, infile, jardir):
|
||||
'''makeJar is the main entry point to JarMaker.
|
||||
|
||||
It takes the input file, the output directory, the source dirs and the
|
||||
top source dir as argument, and optionally the l10n dirs.
|
||||
'''
|
||||
|
||||
# making paths absolute, guess srcdir if file and add to sourcedirs
|
||||
_normpath = lambda p: os.path.normpath(os.path.abspath(p))
|
||||
self.topsourcedir = _normpath(self.topsourcedir)
|
||||
self.sourcedirs = [_normpath(p) for p in self.sourcedirs]
|
||||
if self.localedirs:
|
||||
self.localedirs = [_normpath(p) for p in self.localedirs]
|
||||
elif self.relativesrcdir:
|
||||
self.localedirs = \
|
||||
self.generateLocaleDirs(self.relativesrcdir)
|
||||
if isinstance(infile, basestring):
|
||||
logging.info('processing ' + infile)
|
||||
self.sourcedirs.append(_normpath(os.path.dirname(infile)))
|
||||
pp = self.pp.clone()
|
||||
pp.out = StringIO()
|
||||
pp.do_include(infile)
|
||||
lines = PushbackIter(pp.out.getvalue().splitlines())
|
||||
try:
|
||||
while True:
|
||||
l = lines.next()
|
||||
m = self.jarline.match(l)
|
||||
if not m:
|
||||
raise RuntimeError(l)
|
||||
if m.group('jarfile') is None:
|
||||
# comment
|
||||
continue
|
||||
self.processJarSection(m.group('jarfile'), lines,
|
||||
jardir)
|
||||
except StopIteration:
|
||||
# we read the file
|
||||
pass
|
||||
return
|
||||
|
||||
def generateLocaleDirs(self, relativesrcdir):
|
||||
if os.path.basename(relativesrcdir) == 'locales':
|
||||
# strip locales
|
||||
l10nrelsrcdir = os.path.dirname(relativesrcdir)
|
||||
else:
|
||||
l10nrelsrcdir = relativesrcdir
|
||||
locdirs = []
|
||||
|
||||
# generate locales dirs, merge, l10nbase, en-US
|
||||
if self.l10nmerge:
|
||||
locdirs.append(os.path.join(self.l10nmerge, l10nrelsrcdir))
|
||||
if self.l10nbase:
|
||||
locdirs.append(os.path.join(self.l10nbase, l10nrelsrcdir))
|
||||
if self.l10nmerge or not self.l10nbase:
|
||||
# add en-US if we merge, or if it's not l10n
|
||||
locdirs.append(os.path.join(self.topsourcedir,
|
||||
relativesrcdir, 'en-US'))
|
||||
return locdirs
|
||||
|
||||
def processJarSection(self, jarfile, lines, jardir):
|
||||
'''Internal method called by makeJar to actually process a section
|
||||
of a jar.mn file.
|
||||
|
||||
jarfile is the basename of the jarfile or the directory name for
|
||||
flat output, lines is a PushbackIter of the lines of jar.mn,
|
||||
the remaining options are carried over from makeJar.
|
||||
'''
|
||||
|
||||
# chromebasepath is used for chrome registration manifests
|
||||
# {0} is getting replaced with chrome/ for chrome.manifest, and with
|
||||
# an empty string for jarfile.manifest
|
||||
|
||||
chromebasepath = '{0}' + os.path.basename(jarfile)
|
||||
if self.outputFormat == 'jar':
|
||||
chromebasepath = 'jar:' + chromebasepath + '.jar!'
|
||||
chromebasepath += '/'
|
||||
|
||||
jarfile = os.path.join(jardir, jarfile)
|
||||
jf = None
|
||||
if self.outputFormat == 'jar':
|
||||
# jar
|
||||
jarfilepath = jarfile + '.jar'
|
||||
try:
|
||||
os.makedirs(os.path.dirname(jarfilepath))
|
||||
except OSError, error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
jf = ZipFile(jarfilepath, 'a', lock=True)
|
||||
outHelper = self.OutputHelper_jar(jf)
|
||||
else:
|
||||
outHelper = getattr(self, 'OutputHelper_'
|
||||
+ self.outputFormat)(jarfile)
|
||||
register = {}
|
||||
|
||||
# This loop exits on either
|
||||
# - the end of the jar.mn file
|
||||
# - an line in the jar.mn file that's not part of a jar section
|
||||
# - on an exception raised, close the jf in that case in a finally
|
||||
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
l = lines.next()
|
||||
except StopIteration:
|
||||
# we're done with this jar.mn, and this jar section
|
||||
self.finalizeJar(jarfile, chromebasepath, register)
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
|
||||
# reraise the StopIteration for makeJar
|
||||
raise
|
||||
if self.ignore.match(l):
|
||||
continue
|
||||
m = self.relsrcline.match(l)
|
||||
if m:
|
||||
relativesrcdir = m.group('relativesrcdir')
|
||||
self.localedirs = \
|
||||
self.generateLocaleDirs(relativesrcdir)
|
||||
continue
|
||||
m = self.regline.match(l)
|
||||
if m:
|
||||
rline = m.group(1)
|
||||
register[rline] = 1
|
||||
continue
|
||||
m = self.entryline.match(l)
|
||||
if not m:
|
||||
# neither an entry line nor chrome reg, this jar section is done
|
||||
self.finalizeJar(jarfile, chromebasepath, register)
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
lines.pushback(l)
|
||||
return
|
||||
self._processEntryLine(m, outHelper, jf)
|
||||
finally:
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
return
|
||||
|
||||
def _processEntryLine(self, m, outHelper, jf):
|
||||
out = m.group('output')
|
||||
src = m.group('source') or os.path.basename(out)
|
||||
|
||||
# pick the right sourcedir -- l10n, topsrc or src
|
||||
|
||||
if m.group('locale'):
|
||||
src_base = self.localedirs
|
||||
elif src.startswith('/'):
|
||||
# path/in/jar/file_name.xul (/path/in/sourcetree/file_name.xul)
|
||||
# refers to a path relative to topsourcedir, use that as base
|
||||
# and strip the leading '/'
|
||||
src_base = [self.topsourcedir]
|
||||
src = src[1:]
|
||||
else:
|
||||
# use srcdirs and the objdir (current working dir) for relative paths
|
||||
src_base = self.sourcedirs + [os.getcwd()]
|
||||
|
||||
# check if the source file exists
|
||||
realsrc = None
|
||||
for _srcdir in src_base:
|
||||
if os.path.isfile(os.path.join(_srcdir, src)):
|
||||
realsrc = os.path.join(_srcdir, src)
|
||||
break
|
||||
if realsrc is None:
|
||||
if jf is not None:
|
||||
jf.close()
|
||||
raise RuntimeError('File "{0}" not found in {1}'.format(src,
|
||||
', '.join(src_base)))
|
||||
if m.group('optPreprocess'):
|
||||
outf = outHelper.getOutput(out)
|
||||
inf = open(realsrc)
|
||||
pp = self.pp.clone()
|
||||
if src[-4:] == '.css':
|
||||
pp.setMarker('%')
|
||||
pp.out = outf
|
||||
pp.do_include(inf)
|
||||
pp.warnUnused(realsrc)
|
||||
outf.close()
|
||||
inf.close()
|
||||
return
|
||||
|
||||
# copy or symlink if newer or overwrite
|
||||
|
||||
if m.group('optOverwrite') or getModTime(realsrc) \
|
||||
> outHelper.getDestModTime(m.group('output')):
|
||||
if self.outputFormat == 'symlink':
|
||||
outHelper.symlink(realsrc, out)
|
||||
return
|
||||
outf = outHelper.getOutput(out)
|
||||
|
||||
# open in binary mode, this can be images etc
|
||||
|
||||
inf = open(realsrc, 'rb')
|
||||
outf.write(inf.read())
|
||||
outf.close()
|
||||
inf.close()
|
||||
|
||||
class OutputHelper_jar(object):
|
||||
'''Provide getDestModTime and getOutput for a given jarfile.'''
|
||||
|
||||
def __init__(self, jarfile):
|
||||
self.jarfile = jarfile
|
||||
|
||||
def getDestModTime(self, aPath):
|
||||
try:
|
||||
info = self.jarfile.getinfo(aPath)
|
||||
return info.date_time
|
||||
except:
|
||||
return 0
|
||||
|
||||
def getOutput(self, name):
|
||||
return ZipEntry(name, self.jarfile)
|
||||
|
||||
class OutputHelper_flat(object):
|
||||
'''Provide getDestModTime and getOutput for a given flat
|
||||
output directory. The helper method ensureDirFor is used by
|
||||
the symlink subclass.
|
||||
'''
|
||||
|
||||
def __init__(self, basepath):
|
||||
self.basepath = basepath
|
||||
|
||||
def getDestModTime(self, aPath):
|
||||
return getModTime(os.path.join(self.basepath, aPath))
|
||||
|
||||
def getOutput(self, name):
|
||||
out = self.ensureDirFor(name)
|
||||
|
||||
# remove previous link or file
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError, e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
return open(out, 'wb')
|
||||
|
||||
def ensureDirFor(self, name):
|
||||
out = os.path.join(self.basepath, name)
|
||||
outdir = os.path.dirname(out)
|
||||
if not os.path.isdir(outdir):
|
||||
try:
|
||||
os.makedirs(outdir)
|
||||
except OSError, error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
return out
|
||||
|
||||
class OutputHelper_symlink(OutputHelper_flat):
|
||||
'''Subclass of OutputHelper_flat that provides a helper for
|
||||
creating a symlink including creating the parent directories.
|
||||
'''
|
||||
|
||||
def symlink(self, src, dest):
|
||||
out = self.ensureDirFor(dest)
|
||||
|
||||
# remove previous link or file
|
||||
try:
|
||||
os.remove(out)
|
||||
except OSError, e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
if sys.platform != 'win32':
|
||||
os.symlink(src, out)
|
||||
else:
|
||||
# On Win32, use ctypes to create a hardlink
|
||||
rv = CreateHardLink(out, src, None)
|
||||
if rv == 0:
|
||||
raise WinError()
|
||||
|
||||
|
||||
def main(args=None):
|
||||
args = args or sys.argv
|
||||
jm = JarMaker()
|
||||
p = jm.getCommandLineParser()
|
||||
(options, args) = p.parse_args(args)
|
||||
jm.processIncludes(options.I)
|
||||
jm.outputFormat = options.f
|
||||
jm.sourcedirs = options.s
|
||||
jm.topsourcedir = options.t
|
||||
if options.e:
|
||||
jm.useChromeManifest = True
|
||||
jm.useJarfileManifest = False
|
||||
if options.bothManifests:
|
||||
jm.useChromeManifest = True
|
||||
jm.useJarfileManifest = True
|
||||
if options.l10n_base:
|
||||
if not options.relativesrcdir:
|
||||
p.error('relativesrcdir required when using l10n-base')
|
||||
if options.l10n_src:
|
||||
p.error('both l10n-src and l10n-base are not supported')
|
||||
jm.l10nbase = options.l10n_base
|
||||
jm.relativesrcdir = options.relativesrcdir
|
||||
jm.l10nmerge = options.locale_mergedir
|
||||
if jm.l10nmerge and not os.path.isdir(jm.l10nmerge):
|
||||
logging.warning("WARNING: --locale-mergedir passed, but '%s' does not exist. Ignore this message if the locale is complete."
|
||||
)
|
||||
elif options.locale_mergedir:
|
||||
p.error('l10n-base required when using locale-mergedir')
|
||||
jm.localedirs = options.l10n_src
|
||||
if options.root_manifest_entry_appid:
|
||||
jm.rootManifestAppId = options.root_manifest_entry_appid
|
||||
noise = logging.INFO
|
||||
if options.verbose is not None:
|
||||
noise = options.verbose and logging.DEBUG or logging.WARN
|
||||
if sys.version_info[:2] > (2, 3):
|
||||
logging.basicConfig(format='%(message)s')
|
||||
else:
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(noise)
|
||||
topsrc = options.t
|
||||
topsrc = os.path.normpath(os.path.abspath(topsrc))
|
||||
if not args:
|
||||
infile = sys.stdin
|
||||
else:
|
||||
(infile, ) = args
|
||||
jm.makeJar(infile, options.j)
|
@ -23,6 +23,7 @@ from mozbuild.base import (
|
||||
MozbuildObject,
|
||||
MozconfigFindException,
|
||||
MozconfigLoadException,
|
||||
ObjdirMismatchException,
|
||||
)
|
||||
|
||||
|
||||
@ -834,10 +835,7 @@ class Makefiles(MachCommandBase):
|
||||
yield os.path.join(root, f)
|
||||
|
||||
@CommandProvider
|
||||
class MachDebug(object):
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
class MachDebug(MachCommandBase):
|
||||
@Command('environment', category='build-dev',
|
||||
description='Show info about the mach and build environment.')
|
||||
@CommandArgument('--verbose', '-v', action='store_true',
|
||||
@ -847,13 +845,22 @@ class MachDebug(object):
|
||||
print('platform:\n\t%s' % platform.platform())
|
||||
print('python version:\n\t%s' % sys.version)
|
||||
print('python prefix:\n\t%s' % sys.prefix)
|
||||
print('mach cwd:\n\t%s' % self.context.cwd)
|
||||
print('mach cwd:\n\t%s' % self._mach_context.cwd)
|
||||
print('os cwd:\n\t%s' % os.getcwd())
|
||||
print('mach directory:\n\t%s' % self.context.topdir)
|
||||
print('state directory:\n\t%s' % self.context.state_dir)
|
||||
print('mach directory:\n\t%s' % self._mach_context.topdir)
|
||||
print('state directory:\n\t%s' % self._mach_context.state_dir)
|
||||
|
||||
mb = MozbuildObject(self.context.topdir, self.context.settings,
|
||||
self.context.log_manager)
|
||||
try:
|
||||
mb = MozbuildObject.from_environment(cwd=self._mach_context.cwd)
|
||||
except ObjdirMismatchException as e:
|
||||
print('Ambiguous object directory detected. We detected that '
|
||||
'both %s and %s could be object directories. This is '
|
||||
'typically caused by having a mozconfig pointing to a '
|
||||
'different object directory from the current working '
|
||||
'directory. To solve this problem, ensure you do not have a '
|
||||
'default mozconfig in searched paths.' % (e.objdir1,
|
||||
e.objdir2))
|
||||
return 1
|
||||
|
||||
mozconfig = None
|
||||
|
||||
|
@ -200,7 +200,7 @@ class TestMozbuildObject(unittest.TestCase):
|
||||
|
||||
context = MockMachContext()
|
||||
context.cwd = topobjdir
|
||||
context.topdir = topobjdir
|
||||
context.topdir = topsrcdir
|
||||
context.settings = None
|
||||
context.log_manager = None
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
# 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/.
|
||||
|
||||
from __future__ import print_function
|
||||
import unittest
|
||||
|
||||
@ -8,7 +12,9 @@ from shutil import rmtree, copy2
|
||||
from StringIO import StringIO
|
||||
from zipfile import ZipFile
|
||||
import mozunit
|
||||
from JarMaker import JarMaker
|
||||
|
||||
from mozbuild.jar import JarMaker
|
||||
|
||||
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
@ -7,7 +7,6 @@ ifneq (android,$(MOZ_WIDGET_TOOLKIT))
|
||||
MOCHITEST_FILES = \
|
||||
test_webapps_actor.html \
|
||||
debugger-protocol-helper.js \
|
||||
data/ \
|
||||
redirect.sjs \
|
||||
$(NULL)
|
||||
|
||||
|
@ -429,6 +429,8 @@ enum nsEventStructType
|
||||
|
||||
#define NS_WHEEL_EVENT_START 5400
|
||||
#define NS_WHEEL_WHEEL (NS_WHEEL_EVENT_START)
|
||||
#define NS_WHEEL_START (NS_WHEEL_EVENT_START + 1)
|
||||
#define NS_WHEEL_STOP (NS_WHEEL_EVENT_START + 2)
|
||||
|
||||
//System time is changed
|
||||
#define NS_MOZ_TIME_CHANGE_EVENT 5500
|
||||
|
@ -318,7 +318,8 @@ public:
|
||||
deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
|
||||
customizedByUserPrefs(false), isMomentum(false), isPixelOnlyDevice(false),
|
||||
lineOrPageDeltaX(0), lineOrPageDeltaY(0), scrollType(SCROLL_DEFAULT),
|
||||
overflowDeltaX(0.0), overflowDeltaY(0.0)
|
||||
overflowDeltaX(0.0), overflowDeltaY(0.0),
|
||||
mViewPortIsOverscrolled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -399,6 +400,12 @@ public:
|
||||
double overflowDeltaX;
|
||||
double overflowDeltaY;
|
||||
|
||||
// Whether or not the parent of the currently overscrolled frame is the
|
||||
// ViewPort. This is false in situations when an element on the page is being
|
||||
// overscrolled (such as a text field), but true when the 'page' is being
|
||||
// overscrolled.
|
||||
bool mViewPortIsOverscrolled;
|
||||
|
||||
void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
|
||||
{
|
||||
AssignMouseEventBaseData(aEvent, aCopyTargets);
|
||||
@ -415,6 +422,7 @@ public:
|
||||
scrollType = aEvent.scrollType;
|
||||
overflowDeltaX = aEvent.overflowDeltaX;
|
||||
overflowDeltaY = aEvent.overflowDeltaY;
|
||||
mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,6 +205,12 @@ typedef NSInteger NSEventGestureAxis;
|
||||
#endif // #ifdef __LP64__
|
||||
#endif // #if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
|
||||
enum {
|
||||
NSEventPhaseMayBegin = 0x1 << 5
|
||||
};
|
||||
#endif // #if !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
|
||||
|
||||
// Undocumented scrollPhase flag that lets us discern between real scrolls and
|
||||
// automatically firing momentum scroll events.
|
||||
@interface NSEvent (ScrollPhase)
|
||||
@ -252,6 +258,11 @@ typedef NSInteger NSEventGestureAxis;
|
||||
BOOL mPendingFullDisplay;
|
||||
BOOL mPendingDisplay;
|
||||
|
||||
// WheelStart/Stop events should always come in pairs. This BOOL records the
|
||||
// last received event so that, when we receive one of the events, we make sure
|
||||
// to send its pair event first, in case we didn't yet for any reason.
|
||||
BOOL mExpectingWheelStop;
|
||||
|
||||
// Holds our drag service across multiple drag calls. The reference to the
|
||||
// service is obtained when the mouse enters the view and is released when
|
||||
// the mouse exits or there is a drop. This prevents us from having to
|
||||
@ -290,6 +301,7 @@ typedef NSInteger NSEventGestureAxis;
|
||||
#ifdef __LP64__
|
||||
// Support for fluid swipe tracking.
|
||||
BOOL* mCancelSwipeAnimation;
|
||||
uint32_t mCurrentSwipeDir;
|
||||
#endif
|
||||
|
||||
// Whether this uses off-main-thread compositing.
|
||||
@ -354,13 +366,17 @@ typedef NSInteger NSEventGestureAxis;
|
||||
- (void)rotateWithEvent:(NSEvent *)anEvent;
|
||||
- (void)endGestureWithEvent:(NSEvent *)anEvent;
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)anEvent;
|
||||
|
||||
// Helper function for Lion smart magnify events
|
||||
+ (BOOL)isLionSmartMagnifyEvent:(NSEvent*)anEvent;
|
||||
|
||||
// Support for fluid swipe tracking.
|
||||
#ifdef __LP64__
|
||||
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
|
||||
scrollOverflow:(double)overflow;
|
||||
scrollOverflowX:(double)anOverflowX
|
||||
scrollOverflowY:(double)anOverflowY
|
||||
viewPortIsOverscrolled:(BOOL)aViewPortIsOverscrolled;
|
||||
#endif
|
||||
|
||||
- (void)setUsingOMTCompositor:(BOOL)aUseOMTC;
|
||||
|
@ -140,6 +140,8 @@ uint32_t nsChildView::sLastInputEventCount = 0;
|
||||
- (void)forceRefreshOpenGL;
|
||||
|
||||
// set up a gecko mouse event based on a cocoa mouse event
|
||||
- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent
|
||||
toGeckoEvent:(WidgetWheelEvent*)outWheelEvent;
|
||||
- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent
|
||||
toGeckoEvent:(WidgetInputEvent*)outGeckoEvent;
|
||||
|
||||
@ -2777,6 +2779,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
#endif
|
||||
mPendingDisplay = NO;
|
||||
mBlockedLastMouseDown = NO;
|
||||
mExpectingWheelStop = NO;
|
||||
|
||||
mLastMouseDownEvent = nil;
|
||||
mClickThroughMouseDownEvent = nil;
|
||||
@ -2796,6 +2799,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
|
||||
#ifdef __LP64__
|
||||
mCancelSwipeAnimation = nil;
|
||||
mCurrentSwipeDir = 0;
|
||||
#endif
|
||||
|
||||
mTopLeftCornerMask = NULL;
|
||||
@ -4093,17 +4097,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
delta:0.0];
|
||||
}
|
||||
|
||||
// Support fluid swipe tracking on OS X 10.7 and higher. We must be careful
|
||||
// to only invoke this support on a horizontal two-finger gesture that really
|
||||
// Support fluid swipe tracking on OS X 10.7 and higher. We must be careful
|
||||
// to only invoke this support on a two-finger gesture that really
|
||||
// is a swipe (and not a scroll) -- in other words, the app is responsible
|
||||
// for deciding which is which. But once the decision is made, the OS tracks
|
||||
// for deciding which is which. But once the decision is made, the OS tracks
|
||||
// the swipe until it has finished, and decides whether or not it succeeded.
|
||||
// A swipe has the same functionality as the Back and Forward buttons. For
|
||||
// now swipe animation is unsupported (e.g. no bounces). This method is
|
||||
// partly based on Apple sample code available at
|
||||
// http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html
|
||||
// A horizontal swipe has the same functionality as the Back and Forward
|
||||
// buttons.
|
||||
// This method is partly based on Apple sample code available at
|
||||
// developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html
|
||||
// (under Fluid Swipe Tracking API).
|
||||
- (void)maybeTrackScrollEventAsSwipe:(NSEvent *)anEvent
|
||||
scrollOverflow:(double)overflow
|
||||
scrollOverflowX:(double)anOverflowX
|
||||
scrollOverflowY:(double)anOverflowY
|
||||
viewPortIsOverscrolled:(BOOL)aViewPortIsOverscrolled
|
||||
{
|
||||
if (!nsCocoaFeatures::OnLionOrLater()) {
|
||||
return;
|
||||
@ -4118,6 +4125,12 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
// We should only track scroll events as swipe if the viewport is being
|
||||
// overscrolled.
|
||||
if (!aViewPortIsOverscrolled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify that this is a scroll wheel event with proper phase to be tracked
|
||||
// by the OS.
|
||||
if ([anEvent type] != NSScrollWheel || [anEvent phase] == NSEventPhaseNone) {
|
||||
@ -4125,12 +4138,10 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
}
|
||||
|
||||
// Only initiate tracking if the user has tried to scroll past the edge of
|
||||
// the current page (as indicated by 'overflow' being non-zero). Gecko only
|
||||
// sets WidgetMouseScrollEvent.scrollOverflow when it's processing
|
||||
// NS_MOUSE_PIXEL_SCROLL events (not NS_MOUSE_SCROLL events).
|
||||
// WidgetMouseScrollEvent.scrollOverflow only indicates left or right overflow
|
||||
// for horizontal NS_MOUSE_PIXEL_SCROLL events.
|
||||
if (!overflow) {
|
||||
// the current page (as indicated by 'anOverflowX' or 'anOverflowY' being
|
||||
// non-zero). Gecko only sets WidgetMouseScrollEvent.scrollOverflow when it's
|
||||
// processing NS_MOUSE_PIXEL_SCROLL events (not NS_MOUSE_SCROLL events).
|
||||
if (anOverflowX == 0.0 && anOverflowY == 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4139,18 +4150,20 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
deltaX = [anEvent scrollingDeltaX];
|
||||
deltaY = [anEvent scrollingDeltaY];
|
||||
} else {
|
||||
deltaX = [anEvent deltaX];
|
||||
deltaY = [anEvent deltaY];
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t vDirs = (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_DOWN |
|
||||
(uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_UP;
|
||||
uint32_t direction = 0;
|
||||
|
||||
// Only initiate horizontal tracking for events whose horizontal element is
|
||||
// at least eight times larger than its vertical element. This minimizes
|
||||
// performance problems with vertical scrolls (by minimizing the possibility
|
||||
// that they'll be misinterpreted as horizontal swipes), while still
|
||||
// tolerating a small vertical element to a true horizontal swipe. The number
|
||||
// '8' was arrived at by trial and error.
|
||||
if (overflow != 0.0 && deltaX != 0.0 &&
|
||||
if (anOverflowX != 0.0 && deltaX != 0.0 &&
|
||||
fabsf(deltaX) > fabsf(deltaY) * 8) {
|
||||
// Only initiate horizontal tracking for gestures that have just begun --
|
||||
// otherwise a scroll to one side of the page can have a swipe tacked on
|
||||
@ -4164,10 +4177,35 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
} else {
|
||||
direction = (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_LEFT;
|
||||
}
|
||||
}
|
||||
// Only initiate vertical tracking for events whose vertical element is
|
||||
// at least two times larger than its horizontal element. This minimizes
|
||||
// performance problems. The number '2' was arrived at by trial and error.
|
||||
else if (anOverflowY != 0.0 && deltaY != 0.0 &&
|
||||
fabsf(deltaY) > fabsf(deltaX) * 2) {
|
||||
if (deltaY < 0.0) {
|
||||
direction = (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_DOWN;
|
||||
} else {
|
||||
direction = (uint32_t)nsIDOMSimpleGestureEvent::DIRECTION_UP;
|
||||
}
|
||||
|
||||
if ((mCurrentSwipeDir & vDirs) && (mCurrentSwipeDir != direction)) {
|
||||
// If a swipe is currently being tracked kill it -- it's been interrupted
|
||||
// by another gesture event.
|
||||
if (mCancelSwipeAnimation && *mCancelSwipeAnimation == NO) {
|
||||
*mCancelSwipeAnimation = YES;
|
||||
mCancelSwipeAnimation = nil;
|
||||
[self sendSwipeEndEvent:anEvent allowedDirections:0];
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Track the direction we're going in.
|
||||
mCurrentSwipeDir = direction;
|
||||
|
||||
// If a swipe is currently being tracked kill it -- it's been interrupted
|
||||
// by another gesture event.
|
||||
if (mCancelSwipeAnimation && *mCancelSwipeAnimation == NO) {
|
||||
@ -4189,8 +4227,14 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
double min = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ? -1 : 0;
|
||||
double max = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ? 1 : 0;
|
||||
CGFloat min = 0.0;
|
||||
CGFloat max = 0.0;
|
||||
if (!(direction & vDirs)) {
|
||||
min = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ?
|
||||
-1.0 : 0.0;
|
||||
max = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ?
|
||||
1.0 : 0.0;
|
||||
}
|
||||
|
||||
__block BOOL animationCanceled = NO;
|
||||
__block BOOL geckoSwipeEventSent = NO;
|
||||
@ -4228,13 +4272,15 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
if (animationCanceled || !mGeckoChild || gestureAmount == 0.0) {
|
||||
*stop = YES;
|
||||
animationCanceled = YES;
|
||||
if (gestureAmount == 0.0) {
|
||||
if (gestureAmount == 0.0 ||
|
||||
((direction & vDirs) && (direction != mCurrentSwipeDir))) {
|
||||
if (mCancelSwipeAnimation)
|
||||
*mCancelSwipeAnimation = YES;
|
||||
mCancelSwipeAnimation = nil;
|
||||
[self sendSwipeEndEvent:anEvent
|
||||
allowedDirections:allowedDirectionsCopy];
|
||||
}
|
||||
mCurrentSwipeDir = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4268,6 +4314,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
|
||||
if (isComplete) {
|
||||
[self sendSwipeEndEvent:anEvent allowedDirections:allowedDirectionsCopy];
|
||||
mCurrentSwipeDir = 0;
|
||||
mCancelSwipeAnimation = nil;
|
||||
}
|
||||
}];
|
||||
@ -4708,6 +4755,22 @@ static int32_t RoundUp(double aDouble)
|
||||
static_cast<int32_t>(ceil(aDouble));
|
||||
}
|
||||
|
||||
- (void)sendWheelStartOrStop:(uint32_t)msg forEvent:(NSEvent *)theEvent
|
||||
{
|
||||
WidgetWheelEvent wheelEvent(true, msg, mGeckoChild);
|
||||
[self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent];
|
||||
mExpectingWheelStop = (msg == NS_WHEEL_START);
|
||||
mGeckoChild->DispatchWindowEvent(wheelEvent);
|
||||
}
|
||||
|
||||
- (void)sendWheelCondition:(BOOL)condition first:(uint32_t)first second:(uint32_t)second forEvent:(NSEvent *)theEvent
|
||||
{
|
||||
if (mExpectingWheelStop == condition) {
|
||||
[self sendWheelStartOrStop:first forEvent:theEvent];
|
||||
}
|
||||
[self sendWheelStartOrStop:second forEvent:theEvent];
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent*)theEvent
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
@ -4724,25 +4787,23 @@ static int32_t RoundUp(double aDouble)
|
||||
return;
|
||||
}
|
||||
|
||||
WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, mGeckoChild);
|
||||
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&wheelEvent];
|
||||
wheelEvent.deltaMode =
|
||||
Preferences::GetBool("mousewheel.enable_pixel_scrolling", true) ?
|
||||
nsIDOMWheelEvent::DOM_DELTA_PIXEL : nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
if (nsCocoaFeatures::OnLionOrLater()) {
|
||||
NSEventPhase phase = [theEvent phase];
|
||||
// Fire NS_WHEEL_START/STOP events when 2 fingers touch/release the touchpad.
|
||||
if (phase & NSEventPhaseMayBegin) {
|
||||
[self sendWheelCondition:YES first:NS_WHEEL_STOP second:NS_WHEEL_START forEvent:theEvent];
|
||||
return;
|
||||
}
|
||||
|
||||
// Calling deviceDeltaX or deviceDeltaY on theEvent will trigger a Cocoa
|
||||
// assertion and an Objective-C NSInternalInconsistencyException if the
|
||||
// underlying "Carbon" event doesn't contain pixel scrolling information.
|
||||
// For these events, carbonEventKind is kEventMouseWheelMoved instead of
|
||||
// kEventMouseScroll.
|
||||
if (wheelEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) {
|
||||
EventRef theCarbonEvent = [theEvent _eventRef];
|
||||
UInt32 carbonEventKind = theCarbonEvent ? ::GetEventKind(theCarbonEvent) : 0;
|
||||
if (carbonEventKind != kEventMouseScroll) {
|
||||
wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
if (phase & (NSEventPhaseEnded | NSEventPhaseCancelled)) {
|
||||
[self sendWheelCondition:NO first:NS_WHEEL_START second:NS_WHEEL_STOP forEvent:theEvent];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, mGeckoChild);
|
||||
[self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent];
|
||||
|
||||
wheelEvent.lineOrPageDeltaX = RoundUp(-[theEvent deltaX]);
|
||||
wheelEvent.lineOrPageDeltaY = RoundUp(-[theEvent deltaY]);
|
||||
|
||||
@ -4773,25 +4834,36 @@ static int32_t RoundUp(double aDouble)
|
||||
return;
|
||||
}
|
||||
|
||||
wheelEvent.isMomentum = nsCocoaUtils::IsMomentumScrollEvent(theEvent);
|
||||
|
||||
NPCocoaEvent cocoaEvent;
|
||||
ChildViewMouseTracker::AttachPluginEvent(wheelEvent, self, theEvent,
|
||||
NPCocoaEventScrollWheel,
|
||||
&cocoaEvent);
|
||||
|
||||
mGeckoChild->DispatchWindowEvent(wheelEvent);
|
||||
if (!mGeckoChild) {
|
||||
return;
|
||||
#ifdef __LP64__
|
||||
// Only dispatch this event if we're not currently tracking a scroll event as
|
||||
// swipe.
|
||||
if (!mCancelSwipeAnimation || *mCancelSwipeAnimation == YES) {
|
||||
#endif // #ifdef __LP64__
|
||||
mGeckoChild->DispatchWindowEvent(wheelEvent);
|
||||
if (!mGeckoChild) {
|
||||
return;
|
||||
}
|
||||
#ifdef __LP64__
|
||||
} else {
|
||||
// Manually set these members here since we didn't dispatch the event.
|
||||
wheelEvent.overflowDeltaX = wheelEvent.deltaX;
|
||||
wheelEvent.overflowDeltaY = wheelEvent.deltaY;
|
||||
wheelEvent.mViewPortIsOverscrolled = true;
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
// overflowDeltaX tells us when the user has tried to scroll past the edge
|
||||
// of a page to the left or the right (in those cases it's non-zero).
|
||||
if (wheelEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL &&
|
||||
wheelEvent.deltaX != 0.0) {
|
||||
// overflowDeltaX and overflowDeltaY tell us when the user has tried to
|
||||
// scroll past the edge of a page (in those cases it's non-zero).
|
||||
if ((wheelEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) &&
|
||||
(wheelEvent.deltaX != 0.0 || wheelEvent.deltaY != 0.0)) {
|
||||
[self maybeTrackScrollEventAsSwipe:theEvent
|
||||
scrollOverflow:wheelEvent.overflowDeltaX];
|
||||
scrollOverflowX:wheelEvent.overflowDeltaX
|
||||
scrollOverflowY:wheelEvent.overflowDeltaY
|
||||
viewPortIsOverscrolled:wheelEvent.mViewPortIsOverscrolled];
|
||||
}
|
||||
#endif // #ifdef __LP64__
|
||||
|
||||
@ -4850,6 +4922,29 @@ static int32_t RoundUp(double aDouble)
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||
}
|
||||
|
||||
- (void) convertCocoaMouseWheelEvent:(NSEvent*)aMouseEvent
|
||||
toGeckoEvent:(WidgetWheelEvent*)outWheelEvent
|
||||
{
|
||||
[self convertCocoaMouseEvent:aMouseEvent toGeckoEvent:outWheelEvent];
|
||||
outWheelEvent->deltaMode =
|
||||
Preferences::GetBool("mousewheel.enable_pixel_scrolling", true) ?
|
||||
nsIDOMWheelEvent::DOM_DELTA_PIXEL : nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
|
||||
// Calling deviceDeltaX or deviceDeltaY on theEvent will trigger a Cocoa
|
||||
// assertion and an Objective-C NSInternalInconsistencyException if the
|
||||
// underlying "Carbon" event doesn't contain pixel scrolling information.
|
||||
// For these events, carbonEventKind is kEventMouseWheelMoved instead of
|
||||
// kEventMouseScroll.
|
||||
if (outWheelEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL) {
|
||||
EventRef theCarbonEvent = [aMouseEvent _eventRef];
|
||||
UInt32 carbonEventKind = theCarbonEvent ? ::GetEventKind(theCarbonEvent) : 0;
|
||||
if (carbonEventKind != kEventMouseScroll) {
|
||||
outWheelEvent->deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
|
||||
}
|
||||
}
|
||||
outWheelEvent->isMomentum = nsCocoaUtils::IsMomentumScrollEvent(aMouseEvent);
|
||||
}
|
||||
|
||||
- (void) convertCocoaMouseEvent:(NSEvent*)aMouseEvent
|
||||
toGeckoEvent:(WidgetInputEvent*)outGeckoEvent
|
||||
{
|
||||
|
@ -290,10 +290,7 @@ nsToolkit* nsToolkit::GetToolkit()
|
||||
// Since the Method type becomes an opaque type as of Objective-C 2.0, we'll
|
||||
// have to switch to using accessor methods like method_exchangeImplementations()
|
||||
// when we build 64-bit binaries that use Objective-C 2.0 (on and for Leopard
|
||||
// and above). But these accessor methods aren't available in Objective-C 1
|
||||
// (or on Tiger). So we need to access Method's members directly for (Tiger-
|
||||
// capable) binaries (32-bit or 64-bit) that use Objective-C 1 (as long as we
|
||||
// keep supporting Tiger).
|
||||
// and above).
|
||||
//
|
||||
// Be aware that, if aClass doesn't have an orgMethod selector but one of its
|
||||
// superclasses does, the method substitution will (in effect) take place in
|
||||
@ -321,13 +318,7 @@ nsresult nsToolkit::SwizzleMethods(Class aClass, SEL orgMethod, SEL posedMethod,
|
||||
if (!original || !posed)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#ifdef __LP64__
|
||||
method_exchangeImplementations(original, posed);
|
||||
#else
|
||||
IMP aMethodImp = original->method_imp;
|
||||
original->method_imp = posed->method_imp;
|
||||
posed->method_imp = aMethodImp;
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user