mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Back out bug 813978 on a CLOSED TREE.
This commit is contained in:
commit
1ffd79274e
@ -11,7 +11,7 @@
|
||||
],
|
||||
"zip_files": [
|
||||
["{workdir}/out/target/product/otoro/*.img", "out/target/product/otoro/"],
|
||||
"{workdir}/boot.img",
|
||||
["{workdir}/boot.img", "out/target/product/otoro/"],
|
||||
"{workdir}/flash.sh",
|
||||
"{workdir}/load-config.sh",
|
||||
"{workdir}/.config",
|
||||
|
@ -12,7 +12,7 @@
|
||||
],
|
||||
"zip_files": [
|
||||
["{workdir}/out/target/product/unagi/*.img", "out/target/product/unagi/"],
|
||||
"{workdir}/boot.img",
|
||||
["{workdir}/boot.img", "out/target/product/unagi/"],
|
||||
"{workdir}/flash.sh",
|
||||
"{workdir}/load-config.sh",
|
||||
"{workdir}/.config",
|
||||
|
@ -31,11 +31,8 @@ DEFINES += \
|
||||
-DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
|
||||
-DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
|
||||
-DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZILLA_OFFICIAL
|
||||
DEFINES += -DMOZILLA_OFFICIAL
|
||||
endif
|
||||
$(NULL)
|
||||
|
||||
ifdef LIBXUL_SDK #{
|
||||
PREF_JS_EXPORTS += $(srcdir)/profile/channel-prefs.js
|
||||
|
@ -734,12 +734,6 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
|
||||
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
// Normally the "client ID" sent in updates is appinfo.name, but for
|
||||
// official Firefox releases from Mozilla we use a special identifier.
|
||||
pref("browser.safebrowsing.id", "navclient-auto-ffox");
|
||||
#endif
|
||||
|
||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||
// pages on phishing/malware hits. (bug 399233)
|
||||
pref("urlclassifier.alternate_error_page", "blocked");
|
||||
|
@ -35,6 +35,9 @@
|
||||
|
||||
<toolbar id="placesToolbar">
|
||||
<toolbarbutton id="clearDownloadsButton"
|
||||
#ifdef XP_MACOSX
|
||||
class="tabbable"
|
||||
#endif
|
||||
insertbefore="libraryToolbarSpacer"
|
||||
label="&clearDownloadsButton.label;"
|
||||
command="downloadsCmd_clearDownloads"
|
||||
|
@ -31,4 +31,4 @@ browser.jar:
|
||||
content/browser/places/moveBookmarks.js (content/moveBookmarks.js)
|
||||
content/browser/places/editBookmarkOverlay.xul (content/editBookmarkOverlay.xul)
|
||||
content/browser/places/editBookmarkOverlay.js (content/editBookmarkOverlay.js)
|
||||
content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
|
||||
* content/browser/places/downloadsViewOverlay.xul (content/downloadsViewOverlay.xul)
|
||||
|
@ -374,8 +374,6 @@
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
||||
@BINPATH@/components/nsSidebar.manifest
|
||||
@BINPATH@/components/nsSidebar.js
|
||||
@BINPATH@/components/extensions.manifest
|
||||
|
@ -318,8 +318,10 @@ toolbar[iconsize="large"] > #downloads-indicator[attention] > #downloads-indicat
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(255, 135, 94);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
@ -492,8 +492,10 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 185, 255);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
@ -343,8 +343,10 @@ richlistitem[type="download"]:hover > stack > .downloadButton.downloadRetry:acti
|
||||
-moz-appearance: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
/* The background-clip: border-box; and background-image: none; are there to expand the background-color behind the border */
|
||||
background-clip: padding-box, border-box;
|
||||
background-color: rgb(90, 201, 66);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px);
|
||||
background-image: linear-gradient(transparent 1px, rgba(255, 255, 255, 0.4) 1px, rgba(255, 255, 255, 0.4) 2px, transparent 2px), none;
|
||||
border: 1px solid;
|
||||
border-color: rgba(0,43,86,.6) rgba(0,43,86,.4) rgba(0,43,86,.4);
|
||||
border-radius: 2px 0 0 2px;
|
||||
|
@ -9,6 +9,7 @@
|
||||
from __future__ import with_statement
|
||||
from optparse import OptionParser
|
||||
import sys, re, os, posixpath, ntpath
|
||||
import errno
|
||||
from StringIO import StringIO
|
||||
# Standalone js doesn't have virtualenv.
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
||||
|
@ -274,38 +274,37 @@ class Automation(object):
|
||||
cursor.execute("PRAGMA user_version=3");
|
||||
|
||||
# SQL copied from nsPermissionManager.cpp
|
||||
cursor.execute("""CREATE TABLE moz_hosts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
host TEXT,
|
||||
type TEXT,
|
||||
permission INTEGER,
|
||||
expireType INTEGER,
|
||||
expireTime INTEGER,
|
||||
appId INTEGER,
|
||||
isInBrowserElement INTEGER)""")
|
||||
cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
host TEXT,
|
||||
type TEXT,
|
||||
permission INTEGER,
|
||||
expireType INTEGER,
|
||||
expireTime INTEGER,
|
||||
appId INTEGER,
|
||||
isInBrowserElement INTEGER)""")
|
||||
|
||||
# Insert desired permissions
|
||||
c = 0
|
||||
for perm in permissions.keys():
|
||||
for host,allow in permissions[perm]:
|
||||
c += 1
|
||||
cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0, 0, 0)",
|
||||
(c, host, perm, 1 if allow else 2))
|
||||
cursor.execute("INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)",
|
||||
(host, perm, 1 if allow else 2))
|
||||
|
||||
# Commit and close
|
||||
permDB.commit()
|
||||
cursor.close()
|
||||
|
||||
def setupTestApps(self, profileDir, apps):
|
||||
webappJSONTemplate = Template(""""$name": {
|
||||
"origin": "$origin",
|
||||
"installOrigin": "$origin",
|
||||
"receipt": null,
|
||||
"installTime": 132333986000,
|
||||
"manifestURL": "$manifestURL",
|
||||
"localId": $localId,
|
||||
"appStatus": $appStatus,
|
||||
"csp": "$csp"
|
||||
webappJSONTemplate = Template(""""$id": {
|
||||
"origin": "$origin",
|
||||
"installOrigin": "$origin",
|
||||
"receipt": null,
|
||||
"installTime": 132333986000,
|
||||
"manifestURL": "$manifestURL",
|
||||
"localId": $localId,
|
||||
"id": "$id",
|
||||
"appStatus": $appStatus,
|
||||
"csp": "$csp"
|
||||
}""")
|
||||
|
||||
manifestTemplate = Template("""{
|
||||
@ -333,16 +332,73 @@ class Automation(object):
|
||||
|
||||
# Create webapps/webapps.json
|
||||
webappsDir = os.path.join(profileDir, "webapps")
|
||||
os.mkdir(webappsDir);
|
||||
if not os.access(webappsDir, os.F_OK):
|
||||
os.mkdir(webappsDir)
|
||||
|
||||
lineRe = re.compile(r'(.*?)"(.*?)": (.*)')
|
||||
|
||||
webappsJSONFilename = os.path.join(webappsDir, "webapps.json")
|
||||
webappsJSON = []
|
||||
for localId, app in enumerate(apps):
|
||||
app['localId'] = localId + 1 # Has to be 1..n
|
||||
webappsJSON.append(webappJSONTemplate.substitute(app))
|
||||
webappsJSON = '{\n' + ',\n'.join(webappsJSON) + '\n}\n'
|
||||
if os.access(webappsJSONFilename, os.F_OK):
|
||||
# If there is an existing webapps.json file (which will be the case for
|
||||
# b2g), we parse the data in the existing file before appending test
|
||||
# test apps to it.
|
||||
startId = 1
|
||||
webappsJSONFile = open(webappsJSONFilename, "r")
|
||||
contents = webappsJSONFile.read()
|
||||
|
||||
webappsJSONFile = open(os.path.join(webappsDir, "webapps.json"), "a")
|
||||
webappsJSONFile.write(webappsJSON)
|
||||
for app_content in contents.split('},'):
|
||||
app = {}
|
||||
# ghetto json parser needed due to lack of json/simplejson on test slaves
|
||||
for line in app_content.split('\n'):
|
||||
m = lineRe.match(line)
|
||||
if m:
|
||||
value = m.groups()[2]
|
||||
# remove any trailing commas
|
||||
if value[-1:] == ',':
|
||||
value = value[:-1]
|
||||
# set the app name from a line that looks like this:
|
||||
# "name.gaiamobile.org": {
|
||||
if value == '{':
|
||||
app['id'] = m.groups()[1]
|
||||
# parse string, None, bool and int types
|
||||
elif value[0:1] == '"':
|
||||
app[m.groups()[1]] = value[1:-1]
|
||||
elif value == "null":
|
||||
app[m.groups()[1]] = None
|
||||
elif value == "true":
|
||||
app[m.groups()[1]] = True
|
||||
elif value == "false":
|
||||
app[m.groups()[1]] = False
|
||||
else:
|
||||
app[m.groups()[1]] = int(value)
|
||||
if app:
|
||||
webappsJSON.append(app)
|
||||
|
||||
webappsJSONFile.close()
|
||||
|
||||
startId = 1
|
||||
for app in webappsJSON:
|
||||
if app['localId'] >= startId:
|
||||
startId = app['localId'] + 1
|
||||
if not app.get('csp'):
|
||||
app['csp'] = ''
|
||||
if not app.get('appStatus'):
|
||||
app['appStatus'] = 3
|
||||
|
||||
for localId, app in enumerate(apps):
|
||||
app['localId'] = localId + startId # localId must be from 1..N
|
||||
if not app.get('id'):
|
||||
app['id'] = app['name']
|
||||
webappsJSON.append(app)
|
||||
|
||||
contents = []
|
||||
for app in webappsJSON:
|
||||
contents.append(webappJSONTemplate.substitute(app))
|
||||
contents = '{\n' + ',\n'.join(contents) + '\n}\n'
|
||||
|
||||
webappsJSONFile = open(webappsJSONFilename, "w")
|
||||
webappsJSONFile.write(contents)
|
||||
webappsJSONFile.close()
|
||||
|
||||
# Create manifest file for each app.
|
||||
@ -356,13 +412,19 @@ class Automation(object):
|
||||
manifestFile.write(manifest)
|
||||
manifestFile.close()
|
||||
|
||||
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
|
||||
def initializeProfile(self, profileDir, extraPrefs=[],
|
||||
useServerLocations=False,
|
||||
initialProfile=None):
|
||||
" Sets up the standard testing profile."
|
||||
|
||||
prefs = []
|
||||
# Start with a clean slate.
|
||||
shutil.rmtree(profileDir, True)
|
||||
os.mkdir(profileDir)
|
||||
|
||||
if initialProfile:
|
||||
shutil.copytree(initialProfile, profileDir)
|
||||
else:
|
||||
os.mkdir(profileDir)
|
||||
|
||||
# Set up permissions database
|
||||
locations = self.readLocations()
|
||||
@ -600,7 +662,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
'manifestURL': 'https://example.com/manifest_csp_cert.webapp',
|
||||
'description': 'https://example.com Certified App with manifest policy',
|
||||
'appStatus': _APP_STATUS_CERTIFIED
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'https_example_csp_installed',
|
||||
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
||||
@ -608,7 +670,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
'manifestURL': 'https://example.com/manifest_csp_inst.webapp',
|
||||
'description': 'https://example.com Installed App with manifest policy',
|
||||
'appStatus': _APP_STATUS_INSTALLED
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'https_example_csp_privileged',
|
||||
'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
|
||||
@ -616,15 +678,15 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
'manifestURL': 'https://example.com/manifest_csp_priv.webapp',
|
||||
'description': 'https://example.com Privileged App with manifest policy',
|
||||
'appStatus': _APP_STATUS_PRIVILEGED
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'https_a_domain_certified',
|
||||
'csp' : "",
|
||||
'csp': "",
|
||||
'origin': 'https://acertified.com',
|
||||
'manifestURL': 'https://acertified.com/manifest.webapp',
|
||||
'description': 'https://acertified.com Certified App',
|
||||
'appStatus': _APP_STATUS_CERTIFIED
|
||||
},
|
||||
},
|
||||
{
|
||||
'name': 'https_a_domain_privileged',
|
||||
'csp': "",
|
||||
@ -632,7 +694,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
'manifestURL': 'https://aprivileged.com/manifest.webapp',
|
||||
'description': 'https://aprivileged.com Privileged App ',
|
||||
'appStatus': _APP_STATUS_PRIVILEGED
|
||||
},
|
||||
},
|
||||
];
|
||||
self.setupTestApps(profileDir, apps)
|
||||
|
||||
@ -1033,7 +1095,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
runSSLTunnel = False, utilityPath = None,
|
||||
xrePath = None, certPath = None,
|
||||
debuggerInfo = None, symbolsPath = None,
|
||||
timeout = -1, maxTime = None):
|
||||
timeout = -1, maxTime = None, onLaunch = None):
|
||||
"""
|
||||
Run the app, log the duration it took to execute, return the status code.
|
||||
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
|
||||
@ -1090,6 +1152,11 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
|
||||
stderr = subprocess.STDOUT)
|
||||
self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
|
||||
|
||||
if onLaunch is not None:
|
||||
# Allow callers to specify an onLaunch callback to be fired after the
|
||||
# app is launched.
|
||||
onLaunch()
|
||||
|
||||
status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
|
||||
self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
|
||||
|
||||
|
@ -48,7 +48,7 @@ class B2GRemoteAutomation(Automation):
|
||||
self._product = "b2g"
|
||||
self.lastTestSeen = "b2gautomation.py"
|
||||
# Default log finish to mochitest standard
|
||||
self.logFinish = 'INFO SimpleTest FINISHED'
|
||||
self.logFinish = 'INFO SimpleTest FINISHED'
|
||||
Automation.__init__(self)
|
||||
|
||||
def setEmulator(self, is_emulator):
|
||||
@ -85,7 +85,7 @@ class B2GRemoteAutomation(Automation):
|
||||
env['MOZ_HIDE_RESULTS_TABLE'] = '1'
|
||||
return env
|
||||
|
||||
def waitForNet(self):
|
||||
def waitForNet(self):
|
||||
active = False
|
||||
time_out = 0
|
||||
while not active and time_out < 40:
|
||||
@ -106,15 +106,20 @@ class B2GRemoteAutomation(Automation):
|
||||
self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
|
||||
crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
|
||||
try:
|
||||
shutil.rmtree(dumpDir)
|
||||
shutil.rmtree(dumpDir)
|
||||
except:
|
||||
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
||||
print "WARNING: unable to remove directory: %s" % (dumpDir)
|
||||
return crashed
|
||||
|
||||
def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
|
||||
def initializeProfile(self, profileDir, extraPrefs=[],
|
||||
useServerLocations=False,
|
||||
initialProfile=None):
|
||||
# add b2g specific prefs
|
||||
extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
|
||||
return Automation.initializeProfile(self, profileDir, extraPrefs, useServerLocations)
|
||||
return Automation.initializeProfile(self, profileDir,
|
||||
extraPrefs,
|
||||
useServerLocations,
|
||||
initialProfile)
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
# if remote profile is specified, use that instead
|
||||
@ -165,7 +170,7 @@ class B2GRemoteAutomation(Automation):
|
||||
status = 'unknown'
|
||||
|
||||
for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
|
||||
result = re.match('(.*?)\t(.*)', line)
|
||||
result = re.match('(.*?)\t(.*)', line)
|
||||
if result:
|
||||
thisSerial = result.group(1)
|
||||
if not serial or thisSerial == serial:
|
||||
@ -223,9 +228,9 @@ class B2GRemoteAutomation(Automation):
|
||||
if not self._is_emulator:
|
||||
self.rebootDevice()
|
||||
time.sleep(5)
|
||||
#wait for wlan to come up
|
||||
#wait for wlan to come up
|
||||
if not self.waitForNet():
|
||||
raise Exception("network did not come up, please configure the network" +
|
||||
raise Exception("network did not come up, please configure the network" +
|
||||
" prior to running before running the automation framework")
|
||||
|
||||
# stop b2g
|
||||
@ -334,10 +339,33 @@ class B2GRemoteAutomation(Automation):
|
||||
break
|
||||
return '\n'.join(lines)
|
||||
|
||||
def wait(self, timeout = None):
|
||||
def wait(self, timeout=None):
|
||||
# this should never happen
|
||||
raise Exception("'wait' called on B2GInstance")
|
||||
|
||||
def kill(self):
|
||||
# this should never happen
|
||||
raise Exception("'kill' called on B2GInstance")
|
||||
|
||||
|
||||
class B2GDesktopAutomation(Automation):
|
||||
|
||||
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
||||
""" build the application command line """
|
||||
|
||||
cmd = os.path.abspath(app)
|
||||
args = []
|
||||
|
||||
if debuggerInfo:
|
||||
args.extend(debuggerInfo["args"])
|
||||
args.append(cmd)
|
||||
cmd = os.path.abspath(debuggerInfo["path"])
|
||||
|
||||
if self.IS_MAC:
|
||||
args.append("-foreground")
|
||||
|
||||
profileDirectory = profileDir + "/"
|
||||
|
||||
args.extend(("-profile", profileDirectory))
|
||||
args.extend(extraArgs)
|
||||
return cmd, args
|
||||
|
@ -73,7 +73,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.20
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.7.15.1
|
||||
SQLITE_VERSION=3.7.15.2
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
|
@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MOCHITEST_FILES := \
|
||||
webaudio.js \
|
||||
test_bug808374.html \
|
||||
test_bug827541.html \
|
||||
test_AudioBuffer.html \
|
||||
test_AudioContext.html \
|
||||
test_AudioListener.html \
|
||||
|
25
content/media/webaudio/test/test_bug827541.html
Normal file
25
content/media/webaudio/test/test_bug827541.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tell the cycle collector about the audio contexts owned by nsGlobalWindow</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
|
||||
|
||||
var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
||||
document.body.appendChild(iframe);
|
||||
var frameWin = iframe.contentWindow;
|
||||
frameWin.mozAudioContext;
|
||||
document.body.removeChild(iframe);
|
||||
frameWin.mozAudioContext();
|
||||
|
||||
ok(true, "This test should not leak");
|
||||
SpecialPowers.clearUserPref("media.webaudio.enabled");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +1,6 @@
|
||||
This is sqlite 3.7.15.1
|
||||
This is sqlite 3.7.15.2
|
||||
|
||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 12/2012
|
||||
-- Ryan VanderMeulen <ryanvm@gmail.com>, 01/2013
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.7.15.1. By combining all the individual C code files into this
|
||||
** version 3.7.15.2. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@ -673,9 +673,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.7.15.1"
|
||||
#define SQLITE_VERSION "3.7.15.2"
|
||||
#define SQLITE_VERSION_NUMBER 3007015
|
||||
#define SQLITE_SOURCE_ID "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"
|
||||
#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -105723,7 +105723,7 @@ static void bestBtreeIndex(WhereBestIdx *p){
|
||||
pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
|
||||
WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
|
||||
bRev, pc.plan.nOBSat));
|
||||
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_UNIQUE)!=0 ){
|
||||
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
|
||||
pc.plan.wsFlags |= WHERE_ORDERED;
|
||||
}
|
||||
if( nOrderBy==pc.plan.nOBSat ){
|
||||
|
@ -107,9 +107,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.7.15.1"
|
||||
#define SQLITE_VERSION "3.7.15.2"
|
||||
#define SQLITE_VERSION_NUMBER 3007015
|
||||
#define SQLITE_SOURCE_ID "2012-12-19 20:39:10 6b85b767d0ff7975146156a99ad673f2c1a23318"
|
||||
#define SQLITE_SOURCE_ID "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
@ -1228,15 +1228,19 @@ this.DOMApplicationRegistry = {
|
||||
// "downloadapplied".
|
||||
let updateObserver = {
|
||||
observe: function(aSubject, aTopic, aObsData) {
|
||||
debug("updateHostedApp: updateSvc.checkForUpdate return for " +
|
||||
app.manifestURL + " - event is " + aTopic);
|
||||
aData.event =
|
||||
aTopic == "offline-cache-update-available" ? "downloadavailable"
|
||||
: "downloadapplied";
|
||||
aData.app.downloadAvailable = (aTopic == "downloadavailable");
|
||||
aData.app.downloadAvailable = (aData.event == "downloadavailable");
|
||||
DOMApplicationRegistry.broadcastMessage("Webapps:CheckForUpdate:Return:OK",
|
||||
aData);
|
||||
}
|
||||
}
|
||||
updateSvc.checkForUpdate(Services.io.newURI(aData.manifestURL, null, null),
|
||||
debug("updateHostedApp: updateSvc.checkForUpdate for " +
|
||||
manifest.fullAppcachePath());
|
||||
updateSvc.checkForUpdate(Services.io.newURI(manifest.fullAppcachePath(), null, null),
|
||||
app.localId, false, updateObserver);
|
||||
}
|
||||
delete app.manifest;
|
||||
@ -1287,7 +1291,9 @@ this.DOMApplicationRegistry = {
|
||||
// "downloadapplied".
|
||||
let updateObserver = {
|
||||
observe: function(aSubject, aTopic, aObsData) {
|
||||
if (aData.event == "offline-cache-update-available") {
|
||||
debug("onlyCheckAppCache updateSvc.checkForUpdate return for " +
|
||||
app.manifestURL + " - event is " + aTopic);
|
||||
if (aTopic == "offline-cache-update-available") {
|
||||
aData.event = "downloadavailable";
|
||||
app.downloadAvailable = true;
|
||||
aData.app = app;
|
||||
@ -1299,7 +1305,10 @@ this.DOMApplicationRegistry = {
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSvc.checkForUpdate(Services.io.newURI(aData.manifestURL, null, null),
|
||||
let helper = new ManifestHelper(manifest);
|
||||
debug("onlyCheckAppCache - launch updateSvc.checkForUpdate for " +
|
||||
helper.fullAppcachePath());
|
||||
updateSvc.checkForUpdate(Services.io.newURI(helper.fullAppcachePath(), null, null),
|
||||
app.localId, false, updateObserver);
|
||||
});
|
||||
return;
|
||||
@ -1312,6 +1321,7 @@ this.DOMApplicationRegistry = {
|
||||
xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||
xhr.responseType = "json";
|
||||
if (app.etag) {
|
||||
debug("adding manifest etag:" + app.etag);
|
||||
xhr.setRequestHeader("If-None-Match", app.etag);
|
||||
}
|
||||
xhr.channel.notificationCallbacks =
|
||||
@ -1333,6 +1343,7 @@ this.DOMApplicationRegistry = {
|
||||
return;
|
||||
} else {
|
||||
app.etag = xhr.getResponseHeader("Etag");
|
||||
debug("at update got app etag=" + app.etag);
|
||||
app.lastCheckedUpdate = Date.now();
|
||||
if (app.origin.startsWith("app://")) {
|
||||
updatePackagedApp.call(this, manifest);
|
||||
@ -1509,6 +1520,7 @@ this.DOMApplicationRegistry = {
|
||||
sendError("INSTALL_FROM_DENIED");
|
||||
} else {
|
||||
app.etag = xhr.getResponseHeader("Etag");
|
||||
debug("at install package got app etag=" + app.etag);
|
||||
Services.obs.notifyObservers(aMm, "webapps-ask-install",
|
||||
JSON.stringify(aData));
|
||||
}
|
||||
@ -1832,7 +1844,7 @@ this.DOMApplicationRegistry = {
|
||||
.QueryInterface(Ci.nsIHttpChannel);
|
||||
requestChannel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||
if (app.packageEtag) {
|
||||
debug('Add If-None-Match header: ' + app.packageEtag);
|
||||
debug("Add If-None-Match header: " + app.packageEtag);
|
||||
requestChannel.setRequestHeader("If-None-Match", app.packageEtag, false);
|
||||
}
|
||||
|
||||
|
@ -1293,18 +1293,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
||||
|
||||
// Traverse stuff from nsPIDOMWindow
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioContexts)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
@ -1333,20 +1331,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
|
||||
|
||||
// Unlink stuff from nsPIDOMWindow
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioContexts)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
struct TraceData
|
||||
|
@ -56,13 +56,20 @@ GlobalPCList.prototype = {
|
||||
addPC: function(pc) {
|
||||
let winID = pc._winID;
|
||||
if (this._list[winID]) {
|
||||
this._list[winID].push(pc);
|
||||
this._list[winID].push(Components.utils.getWeakReference(pc));
|
||||
} else {
|
||||
this._list[winID] = [pc];
|
||||
this._list[winID] = [Components.utils.getWeakReference(pc)];
|
||||
}
|
||||
this.removeNullRefs(winID);
|
||||
},
|
||||
|
||||
removeNullRefs: function(winID) {
|
||||
this._list[winID] = this._list[winID].filter(
|
||||
function (e,i,a) { return e.get() !== null; });
|
||||
},
|
||||
|
||||
hasActivePeerConnection: function(winID) {
|
||||
this.removeNullRefs(winID);
|
||||
return this._list[winID] ? true : false;
|
||||
},
|
||||
|
||||
@ -70,10 +77,13 @@ GlobalPCList.prototype = {
|
||||
if (topic == "inner-window-destroyed") {
|
||||
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
if (this._list[winID]) {
|
||||
this._list[winID].forEach(function(pc) {
|
||||
pc._pc.close(false);
|
||||
delete pc._observer;
|
||||
pc._pc = null;
|
||||
this._list[winID].forEach(function(pcref) {
|
||||
let pc = pcref.get();
|
||||
if (pc !== null) {
|
||||
pc._pc.close(false);
|
||||
delete pc._observer;
|
||||
pc._pc = null;
|
||||
}
|
||||
});
|
||||
delete this._list[winID];
|
||||
}
|
||||
@ -85,10 +95,13 @@ GlobalPCList.prototype = {
|
||||
// while offline, but attempts to connect them should fail.
|
||||
let array;
|
||||
while ((array = this._list.pop()) != undefined) {
|
||||
array.forEach(function(pc) {
|
||||
pc._pc.close(true);
|
||||
delete pc._observer;
|
||||
pc._pc = null;
|
||||
array.forEach(function(pcref) {
|
||||
let pc = pcref.get();
|
||||
if (pc !== null) {
|
||||
pc._pc.close(true);
|
||||
delete pc._observer;
|
||||
pc._pc = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
this._networkdown = true;
|
||||
@ -230,7 +243,9 @@ PeerConnection.prototype = {
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIDOMRTCPeerConnection, Ci.nsIDOMGlobalObjectConstructor
|
||||
Ci.nsIDOMRTCPeerConnection,
|
||||
Ci.nsIDOMGlobalObjectConstructor,
|
||||
Ci.nsISupportsWeakReference,
|
||||
]),
|
||||
|
||||
// Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
|
||||
@ -546,7 +561,8 @@ function PeerConnectionObserver(dompc) {
|
||||
this._dompc = dompc;
|
||||
}
|
||||
PeerConnectionObserver.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver]),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.IPeerConnectionObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
onCreateOfferSuccess: function(offer) {
|
||||
if (this._dompc._onCreateOfferSuccess) {
|
||||
|
@ -39,7 +39,7 @@ const kMessages =["SystemMessageManager:GetPendingMessages",
|
||||
"child-process-shutdown"]
|
||||
|
||||
function debug(aMsg) {
|
||||
//dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
|
||||
dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
|
||||
}
|
||||
|
||||
// Implementation of the component used by internal users.
|
||||
@ -48,6 +48,12 @@ function SystemMessageInternal() {
|
||||
// The set of pages registered by installed apps. We keep the
|
||||
// list of pending messages for each page here also.
|
||||
this._pages = [];
|
||||
|
||||
// The set of listeners. This is a multi-dimensional object. The _listeners
|
||||
// object itself is a map from manifest ID -> an array mapping proccesses to
|
||||
// windows. We do this so that we can track both what processes we have to
|
||||
// send system messages to as well as supporting the single-process case
|
||||
// where we track windows instead.
|
||||
this._listeners = {};
|
||||
|
||||
this._webappsRegistryReady = false;
|
||||
@ -63,6 +69,16 @@ function SystemMessageInternal() {
|
||||
Services.obs.notifyObservers(this, "system-message-internal-ready", null);
|
||||
}
|
||||
|
||||
function findTarget(aListeners, aTarget) {
|
||||
for (let i = 0; i < aListeners.length; ++i) {
|
||||
let listener = aListeners[i];
|
||||
if (listener.target === aTarget)
|
||||
return listener;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
SystemMessageInternal.prototype = {
|
||||
sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
|
||||
// Buffer system messages until the webapps' registration is ready,
|
||||
@ -189,10 +205,19 @@ SystemMessageInternal.prototype = {
|
||||
case "SystemMessageManager:Register":
|
||||
{
|
||||
debug("Got Register from " + msg.manifest);
|
||||
if (!this._listeners[msg.manifest]) {
|
||||
this._listeners[msg.manifest] = {};
|
||||
let targets, target;
|
||||
if (!(targets = this._listeners[msg.manifest])) {
|
||||
this._listeners[msg.manifest] =
|
||||
[ { target: aMessage.target, winCount: 1 } ];
|
||||
} else if (!(target = findTarget(targets, aMessage.target))) {
|
||||
targets[msg.manifest].push({
|
||||
target: aMessage.target,
|
||||
winCount: 1
|
||||
});
|
||||
} else {
|
||||
target.winCount++;
|
||||
}
|
||||
this._listeners[msg.manifest][msg.innerWindowID] = aMessage.target;
|
||||
|
||||
debug("listeners for " + msg.manifest + " innerWinID " + msg.innerWindowID);
|
||||
break;
|
||||
}
|
||||
@ -200,11 +225,20 @@ SystemMessageInternal.prototype = {
|
||||
{
|
||||
debug("Got child-process-shutdown from " + aMessage.target);
|
||||
for (let manifest in this._listeners) {
|
||||
for (let winID in this._listeners[manifest]) {
|
||||
if (aMessage.target === this._listeners[manifest][winID]) {
|
||||
debug("remove " + manifest );
|
||||
delete this._listeners[manifest];
|
||||
return;
|
||||
// See if any processes in this manifest have this target.
|
||||
let targets = this._listeners[manifest];
|
||||
for (let target = 0; target < targets.length; ++target) {
|
||||
if (targets[target].target === aMessage.target) {
|
||||
// One does: if it's the only one, get rid of this manifest
|
||||
// entirely.
|
||||
if (targets.length === 1) {
|
||||
debug("remove " + manifest );
|
||||
delete this._listeners[manifest];
|
||||
} else {
|
||||
// There are other targets for this manifest, get rid of this
|
||||
// one.
|
||||
targets.splice(target, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,7 +247,22 @@ SystemMessageInternal.prototype = {
|
||||
case "SystemMessageManager:Unregister":
|
||||
{
|
||||
debug("Got Unregister from " + aMessage.target + "innerWinID " + msg.innerWindowID);
|
||||
delete this._listeners[msg.manifest][msg.innerWindowID];
|
||||
let targets = this._listeners[msg.manifest];
|
||||
for (let i = 0; i < targets.length; ++i) {
|
||||
if (targets[i].target === aMessage.target) {
|
||||
if (--targets[i].winCount === 0) {
|
||||
if (targets.length === 1) {
|
||||
// Only one listener left, remove the target.
|
||||
delete this._listeners[msg.manifest];
|
||||
} else {
|
||||
// More than one left, remove this one and leave the rest.
|
||||
targets.splice(i, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("Removing " + aMessage.target + "innerWinID " + msg.innerWindowID );
|
||||
|
||||
break;
|
||||
@ -391,13 +440,14 @@ SystemMessageInternal.prototype = {
|
||||
|
||||
let winTargets = this._listeners[aManifestURI];
|
||||
if (winTargets) {
|
||||
for (let winID in winTargets) {
|
||||
winTargets[winID].sendAsyncMessage("SystemMessageManager:Message",
|
||||
{ type: aType,
|
||||
msg: aMessage,
|
||||
manifest: aManifestURI,
|
||||
uri: aPageURI,
|
||||
msgID: aMessageID });
|
||||
for (let target = 0; target < winTargets.length; ++target) {
|
||||
let manager = winTargets[target].target;
|
||||
manager.sendAsyncMessage("SystemMessageManager:Message",
|
||||
{ type: aType,
|
||||
msg: aMessage,
|
||||
manifest: aManifestURI,
|
||||
uri: aPageURI,
|
||||
msgID: aMessageID });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,204 +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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
var gLoggingEnabled = false;
|
||||
|
||||
function LOG(aMsg) {
|
||||
if (gLoggingEnabled)
|
||||
{
|
||||
aMsg = ("*** GPSD GEO: " + aMsg);
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
|
||||
dump(aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
function GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed) {
|
||||
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude = altitude;
|
||||
this.accuracy = accuracy;
|
||||
this.altitudeAccuracy = altitudeAccuracy;
|
||||
this.heading = heading;
|
||||
this.speed = speed;
|
||||
|
||||
};
|
||||
|
||||
GeoPositionCoordsObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords]),
|
||||
|
||||
// Class Info is required to be able to pass objects back into the DOM.
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPositionCoords],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Geoposition Coordinate Object"}),
|
||||
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
altitude: null,
|
||||
accuracy: null,
|
||||
altitudeAccuracy: null,
|
||||
heading: null,
|
||||
speed: null,
|
||||
|
||||
};
|
||||
|
||||
function GeoPositionObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed, timestamp) {
|
||||
this.coords = new GeoPositionCoordsObject(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed);
|
||||
this.timestamp = timestamp;
|
||||
};
|
||||
|
||||
GeoPositionObject.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPosition]),
|
||||
|
||||
// Class Info is required to be able to pass objects back into the DOM.
|
||||
classInfo: XPCOMUtils.generateCI({interfaces: [Ci.nsIDOMGeoPosition],
|
||||
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
||||
classDescription: "Geoposition Object"}),
|
||||
|
||||
coords: null,
|
||||
timestamp: null,
|
||||
|
||||
};
|
||||
|
||||
function GPSDProvider() {
|
||||
this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch).QueryInterface(Ci.nsIPrefService);
|
||||
|
||||
try {
|
||||
gLoggingEnabled = this.prefService.getBoolPref("geo.gpsd.logging.enabled");
|
||||
} catch (e) {}
|
||||
};
|
||||
|
||||
GPSDProvider.prototype = {
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider]),
|
||||
|
||||
classID: Components.ID("{0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D}"),
|
||||
|
||||
prefService: null,
|
||||
|
||||
transport: null,
|
||||
outputStream: null,
|
||||
inputStream: null,
|
||||
|
||||
startup: function() {
|
||||
|
||||
LOG("startup called\n");
|
||||
var socketTransportService = Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci.nsISocketTransportService);
|
||||
|
||||
var hostIPAddr = "127.0.0.1";
|
||||
var hostPort = "2947";
|
||||
|
||||
try {
|
||||
hostIPAddr = this.prefService.getCharPref("geo.gpsd.host.ipaddr");
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
hostPort = this.prefService.getCharPref("geo.gpsd.host.port");
|
||||
} catch (e) {}
|
||||
|
||||
LOG("Host info: " + hostIPAddr + ":" + hostPort + "\n");
|
||||
|
||||
this.transport = socketTransportService.createTransport(null, 0, hostIPAddr, hostPort, null);
|
||||
|
||||
// Alright to open streams here as they are non-blocking by default
|
||||
this.outputStream = this.transport.openOutputStream(0,0,0);
|
||||
this.inputStream = this.transport.openInputStream(0,0,0);
|
||||
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
LOG("shutdown called\n");
|
||||
this.outputStream.close();
|
||||
this.inputStream.close();
|
||||
this.transport.close(Components.results.NS_OK);
|
||||
},
|
||||
|
||||
watch: function(c, isPrivate) {
|
||||
LOG("watch called\n");
|
||||
try {
|
||||
// Go into "watcher" mode
|
||||
var mode = '?WATCH={"enable":true,"json":true}';
|
||||
this.outputStream.write(mode, mode.length);
|
||||
} catch (e) { return; }
|
||||
|
||||
var dataListener = {
|
||||
onStartRequest: function(request, context) {},
|
||||
onStopRequest: function(request, context, status) {},
|
||||
onDataAvailable: function(request, context, inputStream, offset, count) {
|
||||
|
||||
var sInputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
|
||||
sInputStream.init(inputStream);
|
||||
|
||||
var responseSentence = sInputStream.read(count);
|
||||
|
||||
var response = null;
|
||||
try {
|
||||
response = JSON.parse(responseSentence);
|
||||
} catch (e) { return; }
|
||||
|
||||
// is the right kind of sentence?
|
||||
if (response.class != 'TPV') {
|
||||
//don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
// is there a fix?
|
||||
if (response.mode == '1') {
|
||||
// don't do anything
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Got info: " + responseSentence);
|
||||
|
||||
// The API requires these values, if one is missing
|
||||
// we return without updating the position.
|
||||
if (response.time && response.lat && response.lon
|
||||
&& response.epx && response.epy) {
|
||||
var timestamp = response.time; // UTC
|
||||
var latitude = response.lat; // degrees
|
||||
var longitude = response.lon; // degrees
|
||||
var horizontalError = Math.max(response.epx,response.epy); } // meters
|
||||
else { return; }
|
||||
|
||||
// Altitude is optional, but if it's present, so must be vertical precision.
|
||||
var altitude = null;
|
||||
var verticalError = null;
|
||||
if (response.alt && response.epv) {
|
||||
altitude = response.alt; // meters
|
||||
verticalError = response.epv; // meters
|
||||
}
|
||||
|
||||
var speed = null;
|
||||
if (response.speed) { var speed = response.speed; } // meters/sec
|
||||
|
||||
var course = null;
|
||||
if (response.track) { var course = response.track; } // degrees
|
||||
|
||||
var geoPos = new GeoPositionObject(latitude, longitude, altitude, horizontalError, verticalError, course, speed, timestamp);
|
||||
|
||||
c.update(geoPos);
|
||||
LOG("Position updated:" + timestamp + "," + latitude + "," + longitude + ","
|
||||
+ horizontalError + "," + altitude + "," + verticalError + "," + course
|
||||
+ "," + speed);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var pump = Cc["@mozilla.org/network/input-stream-pump;1"].createInstance(Ci.nsIInputStreamPump);
|
||||
pump.init(this.inputStream, -1, -1, 0, 0, false);
|
||||
pump.asyncRead(dataListener, null);
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([GPSDProvider]);
|
@ -1,3 +0,0 @@
|
||||
component {0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D} GPSDGeolocationProvider.js
|
||||
contract @mozilla.org/geolocation/gpsd/provider;1 {0A3BE523-0F2A-32CC-CCD8-1E5986D5A79D}
|
||||
category geolocation-provider GPSDProvider @mozilla.org/geolocation/gpsd/provider;1
|
@ -55,8 +55,6 @@ ifneq (Android,$(OS_TARGET))
|
||||
EXTRA_COMPONENTS = \
|
||||
NetworkGeolocationProvider.js \
|
||||
NetworkGeolocationProvider.manifest \
|
||||
GPSDGeolocationProvider.js \
|
||||
GPSDGeolocationProvider.manifest \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -2799,7 +2799,7 @@ DrawTargetD2D::PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID
|
||||
D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE;
|
||||
D2D1_LAYER_OPTIONS1 options1 = D2D1_LAYER_OPTIONS1_NONE;
|
||||
|
||||
if (mFormat == FORMAT_B8G8R8X8) {
|
||||
if (aRT->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE) {
|
||||
options = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE;
|
||||
options1 = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ ImageContainer::SetCurrentImage(Image *aImage)
|
||||
if (aImage) {
|
||||
mImageContainerChild->SendImageAsync(this, aImage);
|
||||
} else {
|
||||
mImageContainerChild->DispatchSetIdle();
|
||||
mImageContainerChild->SetIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,12 +73,33 @@ void ImageContainerChild::SetIdleNow()
|
||||
mImageQueue.Clear();
|
||||
}
|
||||
|
||||
void ImageContainerChild::DispatchSetIdle()
|
||||
void ImageContainerChild::SetIdleSync(Monitor* aBarrier, bool* aDone)
|
||||
{
|
||||
MonitorAutoLock autoMon(*aBarrier);
|
||||
|
||||
SetIdleNow();
|
||||
*aDone = true;
|
||||
aBarrier->NotifyAll();
|
||||
}
|
||||
|
||||
void ImageContainerChild::SetIdle()
|
||||
{
|
||||
if (mStop) return;
|
||||
|
||||
if (InImageBridgeChildThread()) {
|
||||
return SetIdleNow();
|
||||
}
|
||||
|
||||
Monitor barrier("SetIdle Lock");
|
||||
MonitorAutoLock autoMon(barrier);
|
||||
bool done = false;
|
||||
|
||||
GetMessageLoop()->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &ImageContainerChild::SetIdleNow));
|
||||
NewRunnableMethod(this, &ImageContainerChild::SetIdleSync, &barrier, &done));
|
||||
|
||||
while (!done) {
|
||||
barrier.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageContainerChild::StopChildAndParent()
|
||||
|
@ -106,16 +106,9 @@ public:
|
||||
void DispatchDestroy();
|
||||
|
||||
/**
|
||||
* Dispatches a task on the ImageBridgeChild's thread that will call SendFlush
|
||||
* and deallocate the shared images in the pool.
|
||||
* Can be called on any thread.
|
||||
* Flush and deallocate the shared images in the pool.
|
||||
*/
|
||||
void DispatchSetIdle();
|
||||
|
||||
/**
|
||||
* Must be called on the ImageBridgeChild's thread.
|
||||
*/
|
||||
void SetIdleNow();
|
||||
void SetIdle();
|
||||
|
||||
/**
|
||||
* Can be called from any thread.
|
||||
@ -168,9 +161,21 @@ protected:
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called on the ImageBridgeCHild's thread.
|
||||
* Must be called on the ImageBridgeChild's thread.
|
||||
*/
|
||||
void DestroyNow();
|
||||
|
||||
/**
|
||||
* Dispatches a task on the ImageBridgeChild's thread that will call SendFlush
|
||||
* and deallocate the shared images in the pool.
|
||||
* Can be called on any thread.
|
||||
*/
|
||||
void SetIdleSync(Monitor* aBarrier, bool* aDone);
|
||||
|
||||
/**
|
||||
* Must be called on the ImageBridgeChild's thread.
|
||||
*/
|
||||
void SetIdleNow();
|
||||
|
||||
inline void SetID(uint64_t id)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ parent:
|
||||
|
||||
// Tells the parent side to dispose of its shared images (most likely because the
|
||||
// video element is still alive but will not be displayed for a moment).
|
||||
async Flush();
|
||||
sync Flush();
|
||||
|
||||
// After receiving this message, the ImageContainerParent will not return images
|
||||
// back to the child side (to avoid a race between ReturnImage and __delete__)
|
||||
|
@ -915,19 +915,20 @@ jsdProperty::GetValue(jsdIValue **_rval)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
|
||||
|
||||
static NS_IMETHODIMP
|
||||
AssignToJSString(nsACString *x, JSString *str)
|
||||
AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str)
|
||||
{
|
||||
if (!str) {
|
||||
x->SetLength(0);
|
||||
return NS_OK;
|
||||
}
|
||||
size_t length = JS_GetStringEncodingLength(NULL, str);
|
||||
JSContext *cx = JSD_GetDefaultJSContext(aCx);
|
||||
size_t length = JS_GetStringEncodingLength(cx, str);
|
||||
if (length == size_t(-1))
|
||||
return NS_ERROR_FAILURE;
|
||||
x->SetLength(uint32_t(length));
|
||||
if (x->Length() != uint32_t(length))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_EncodeStringToBuffer(str, x->BeginWriting(), length);
|
||||
JS_EncodeStringToBuffer(cx, str, x->BeginWriting(), length);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -953,7 +954,7 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(false),
|
||||
if (mFunctionName) {
|
||||
JSString *str = JSD_GetScriptFunctionId(mCx, mScript);
|
||||
if (str)
|
||||
AssignToJSString(mFunctionName, str);
|
||||
AssignToJSString(mCx, mFunctionName, str);
|
||||
}
|
||||
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
||||
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
|
||||
@ -1908,7 +1909,7 @@ jsdStackFrame::GetFunctionName(nsACString &_rval)
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
JSString *str = JSD_GetIdForStackFrame(mCx, mThreadState, mStackFrameInfo);
|
||||
if (str)
|
||||
return AssignToJSString(&_rval, str);
|
||||
return AssignToJSString(mCx, &_rval, str);
|
||||
|
||||
_rval.Assign("anonymous");
|
||||
return NS_OK;
|
||||
@ -2238,7 +2239,7 @@ NS_IMETHODIMP
|
||||
jsdValue::GetJsFunctionName(nsACString &_rval)
|
||||
{
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
return AssignToJSString(&_rval, JSD_GetValueFunctionId(mCx, mValue));
|
||||
return AssignToJSString(mCx, &_rval, JSD_GetValueFunctionId(mCx, mValue));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
126
js/public/CharacterEncoding.h
Normal file
126
js/public/CharacterEncoding.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* 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 js_CharacterEncoding_h___
|
||||
#define js_CharacterEncoding_h___
|
||||
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* By default, all C/C++ 1-byte-per-character strings passed into the JSAPI
|
||||
* are treated as ISO/IEC 8859-1, also known as Latin-1. That is, each
|
||||
* byte is treated as a 2-byte character, and there is no way to pass in a
|
||||
* string containing characters beyond U+00FF.
|
||||
*/
|
||||
class Latin1Chars : public mozilla::Range<unsigned char>
|
||||
{
|
||||
typedef mozilla::Range<unsigned char> Base;
|
||||
|
||||
public:
|
||||
Latin1Chars() : Base() {}
|
||||
Latin1Chars(char *bytes, size_t length) : Base(reinterpret_cast<unsigned char *>(bytes), length) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* A Latin1Chars, but with \0 termination for C compatibility.
|
||||
*/
|
||||
class Latin1CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||
{
|
||||
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||
|
||||
public:
|
||||
Latin1CharsZ() : Base(NULL, 0) {}
|
||||
|
||||
Latin1CharsZ(char *bytes, size_t length)
|
||||
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
|
||||
Latin1CharsZ(unsigned char *bytes, size_t length)
|
||||
: Base(bytes, length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
|
||||
char *c_str() { return reinterpret_cast<char *>(get()); }
|
||||
};
|
||||
|
||||
/*
|
||||
* SpiderMonkey also deals directly with UTF-8 encoded text in some places.
|
||||
*/
|
||||
class UTF8CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||
{
|
||||
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||
|
||||
public:
|
||||
UTF8CharsZ() : Base(NULL, 0) {}
|
||||
|
||||
UTF8CharsZ(char *bytes, size_t length)
|
||||
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* SpiderMonkey uses a 2-byte character representation: it is a
|
||||
* 2-byte-at-a-time view of a UTF-16 byte stream. This is similar to UCS-2,
|
||||
* but unlike UCS-2, we do not strip UTF-16 extension bytes. This allows a
|
||||
* sufficiently dedicated JavaScript program to be fully unicode-aware by
|
||||
* manually interpreting UTF-16 extension characters embedded in the JS
|
||||
* string.
|
||||
*/
|
||||
class TwoByteChars : public mozilla::Range<jschar>
|
||||
{
|
||||
typedef mozilla::Range<jschar> Base;
|
||||
|
||||
public:
|
||||
TwoByteChars() : Base() {}
|
||||
TwoByteChars(jschar *chars, size_t length) : Base(chars, length) {}
|
||||
TwoByteChars(const jschar *chars, size_t length) : Base(const_cast<jschar *>(chars), length) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* A TwoByteChars, but \0 terminated for compatibility with JSFlatString.
|
||||
*/
|
||||
class TwoByteCharsZ : public mozilla::RangedPtr<jschar>
|
||||
{
|
||||
typedef mozilla::RangedPtr<jschar> Base;
|
||||
|
||||
public:
|
||||
TwoByteCharsZ(jschar *chars, size_t length)
|
||||
: Base(chars, length)
|
||||
{
|
||||
JS_ASSERT(chars[length] = '\0');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert a 2-byte character sequence to "ISO-Latin-1". This works by
|
||||
* truncating each 2-byte pair in the sequence to a 1-byte pair. If the source
|
||||
* contains any UTF-16 extension characters, then this may give invalid Latin1
|
||||
* output. The returned string is zero terminated. The returned string or the
|
||||
* returned string's |start()| must be freed with JS_free or js_free,
|
||||
* respectively. If allocation fails, an OOM error will be set and the method
|
||||
* will return a NULL chars (which can be tested for with the ! operator).
|
||||
* This method cannot trigger GC.
|
||||
*/
|
||||
extern Latin1CharsZ
|
||||
LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
inline void JS_free(JS::Latin1CharsZ &ptr) { js_free((void*)ptr.get()); }
|
||||
|
||||
#endif // js_CharacterEncoding_h___
|
@ -127,6 +127,7 @@ CPPSRCS = \
|
||||
String.cpp \
|
||||
BytecodeCompiler.cpp \
|
||||
BytecodeEmitter.cpp \
|
||||
CharacterEncoding.cpp \
|
||||
FoldConstants.cpp \
|
||||
Intl.cpp \
|
||||
NameFunctions.cpp \
|
||||
@ -216,6 +217,7 @@ EXPORTS_NAMESPACES += js
|
||||
# that we ensure we don't over-expose our internal integer typedefs. Note that
|
||||
# LegacyIntTypes.h below is deliberately exempted from this requirement.
|
||||
EXPORTS_js = \
|
||||
CharacterEncoding.h \
|
||||
HashTable.h \
|
||||
HeapAPI.h \
|
||||
LegacyIntTypes.h \
|
||||
|
@ -9,6 +9,7 @@
|
||||
from __future__ import with_statement
|
||||
from optparse import OptionParser
|
||||
import sys, re, os, posixpath, ntpath
|
||||
import errno
|
||||
from StringIO import StringIO
|
||||
# Standalone js doesn't have virtualenv.
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
|
||||
|
@ -159,7 +159,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp)
|
||||
int valcnt = 0;
|
||||
if (shape) {
|
||||
bool doGet = true;
|
||||
if (obj2->isNative() && !IsImplicitProperty(shape)) {
|
||||
if (obj2->isNative() && !IsImplicitDenseElement(shape)) {
|
||||
unsigned attrs = shape->attributes();
|
||||
if (attrs & JSPROP_GETTER) {
|
||||
doGet = false;
|
||||
@ -456,7 +456,7 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp)
|
||||
return JS_FALSE;
|
||||
args.rval().setUndefined();
|
||||
if (shape) {
|
||||
if (pobj->isNative() && !IsImplicitProperty(shape)) {
|
||||
if (pobj->isNative() && !IsImplicitDenseElement(shape)) {
|
||||
if (shape->hasGetterValue())
|
||||
args.rval().set(shape->getterValue());
|
||||
}
|
||||
@ -492,7 +492,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
|
||||
return JS_FALSE;
|
||||
args.rval().setUndefined();
|
||||
if (shape) {
|
||||
if (pobj->isNative() && !IsImplicitProperty(shape)) {
|
||||
if (pobj->isNative() && !IsImplicitDenseElement(shape)) {
|
||||
if (shape->hasSetterValue())
|
||||
args.rval().set(shape->setterValue());
|
||||
}
|
||||
|
@ -1747,7 +1747,7 @@ ParallelArrayObject::lookupElement(JSContext *cx, HandleObject obj, uint32_t ind
|
||||
{
|
||||
// No prototype walking for elements.
|
||||
if (index < as(obj)->outermostDimension()) {
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkNonNativePropertyFound(propp);
|
||||
objp.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matc
|
||||
}
|
||||
|
||||
RegExpRunStatus
|
||||
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObject ®exp,
|
||||
ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
|
||||
JSLinearString *input, StableCharPtr chars, size_t length,
|
||||
size_t *lastIndex, MatchConduit &matches)
|
||||
{
|
||||
@ -126,7 +126,7 @@ ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re, RegExpObj
|
||||
/* Only one MatchPair slot provided: execute short-circuiting regexp. */
|
||||
status = re.executeMatchOnly(cx, chars, length, lastIndex, *matches.u.pair);
|
||||
if (status == RegExpRunStatus_Success && res)
|
||||
res->updateLazily(cx, input, ®exp, lastIndex_orig);
|
||||
res->updateLazily(cx, input, &re, lastIndex_orig);
|
||||
} else {
|
||||
/* Vector of MatchPairs provided: execute full regexp. */
|
||||
status = re.execute(cx, chars, length, lastIndex, *matches.u.pairs);
|
||||
@ -151,7 +151,7 @@ js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
|
||||
MatchConduit conduit(&matches);
|
||||
|
||||
RegExpRunStatus status =
|
||||
ExecuteRegExpImpl(cx, res, *shared, reobj, input, chars, length, lastIndex, conduit);
|
||||
ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);
|
||||
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
@ -580,7 +580,7 @@ js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, Match
|
||||
/* Steps 8-21. */
|
||||
size_t lastIndexInt(i);
|
||||
RegExpRunStatus status =
|
||||
ExecuteRegExpImpl(cx, res, *re, *reobj, stableInput, chars, length, &lastIndexInt, matches);
|
||||
ExecuteRegExpImpl(cx, res, *re, stableInput, chars, length, &lastIndexInt, matches);
|
||||
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return RegExpRunStatus_Error;
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/Keywords.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
@ -564,7 +565,8 @@ TokenStream::reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned
|
||||
err.report.uclinebuf = windowBuf.extractWellSized();
|
||||
if (!err.report.uclinebuf)
|
||||
return false;
|
||||
err.report.linebuf = DeflateString(cx, err.report.uclinebuf, windowLength);
|
||||
TwoByteChars tbchars(err.report.uclinebuf, windowLength);
|
||||
err.report.linebuf = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (!err.report.linebuf)
|
||||
return false;
|
||||
|
||||
@ -728,7 +730,8 @@ TokenStream::getXMLEntity()
|
||||
bad:
|
||||
/* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
|
||||
JS_ASSERT((tb.end() - bp) >= 1);
|
||||
bytes = DeflateString(cx, bp + 1, (tb.end() - bp) - 1);
|
||||
TwoByteChars tbchars(bp + 1, (tb.end() - bp) - 1);
|
||||
bytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (bytes) {
|
||||
reportError(msg, bytes);
|
||||
js_free(bytes);
|
||||
|
@ -339,7 +339,6 @@ DeclMarkerImpl(Object, DebugScopeObject)
|
||||
DeclMarkerImpl(Object, GlobalObject)
|
||||
DeclMarkerImpl(Object, JSObject)
|
||||
DeclMarkerImpl(Object, JSFunction)
|
||||
DeclMarkerImpl(Object, RegExpObject)
|
||||
DeclMarkerImpl(Object, ScopeObject)
|
||||
DeclMarkerImpl(Script, JSScript)
|
||||
DeclMarkerImpl(Shape, Shape)
|
||||
|
@ -97,7 +97,6 @@ DeclMarker(Object, DebugScopeObject)
|
||||
DeclMarker(Object, GlobalObject)
|
||||
DeclMarker(Object, JSObject)
|
||||
DeclMarker(Object, JSFunction)
|
||||
DeclMarker(Object, RegExpObject)
|
||||
DeclMarker(Object, ScopeObject)
|
||||
DeclMarker(Script, JSScript)
|
||||
DeclMarker(Shape, Shape)
|
||||
|
@ -562,10 +562,8 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
}
|
||||
|
||||
case REGEXPSTATICS: {
|
||||
/*
|
||||
RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
|
||||
rooter->trace(trc);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
@ -646,15 +644,14 @@ Shape::Range::AutoRooter::trace(JSTracer *trc)
|
||||
void
|
||||
RegExpStatics::AutoRooter::trace(JSTracer *trc)
|
||||
{
|
||||
if (statics->regexp)
|
||||
MarkObjectRoot(trc, reinterpret_cast<JSObject**>(&statics->regexp),
|
||||
"RegExpStatics::AutoRooter regexp");
|
||||
if (statics->matchesInput)
|
||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchesInput),
|
||||
"RegExpStatics::AutoRooter matchesInput");
|
||||
if (statics->pendingInput)
|
||||
MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
|
||||
"RegExpStatics::AutoRooter pendingInput");
|
||||
if (statics->regexp.initialized())
|
||||
statics->regexp->trace(trc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1435,6 +1435,9 @@ IsPropertySetterCallInlineable(JSContext *cx, HandleObject obj, HandleObject hol
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
if (!holder->isNative())
|
||||
return false;
|
||||
|
||||
if (shape->hasSlot())
|
||||
return false;
|
||||
|
||||
|
5
js/src/jit-test/tests/basic/bug820124-1.js
Normal file
5
js/src/jit-test/tests/basic/bug820124-1.js
Normal file
@ -0,0 +1,5 @@
|
||||
// Don't assert.
|
||||
verifyprebarriers();
|
||||
r = /()()()\3/.test();
|
||||
gc();
|
||||
RegExp().test();
|
3
js/src/jit-test/tests/basic/bug820124-2.js
Normal file
3
js/src/jit-test/tests/basic/bug820124-2.js
Normal file
@ -0,0 +1,3 @@
|
||||
// Don't assert.
|
||||
'123456'.replace(/1(\d+)3/, '');
|
||||
RegExp.lastMatch.toString();
|
8
js/src/jit-test/tests/basic/bug820124-3.js
Normal file
8
js/src/jit-test/tests/basic/bug820124-3.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Don't assert.
|
||||
eval("\
|
||||
x = RegExp(\"()\", \"y\");\
|
||||
x.test();\
|
||||
x = {};\
|
||||
")
|
||||
gc()
|
||||
RegExp.$6
|
8
js/src/jit-test/tests/basic/bug820124-4.js
Normal file
8
js/src/jit-test/tests/basic/bug820124-4.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Don't assert.
|
||||
eval("\
|
||||
r = RegExp(\"(?!()(((!))))\", \"g\");\
|
||||
\"^\".replace(r, '');\
|
||||
r = (\"1+\")\
|
||||
")
|
||||
gc()
|
||||
RegExp.$8
|
7
js/src/jit-test/tests/basic/bug829795.js
Normal file
7
js/src/jit-test/tests/basic/bug829795.js
Normal file
@ -0,0 +1,7 @@
|
||||
// |jit-test| error: TypeError
|
||||
|
||||
try {
|
||||
x = [];
|
||||
Array.prototype.forEach()
|
||||
} catch (e) {}
|
||||
x.forEach()
|
10
js/src/jit-test/tests/basic/bug830049.js
Normal file
10
js/src/jit-test/tests/basic/bug830049.js
Normal file
@ -0,0 +1,10 @@
|
||||
// |jit-test| error: InternalError
|
||||
|
||||
p = Proxy.create({
|
||||
has: function() function r() s += ''
|
||||
})
|
||||
Object.prototype.__proto__ = p
|
||||
function TestCase(n) {
|
||||
this.name = n
|
||||
}
|
||||
new TestCase()
|
@ -68,6 +68,7 @@ CPPSRCS = \
|
||||
testStringBuffer.cpp \
|
||||
testTrap.cpp \
|
||||
testTypedArrays.cpp \
|
||||
testUTF8.cpp \
|
||||
testVersion.cpp \
|
||||
testXDR.cpp \
|
||||
$(NULL)
|
||||
|
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "tests.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsstr.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
BEGIN_TEST(testUTF8_badUTF8)
|
||||
{
|
||||
static const char badUTF8[] = "...\xC0...";
|
||||
JSString *str = JS_NewStringCopyZ(cx, badUTF8);
|
||||
CHECK(str);
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||
CHECK(chars);
|
||||
CHECK(chars[3] == 0x00C0);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_badUTF8)
|
||||
|
||||
BEGIN_TEST(testUTF8_bigUTF8)
|
||||
{
|
||||
static const char bigUTF8[] = "...\xFB\xBF\xBF\xBF\xBF...";
|
||||
JSString *str = JS_NewStringCopyZ(cx, bigUTF8);
|
||||
CHECK(str);
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||
CHECK(chars);
|
||||
CHECK(chars[3] == 0x00FB);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_bigUTF8)
|
||||
|
||||
BEGIN_TEST(testUTF8_badSurrogate)
|
||||
{
|
||||
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
||||
JS::TwoByteChars tbchars(badSurrogate, js_strlen(badSurrogate));
|
||||
JS::Latin1CharsZ latin1 = JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
|
||||
CHECK(latin1);
|
||||
CHECK(latin1[3] == 0x00EE);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_badSurrogate)
|
@ -64,6 +64,7 @@
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Memory.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/NumericConversions.h"
|
||||
@ -3572,7 +3573,7 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (!obj2->isNative()) {
|
||||
if (obj2->isProxy()) {
|
||||
AutoPropertyDescriptorRooter desc(cx);
|
||||
if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc, 0))
|
||||
@ -3581,10 +3582,10 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id,
|
||||
*vp = desc.value;
|
||||
return true;
|
||||
}
|
||||
} else if (obj2->isNative()) {
|
||||
*vp = obj2->getDenseElement(JSID_TO_INT(id));
|
||||
return true;
|
||||
}
|
||||
} else if (IsImplicitDenseElement(shape)) {
|
||||
*vp = obj2->getDenseElement(JSID_TO_INT(id));
|
||||
return true;
|
||||
} else {
|
||||
/* Peek at the native property's slot value, without doing a Get. */
|
||||
if (shape->hasSlot()) {
|
||||
@ -4062,7 +4063,7 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned
|
||||
|
||||
desc->obj = obj2;
|
||||
if (obj2->isNative()) {
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
desc->attrs = JSPROP_ENUMERATE;
|
||||
desc->getter = NULL;
|
||||
desc->setter = NULL;
|
||||
@ -6231,27 +6232,24 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(char *)
|
||||
JS_EncodeString(JSContext *cx, JSRawString strArg)
|
||||
JS_EncodeString(JSContext *cx, JSRawString str)
|
||||
{
|
||||
RootedString str(cx, strArg);
|
||||
|
||||
AutoAssertNoGC nogc;
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
JSLinearString *linear = str->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, chars, str->length());
|
||||
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||
{
|
||||
/* jsd calls us with a NULL cx. Ugh. */
|
||||
if (cx) {
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
}
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
@ -6260,8 +6258,11 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
|
||||
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
/*
|
||||
* FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
|
||||
* would allow to distinguish between insufficient buffer and encoding
|
||||
|
@ -5554,7 +5554,7 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str);
|
||||
* written into the buffer.
|
||||
*/
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length);
|
||||
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length);
|
||||
|
||||
class JSAutoByteString
|
||||
{
|
||||
|
@ -23,6 +23,8 @@
|
||||
# include <string>
|
||||
#endif // ANDROID
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsclist.h"
|
||||
@ -55,6 +57,7 @@
|
||||
# include "methodjit/MethodJIT.h"
|
||||
#endif
|
||||
#include "gc/Marking.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "frontend/ParseMaps.h"
|
||||
@ -69,6 +72,7 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::PointerRangeSize;
|
||||
|
||||
bool
|
||||
js::AutoCycleDetector::init()
|
||||
@ -832,8 +836,10 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
JS_ASSERT(expandedArgs == argCount);
|
||||
*out = 0;
|
||||
js_free(buffer);
|
||||
*messagep = DeflateString(cx, reportp->ucmessage,
|
||||
size_t(out - reportp->ucmessage));
|
||||
TwoByteChars ucmsg(reportp->ucmessage,
|
||||
PointerRangeSize(static_cast<const jschar *>(reportp->ucmessage),
|
||||
static_cast<const jschar *>(out)));
|
||||
*messagep = LossyTwoByteCharsToNewLatin1CharsZ(cx, ucmsg).c_str();
|
||||
if (!*messagep)
|
||||
goto error;
|
||||
}
|
||||
|
@ -291,13 +291,13 @@ MakeTypeId(JSContext *cx, jsid id)
|
||||
*/
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSFlatString *str = JSID_TO_FLAT_STRING(id);
|
||||
const jschar *cp = str->getCharsZ(cx);
|
||||
if (JS7_ISDEC(*cp) || *cp == '-') {
|
||||
cp++;
|
||||
while (JS7_ISDEC(*cp))
|
||||
cp++;
|
||||
if (*cp == 0)
|
||||
return JSID_VOID;
|
||||
TwoByteChars cp = str->range();
|
||||
if (JS7_ISDEC(cp[0]) || cp[0] == '-') {
|
||||
for (size_t i = 1; i < cp.length(); ++i) {
|
||||
if (!JS7_ISDEC(cp[i]))
|
||||
return id;
|
||||
}
|
||||
return JSID_VOID;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
@ -1103,7 +1103,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
|
||||
if (prop) {
|
||||
unsigned attrs;
|
||||
if (obj2->isNative())
|
||||
attrs = IsImplicitProperty(prop) ? JSPROP_ENUMERATE : prop->attributes();
|
||||
attrs = GetShapeAttributes(prop);
|
||||
else if (!JSObject::getGenericAttributes(cx, obj2, id, &attrs))
|
||||
return false;
|
||||
|
||||
|
@ -631,7 +631,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
||||
shapeHasGetterValue = false,
|
||||
shapeHasSetterValue = false;
|
||||
uint8_t shapeAttributes = JSPROP_ENUMERATE;
|
||||
if (!IsImplicitProperty(shape)) {
|
||||
if (!IsImplicitDenseElement(shape)) {
|
||||
shapeDataDescriptor = shape->isDataDescriptor();
|
||||
shapeAccessorDescriptor = shape->isAccessorDescriptor();
|
||||
shapeWritable = shape->writable();
|
||||
@ -672,7 +672,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
||||
* avoid calling a getter; we won't need the value if it's not a
|
||||
* data descriptor.
|
||||
*/
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
v = obj->getDenseElement(JSID_TO_INT(id));
|
||||
} else if (shape->isDataDescriptor()) {
|
||||
/*
|
||||
@ -814,8 +814,8 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
||||
changed |= JSPROP_ENUMERATE;
|
||||
|
||||
attrs = (shapeAttributes & ~changed) | (desc.attributes() & changed);
|
||||
getter = IsImplicitProperty(shape) ? JS_PropertyStub : shape->getter();
|
||||
setter = IsImplicitProperty(shape) ? JS_StrictPropertyStub : shape->setter();
|
||||
getter = IsImplicitDenseElement(shape) ? JS_PropertyStub : shape->getter();
|
||||
setter = IsImplicitDenseElement(shape) ? JS_StrictPropertyStub : shape->setter();
|
||||
} else if (desc.isDataDescriptor()) {
|
||||
unsigned unchanged = 0;
|
||||
if (!desc.hasConfigurable())
|
||||
@ -3064,7 +3064,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
if (!baseops::LookupProperty(cx, obj, id, &pobj, &shape))
|
||||
return false;
|
||||
if (shape && pobj == obj) {
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
if (!JSObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
|
||||
return false;
|
||||
shape = obj->nativeLookup(cx, id);
|
||||
@ -3237,7 +3237,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
}
|
||||
|
||||
if (JSID_IS_INT(id) && objp->containsDenseElement(JSID_TO_INT(id))) {
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkDenseElementFound(propp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3263,7 +3263,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
|
||||
{
|
||||
if (JSID_IS_INT(id) && current->containsDenseElement(JSID_TO_INT(id))) {
|
||||
objp.set(current);
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkDenseElementFound(propp);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3549,7 +3549,7 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
: JSObject::getGeneric(cx, obj2, obj2, id, vp);
|
||||
}
|
||||
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
vp.set(obj2->getDenseElement(JSID_TO_INT(id)));
|
||||
return true;
|
||||
}
|
||||
@ -3804,7 +3804,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
getter = clasp->getProperty;
|
||||
setter = clasp->setProperty;
|
||||
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
/* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */
|
||||
if (pobj != obj)
|
||||
shape = NULL;
|
||||
@ -3877,7 +3877,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
}
|
||||
}
|
||||
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
JSObject::setDenseElementWithType(cx, obj, JSID_TO_INT(id), vp);
|
||||
return true;
|
||||
}
|
||||
@ -4006,7 +4006,7 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
|
||||
return false;
|
||||
if (!shape)
|
||||
return true;
|
||||
if (nobj->isNative() && IsImplicitProperty(shape)) {
|
||||
if (nobj->isNative() && IsImplicitDenseElement(shape)) {
|
||||
if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id)))
|
||||
return false;
|
||||
shape = obj->nativeLookup(cx, id);
|
||||
@ -4025,7 +4025,7 @@ baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, u
|
||||
return false;
|
||||
if (!shape)
|
||||
return true;
|
||||
if (nobj->isNative() && IsImplicitProperty(shape)) {
|
||||
if (nobj->isNative() && IsImplicitDenseElement(shape)) {
|
||||
if (!JSObject::sparsifyDenseElement(cx, obj, index))
|
||||
return false;
|
||||
shape = obj->nativeLookup(cx, INT_TO_JSID(index));
|
||||
@ -4054,7 +4054,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHand
|
||||
|
||||
GCPoke(cx->runtime);
|
||||
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval))
|
||||
return false;
|
||||
if (rval.isFalse())
|
||||
@ -4295,7 +4295,7 @@ js::CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode,
|
||||
*attrsp = GetShapeAttributes(shape);
|
||||
|
||||
if (!writing) {
|
||||
if (IsImplicitProperty(shape)) {
|
||||
if (IsImplicitDenseElement(shape)) {
|
||||
vp.set(pobj->getDenseElement(JSID_TO_INT(id)));
|
||||
} else {
|
||||
if (shape->hasSlot())
|
||||
|
@ -38,9 +38,9 @@
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "ds/Sort.h"
|
||||
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
@ -6262,10 +6262,11 @@ js::DecompileValueGenerator(JSContext *cx, int spindex, HandleValue v,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
||||
if (!stable)
|
||||
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
||||
TwoByteChars tbchars(linear->chars(), linear->length());
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -6352,10 +6353,10 @@ js::DecompileArgument(JSContext *cx, int formalIndex, HandleValue v)
|
||||
if (!fallback)
|
||||
return NULL;
|
||||
|
||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
||||
if (!stable)
|
||||
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "jspubtd.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
@ -360,8 +362,8 @@ static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
|
||||
return fill2(ss, s ? s : "(null)", slen, width, flags);
|
||||
}
|
||||
|
||||
static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
||||
int flags)
|
||||
static int
|
||||
cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec, int flags)
|
||||
{
|
||||
int result;
|
||||
/*
|
||||
@ -369,12 +371,15 @@ static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
||||
* and malloc() is used to allocate the buffer buffer.
|
||||
*/
|
||||
if (ws) {
|
||||
int slen = js_strlen(ws);
|
||||
char *s = DeflateString(NULL, ws, slen);
|
||||
if (!s)
|
||||
size_t wslen = js_strlen(ws);
|
||||
char *latin1 = js_pod_malloc<char>(wslen + 1);
|
||||
if (!latin1)
|
||||
return -1; /* JSStuffFunc error indicator. */
|
||||
result = cvt_s(ss, s, width, prec, flags);
|
||||
js_free(s);
|
||||
for (size_t i = 0; i < wslen; ++i)
|
||||
latin1[i] = (char)ws[i];
|
||||
latin1[wslen] = '\0';
|
||||
result = cvt_s(ss, latin1, width, prec, flags);
|
||||
js_free(latin1);
|
||||
} else {
|
||||
result = cvt_s(ss, NULL, width, prec, flags);
|
||||
}
|
||||
|
@ -2551,7 +2551,7 @@ proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
return false;
|
||||
|
||||
if (found) {
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkNonNativePropertyFound(propp);
|
||||
objp.set(obj);
|
||||
} else {
|
||||
objp.set(NULL);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
@ -3442,7 +3443,8 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
filename = DeflateString(cx, chars, length);
|
||||
TwoByteChars tbchars(chars, length);
|
||||
filename = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (!filename)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -496,17 +496,25 @@ BaseShape::markChildren(JSTracer *trc)
|
||||
/*
|
||||
* Property lookup hooks on objects are required to return a non-NULL shape to
|
||||
* signify that the property has been found. For cases where the property is
|
||||
* not actually represented by a Shape (dense elements, properties of
|
||||
* non-native objects), use a dummy value.
|
||||
* not actually represented by a Shape, use a dummy value. This includes all
|
||||
* properties of non-native objects, and dense elements for native objects.
|
||||
* Use separate APIs for these two cases.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
MarkImplicitPropertyFound(MutableHandleShape propp)
|
||||
MarkNonNativePropertyFound(MutableHandleShape propp)
|
||||
{
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
||||
static inline void
|
||||
MarkDenseElementFound(MutableHandleShape propp)
|
||||
{
|
||||
propp.set(reinterpret_cast<Shape*>(1));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsImplicitProperty(HandleShape prop)
|
||||
IsImplicitDenseElement(HandleShape prop)
|
||||
{
|
||||
return prop.get() == reinterpret_cast<Shape*>(1);
|
||||
}
|
||||
@ -514,7 +522,7 @@ IsImplicitProperty(HandleShape prop)
|
||||
static inline uint8_t
|
||||
GetShapeAttributes(HandleShape shape)
|
||||
{
|
||||
return IsImplicitProperty(shape) ? JSPROP_ENUMERATE : shape->attributes();
|
||||
return IsImplicitDenseElement(shape) ? JSPROP_ENUMERATE : shape->attributes();
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
135
js/src/jsstr.cpp
135
js/src/jsstr.cpp
@ -2342,6 +2342,116 @@ BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *reps
|
||||
return true;
|
||||
}
|
||||
|
||||
struct StringRange
|
||||
{
|
||||
size_t start;
|
||||
size_t length;
|
||||
|
||||
StringRange(size_t s, size_t l)
|
||||
: start(s), length(l)
|
||||
{ }
|
||||
};
|
||||
|
||||
static JSString *
|
||||
AppendSubstrings(JSContext *cx, Handle<JSStableString*> stableStr,
|
||||
const StringRange *ranges, size_t rangesLen)
|
||||
{
|
||||
JS_ASSERT(rangesLen);
|
||||
|
||||
/* For single substrings, construct a dependent string. */
|
||||
if (rangesLen == 1)
|
||||
return js_NewDependentString(cx, stableStr, ranges[0].start, ranges[0].length);
|
||||
|
||||
/* Collect substrings into a rope. */
|
||||
RopeBuilder rope(cx);
|
||||
for (size_t i = 0; i < rangesLen; i++) {
|
||||
const StringRange &sr = ranges[i];
|
||||
|
||||
RootedString substr(cx, js_NewDependentString(cx, stableStr, sr.start, sr.length));
|
||||
if (!substr)
|
||||
return NULL;
|
||||
|
||||
/* Appending to the rope permanently roots the substring. */
|
||||
rope.append(substr);
|
||||
}
|
||||
|
||||
return rope.result();
|
||||
}
|
||||
|
||||
static bool
|
||||
str_replace_regexp_remove(JSContext *cx, CallArgs args, HandleString str, RegExpShared &re)
|
||||
{
|
||||
Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx));
|
||||
if (!stableStr)
|
||||
return false;
|
||||
|
||||
Vector<StringRange, 16, SystemAllocPolicy> ranges;
|
||||
|
||||
StableCharPtr chars = stableStr->chars();
|
||||
size_t charsLen = stableStr->length();
|
||||
|
||||
MatchPair match;
|
||||
size_t startIndex = 0; /* Index used for iterating through the string. */
|
||||
size_t lastIndex = 0; /* Index after last successful match. */
|
||||
size_t lazyIndex = 0; /* Index before last successful match. */
|
||||
|
||||
/* Accumulate StringRanges for unmatched substrings. */
|
||||
while (startIndex <= charsLen) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx))
|
||||
return false;
|
||||
|
||||
RegExpRunStatus status = re.executeMatchOnly(cx, chars, charsLen, &startIndex, match);
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
if (status == RegExpRunStatus_Success_NotFound)
|
||||
break;
|
||||
|
||||
/* Include the latest unmatched substring. */
|
||||
if (size_t(match.start) > lastIndex) {
|
||||
if (!ranges.append(StringRange(lastIndex, match.start - lastIndex)))
|
||||
return false;
|
||||
}
|
||||
|
||||
lazyIndex = lastIndex;
|
||||
lastIndex = startIndex;
|
||||
|
||||
/* Non-global removal executes at most once. */
|
||||
if (!re.global())
|
||||
break;
|
||||
|
||||
if (match.isEmpty())
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
/* If unmatched, return the input string. */
|
||||
if (!lastIndex) {
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The last successful match updates the RegExpStatics. */
|
||||
cx->regExpStatics()->updateLazily(cx, stableStr, &re, lazyIndex);
|
||||
|
||||
/* Include any remaining part of the string. */
|
||||
if (lastIndex < charsLen) {
|
||||
if (!ranges.append(StringRange(lastIndex, charsLen - lastIndex)))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Handle the empty string before calling .begin(). */
|
||||
if (ranges.empty()) {
|
||||
args.rval().setString(cx->runtime->emptyString);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSString *result = AppendSubstrings(cx, stableStr, ranges.begin(), ranges.length());
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
args.rval().setString(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
|
||||
{
|
||||
@ -2354,6 +2464,12 @@ str_replace_regexp(JSContext *cx, CallArgs args, ReplaceData &rdata)
|
||||
RegExpStatics *res = cx->regExpStatics();
|
||||
RegExpShared &re = rdata.g.regExp();
|
||||
|
||||
/* Optimize removal. */
|
||||
if (rdata.repstr && rdata.repstr->length() == 0 && !rdata.dollar) {
|
||||
JS_ASSERT(!rdata.lambda && !rdata.elembase);
|
||||
return str_replace_regexp_remove(cx, args, rdata.str, re);
|
||||
}
|
||||
|
||||
Value tmp;
|
||||
if (!DoMatch(cx, res, rdata.str, re, ReplaceRegExpCallback, &rdata, REPLACE_ARGS, &tmp))
|
||||
return false;
|
||||
@ -3726,25 +3842,6 @@ js::InflateUTF8String(JSContext *cx, const char *bytes, size_t *lengthp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* May be called with null cx.
|
||||
*/
|
||||
char *
|
||||
js::DeflateString(JSContext *maybecx, const jschar *chars, size_t nchars)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
size_t nbytes = nchars;
|
||||
char *bytes = maybecx
|
||||
? maybecx->pod_malloc<char>(nbytes + 1)
|
||||
: js_pod_malloc<char>(nbytes + 1);
|
||||
if (!bytes)
|
||||
return NULL;
|
||||
for (size_t i = 0; i < nbytes; i++)
|
||||
bytes[i] = (char) chars[i];
|
||||
bytes[nbytes] = 0;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t
|
||||
js::GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
||||
{
|
||||
|
@ -224,9 +224,6 @@ InflateString(JSContext *cx, const char *bytes, size_t *length);
|
||||
extern jschar *
|
||||
InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
|
||||
|
||||
extern char *
|
||||
DeflateString(JSContext *cx, const jschar *chars, size_t length);
|
||||
|
||||
/*
|
||||
* Inflate bytes to JS chars in an existing buffer. 'chars' must be large
|
||||
* enough for 'length' jschars. The buffer is NOT null-terminated.
|
||||
|
@ -1015,7 +1015,7 @@ TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id,
|
||||
JS_ASSERT(tarray->isTypedArray());
|
||||
|
||||
if (isArrayIndex(tarray, id)) {
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkNonNativePropertyFound(propp);
|
||||
objp.set(tarray);
|
||||
return true;
|
||||
}
|
||||
@ -1045,7 +1045,7 @@ TypedArray::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index
|
||||
JS_ASSERT(tarray->isTypedArray());
|
||||
|
||||
if (index < length(tarray)) {
|
||||
MarkImplicitPropertyFound(propp);
|
||||
MarkNonNativePropertyFound(propp);
|
||||
objp.set(tarray);
|
||||
return true;
|
||||
}
|
||||
|
@ -5086,6 +5086,7 @@ mjit::Compiler::jsop_getprop(HandlePropertyName name, JSValueType knownType,
|
||||
* must fit in an int32_t.
|
||||
*/
|
||||
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) {
|
||||
frame.forgetMismatchedObject(top);
|
||||
bool isObject = top->isTypeKnown();
|
||||
if (!isObject) {
|
||||
Jump notObject = frame.testObject(Assembler::NotEqual, top);
|
||||
@ -7593,6 +7594,7 @@ mjit::Compiler::jsop_in()
|
||||
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
|
||||
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript))
|
||||
{
|
||||
frame.forgetMismatchedObject(obj);
|
||||
bool isPacked = !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
|
||||
|
||||
if (!obj->isTypeKnown()) {
|
||||
|
@ -605,6 +605,9 @@ CompileStatus
|
||||
mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes,
|
||||
FrameEntry *thisValue, FrameEntry *argValue)
|
||||
{
|
||||
frame.forgetMismatchedObject(thisValue);
|
||||
frame.forgetMismatchedObject(argValue);
|
||||
|
||||
/*
|
||||
* Require the 'this' types to have a specific type matching the current
|
||||
* global, so we can create the result object inline.
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
#include "vm/StringObject-inl.h"
|
||||
|
||||
@ -2409,12 +2411,12 @@ GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandleP
|
||||
|
||||
CodeLocationLabel cs = buffer.finalize(f);
|
||||
#if DEBUG
|
||||
char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
|
||||
Latin1CharsZ latin1 = LossyTwoByteCharsToNewLatin1CharsZ(cx, v.toString()->ensureLinear(cx)->range());
|
||||
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
|
||||
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, chars,
|
||||
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, latin1.get(),
|
||||
(void*)holder->lastProperty(), cx->fp()->script()->filename,
|
||||
CurrentLine(cx));
|
||||
js_free(chars);
|
||||
JS_free(latin1);
|
||||
#endif
|
||||
|
||||
// Update the inline guards, if needed.
|
||||
|
@ -2440,47 +2440,6 @@ ToInt32(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* badUTF8 = "...\xC0...";
|
||||
static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
|
||||
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
||||
|
||||
static JSBool
|
||||
TestUTF8(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
int32_t mode = 1;
|
||||
jschar chars[20];
|
||||
size_t charsLength = 5;
|
||||
char bytes[20];
|
||||
size_t bytesLength = 20;
|
||||
if (argc && !JS_ValueToInt32(cx, *JS_ARGV(cx, vp), &mode))
|
||||
return false;
|
||||
|
||||
/* The following throw errors if compiled with UTF-8. */
|
||||
switch (mode) {
|
||||
/* mode 1: malformed UTF-8 string. */
|
||||
case 1:
|
||||
JS_NewStringCopyZ(cx, badUTF8);
|
||||
break;
|
||||
/* mode 2: big UTF-8 character. */
|
||||
case 2:
|
||||
JS_NewStringCopyZ(cx, bigUTF8);
|
||||
break;
|
||||
/* mode 3: bad surrogate character. */
|
||||
case 3:
|
||||
DeflateStringToBuffer(cx, badSurrogate, 6, bytes, &bytesLength);
|
||||
break;
|
||||
/* mode 4: use a too small buffer. */
|
||||
case 4:
|
||||
JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
|
||||
break;
|
||||
default:
|
||||
JS_ReportError(cx, "invalid mode parameter");
|
||||
return false;
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return !JS_IsExceptionPending (cx);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ThrowError(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
@ -3740,10 +3699,6 @@ static JSFunctionSpecWithHelp shell_functions[] = {
|
||||
"pc2line(fun[, pc])",
|
||||
" Map PC to line number."),
|
||||
|
||||
JS_FN_HELP("testUTF8", TestUTF8, 1, 0,
|
||||
"testUTF8(mode)",
|
||||
" Perform UTF-8 tests (modes are 1 to 4)."),
|
||||
|
||||
JS_FN_HELP("throwError", ThrowError, 0, 0,
|
||||
"throwError()",
|
||||
" Throw an error from JS_ReportError."),
|
||||
|
@ -1,122 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
var BUGNUMBER = 232182;
|
||||
var summary = 'Display non-ascii characters in JS exceptions';
|
||||
var actual = '';
|
||||
var expect = 'no error';
|
||||
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
/*
|
||||
* This test accesses an undefined Unicode symbol. If the code has not been
|
||||
* compiled with JS_C_STRINGS_ARE_UTF8, the thrown error truncates Unicode
|
||||
* characters to bytes. Accessing \u0440\u0441, therefore, results in a
|
||||
* message talking about an undefined variable 'AB' (\x41\x42).
|
||||
*/
|
||||
var utf8Enabled = false;
|
||||
try
|
||||
{
|
||||
\u0441\u0442;
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
utf8Enabled = (e.message.charAt (0) == '\u0441');
|
||||
}
|
||||
|
||||
// Run the tests only if UTF-8 is enabled
|
||||
|
||||
printStatus('UTF-8 is ' + (utf8Enabled?'':'not ') + 'enabled');
|
||||
|
||||
if (!utf8Enabled)
|
||||
{
|
||||
reportCompare('Not run', 'Not run', 'utf8 is not enabled');
|
||||
}
|
||||
else
|
||||
{
|
||||
status = summary + ': Throw Error with Unicode message';
|
||||
expect = 'test \u0440\u0441';
|
||||
try
|
||||
{
|
||||
throw Error (expect);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = e.message;
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
var inShell = (typeof stringsAreUTF8 == "function");
|
||||
if (!inShell)
|
||||
{
|
||||
inShell = (typeof stringsAreUtf8 == "function");
|
||||
if (inShell)
|
||||
{
|
||||
this.stringsAreUTF8 = stringsAreUtf8;
|
||||
this.testUTF8 = testUtf8;
|
||||
}
|
||||
}
|
||||
|
||||
if (inShell && stringsAreUTF8())
|
||||
{
|
||||
status = summary + ': UTF-8 test: bad UTF-08 sequence';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(1);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
status = summary + ': UTF-8 character too big to fit into Unicode surrogate pairs';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(2);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
status = summary + ': bad Unicode surrogate character';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(3);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
}
|
||||
|
||||
if (inShell)
|
||||
{
|
||||
status = summary + ': conversion target buffer overrun';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(4);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
}
|
||||
}
|
28
js/src/vm/CharacterEncoding.cpp
Normal file
28
js/src/vm/CharacterEncoding.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
using namespace JS;
|
||||
|
||||
Latin1CharsZ
|
||||
JS::LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(cx);
|
||||
size_t len = tbchars.length();
|
||||
unsigned char *latin1 = cx->pod_malloc<unsigned char>(len + 1);
|
||||
if (!latin1)
|
||||
return Latin1CharsZ();
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
latin1[i] = static_cast<unsigned char>(tbchars[i]);
|
||||
latin1[len] = '\0';
|
||||
return Latin1CharsZ(latin1, len);
|
||||
}
|
||||
|
@ -405,12 +405,6 @@ RegExpShared::~RegExpShared()
|
||||
js_delete<BytecodePattern>(bytecode);
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::trace(JSTracer *trc)
|
||||
{
|
||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||
}
|
||||
|
||||
void
|
||||
RegExpShared::reportYarrError(JSContext *cx, TokenStream *ts, ErrorCode error)
|
||||
{
|
||||
@ -651,6 +645,18 @@ RegExpCompartment::RegExpCompartment(JSRuntime *rt)
|
||||
RegExpCompartment::~RegExpCompartment()
|
||||
{
|
||||
JS_ASSERT(map_.empty());
|
||||
|
||||
/*
|
||||
* RegExpStatics may have prevented a single RegExpShared from
|
||||
* being collected during RegExpCompartment::sweep().
|
||||
*/
|
||||
if (!inUse_.empty()) {
|
||||
PendingSet::Enum e(inUse_);
|
||||
RegExpShared *shared = e.front();
|
||||
JS_ASSERT(shared->activeUseCount == 0);
|
||||
js_delete(shared);
|
||||
e.removeFront();
|
||||
}
|
||||
JS_ASSERT(inUse_.empty());
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "js/TemplateLib.h"
|
||||
#include "vm/MatchPairs.h"
|
||||
|
||||
@ -120,11 +122,12 @@ class RegExpShared
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Source to the RegExp. The RegExpShared must either be protected by a
|
||||
* RegExpGuard, which handles rooting for stacky RegExpShareds,
|
||||
* or trace() must be explicitly called during marking.
|
||||
* Source to the RegExp, for lazy compilation.
|
||||
* The source must be rooted while activeUseCount is non-zero
|
||||
* via RegExpGuard, RegExpHeapGuard, or explicit calls to trace().
|
||||
*/
|
||||
JSAtom * source;
|
||||
|
||||
RegExpFlag flags;
|
||||
unsigned parenCount;
|
||||
|
||||
@ -149,7 +152,10 @@ class RegExpShared
|
||||
RegExpShared(JSRuntime *rt, JSAtom *source, RegExpFlag flags);
|
||||
~RegExpShared();
|
||||
|
||||
void trace(JSTracer *trc);
|
||||
/* Explicit trace function for use by the RegExpStatics and JITs. */
|
||||
void trace(JSTracer *trc) {
|
||||
MarkStringUnbarriered(trc, &source, "regexpshared source");
|
||||
}
|
||||
|
||||
/* Static functions to expose some Yarr logic. */
|
||||
static inline bool isJITRuntimeEnabled(JSContext *cx);
|
||||
@ -222,17 +228,58 @@ class RegExpGuard
|
||||
re_->incRef();
|
||||
}
|
||||
|
||||
~RegExpGuard() {
|
||||
if (re_)
|
||||
re_->decRef();
|
||||
}
|
||||
~RegExpGuard() { release(); }
|
||||
|
||||
public:
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!re_);
|
||||
JS_ASSERT(!initialized());
|
||||
re_ = &re;
|
||||
re_->incRef();
|
||||
source_ = re.source;
|
||||
source_ = re_->source;
|
||||
}
|
||||
void release() {
|
||||
if (re_) {
|
||||
re_->decRef();
|
||||
re_ = NULL;
|
||||
source_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool initialized() const { return !!re_; }
|
||||
RegExpShared *re() const { JS_ASSERT(initialized()); return re_; }
|
||||
RegExpShared *operator->() { return re(); }
|
||||
RegExpShared &operator*() { return *re(); }
|
||||
};
|
||||
|
||||
/* Equivalent of RegExpGuard, heap-allocated, with explicit tracing. */
|
||||
class RegExpHeapGuard
|
||||
{
|
||||
RegExpShared *re_;
|
||||
|
||||
RegExpHeapGuard(const RegExpGuard &) MOZ_DELETE;
|
||||
void operator=(const RegExpHeapGuard &) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
RegExpHeapGuard() : re_(NULL) { }
|
||||
RegExpHeapGuard(RegExpShared &re) { init(re); }
|
||||
~RegExpHeapGuard() { release(); }
|
||||
|
||||
public:
|
||||
void init(RegExpShared &re) {
|
||||
JS_ASSERT(!initialized());
|
||||
re_ = &re;
|
||||
re_->incRef();
|
||||
}
|
||||
void release() {
|
||||
if (re_) {
|
||||
re_->decRef();
|
||||
re_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void trace(JSTracer *trc) {
|
||||
if (initialized())
|
||||
re_->trace(trc);
|
||||
}
|
||||
|
||||
bool initialized() const { return !!re_; }
|
||||
@ -246,9 +293,12 @@ class RegExpCompartment
|
||||
struct Key {
|
||||
JSAtom *atom;
|
||||
uint16_t flag;
|
||||
|
||||
Key() {}
|
||||
Key(JSAtom *atom, RegExpFlag flag)
|
||||
: atom(atom), flag(flag) {}
|
||||
: atom(atom), flag(flag)
|
||||
{ }
|
||||
|
||||
typedef Key Lookup;
|
||||
static HashNumber hash(const Lookup &l) {
|
||||
return DefaultHasher<JSAtom *>::hash(l.atom) ^ (l.flag << 1);
|
||||
|
@ -27,15 +27,6 @@ SizeOfRegExpStaticsData(const JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
|
||||
return mallocSizeOf(obj->getPrivate());
|
||||
}
|
||||
|
||||
inline
|
||||
RegExpStatics::RegExpStatics()
|
||||
: pendingLazyEvaluation(false),
|
||||
bufferLink(NULL),
|
||||
copied(false)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
inline bool
|
||||
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out)
|
||||
{
|
||||
@ -231,15 +222,20 @@ RegExpStatics::copyTo(RegExpStatics &dst)
|
||||
if (!pendingLazyEvaluation)
|
||||
dst.matches.initArrayFrom(matches);
|
||||
|
||||
if (regexp.initialized())
|
||||
dst.regexp.init(*regexp);
|
||||
else
|
||||
dst.regexp.release();
|
||||
|
||||
dst.matchesInput = matchesInput;
|
||||
dst.regexp = regexp;
|
||||
dst.lastIndex = lastIndex;
|
||||
dst.pendingInput = pendingInput;
|
||||
dst.flags = flags;
|
||||
dst.pendingLazyEvaluation = pendingLazyEvaluation;
|
||||
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp);
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, regexp.initialized());
|
||||
JS_ASSERT_IF(pendingLazyEvaluation, matchesInput);
|
||||
JS_ASSERT(regexp.initialized() == dst.regexp.initialized());
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -261,17 +257,20 @@ RegExpStatics::restore()
|
||||
|
||||
inline void
|
||||
RegExpStatics::updateLazily(JSContext *cx, JSLinearString *input,
|
||||
RegExpObject *regexp, size_t lastIndex)
|
||||
RegExpShared *shared, size_t lastIndex)
|
||||
{
|
||||
JS_ASSERT(input && regexp);
|
||||
JS_ASSERT(input && shared);
|
||||
aboutToWrite();
|
||||
|
||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||
pendingInput, input,
|
||||
matchesInput, input);
|
||||
pendingLazyEvaluation = true;
|
||||
this->regexp = regexp;
|
||||
if (regexp.initialized())
|
||||
regexp.release();
|
||||
regexp.init(*shared);
|
||||
|
||||
this->lastIndex = lastIndex;
|
||||
pendingLazyEvaluation = true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -282,7 +281,7 @@ RegExpStatics::updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchP
|
||||
|
||||
/* Unset all lazy state. */
|
||||
pendingLazyEvaluation = false;
|
||||
this->regexp = NULL;
|
||||
this->regexp.release();
|
||||
this->lastIndex = size_t(-1);
|
||||
|
||||
BarrieredSetPair<JSString, JSLinearString>(cx->compartment,
|
||||
@ -301,11 +300,14 @@ inline void
|
||||
RegExpStatics::clear()
|
||||
{
|
||||
aboutToWrite();
|
||||
flags = RegExpFlag(0);
|
||||
pendingInput = NULL;
|
||||
pendingLazyEvaluation = false;
|
||||
matchesInput = NULL;
|
||||
|
||||
matches.forgetArray();
|
||||
matchesInput = NULL;
|
||||
regexp.release();
|
||||
lastIndex = size_t(-1);
|
||||
pendingInput = NULL;
|
||||
flags = RegExpFlag(0);
|
||||
pendingLazyEvaluation = false;
|
||||
}
|
||||
|
||||
inline void
|
||||
@ -363,8 +365,9 @@ RegExpStatics::checkInvariants()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (pendingLazyEvaluation) {
|
||||
JS_ASSERT(regexp);
|
||||
JS_ASSERT(regexp.initialized());
|
||||
JS_ASSERT(pendingInput);
|
||||
JS_ASSERT(lastIndex != size_t(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ RegExpStatics::executeLazy(JSContext *cx)
|
||||
if (!pendingLazyEvaluation)
|
||||
return true;
|
||||
|
||||
JS_ASSERT(regexp);
|
||||
JS_ASSERT(regexp.initialized());
|
||||
JS_ASSERT(matchesInput);
|
||||
JS_ASSERT(lastIndex != size_t(-1));
|
||||
|
||||
@ -87,17 +87,20 @@ RegExpStatics::executeLazy(JSContext *cx)
|
||||
StableCharPtr chars(matchesInput->chars(), length);
|
||||
|
||||
/* Execute the full regular expression. */
|
||||
RegExpGuard shared(cx);
|
||||
if (!regexp->getShared(cx, &shared))
|
||||
return false;
|
||||
|
||||
RegExpRunStatus status = shared->execute(cx, chars, length, &this->lastIndex, this->matches);
|
||||
RegExpRunStatus status = regexp->execute(cx, chars, length, &this->lastIndex, this->matches);
|
||||
if (status == RegExpRunStatus_Error)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* RegExpStatics are only updated on successful (matching) execution.
|
||||
* Re-running the same expression must therefore produce a matching result.
|
||||
*/
|
||||
JS_ASSERT(status == RegExpRunStatus_Success);
|
||||
|
||||
/* Unset lazy state and remove rooted values that now have no use. */
|
||||
pendingLazyEvaluation = false;
|
||||
regexp = NULL;
|
||||
regexp.release();
|
||||
lastIndex = size_t(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "js/Vector.h"
|
||||
|
||||
#include "vm/MatchPairs.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -27,7 +28,7 @@ class RegExpStatics
|
||||
HeapPtr<JSLinearString> matchesInput;
|
||||
|
||||
/* The previous RegExp input, used to resolve lazy state. */
|
||||
HeapPtr<RegExpObject> regexp;
|
||||
RegExpHeapGuard regexp;
|
||||
size_t lastIndex;
|
||||
|
||||
/* The latest RegExp input, set before execution. */
|
||||
@ -44,6 +45,10 @@ class RegExpStatics
|
||||
RegExpStatics *bufferLink;
|
||||
bool copied;
|
||||
|
||||
public:
|
||||
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
|
||||
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
||||
|
||||
private:
|
||||
bool executeLazy(JSContext *cx);
|
||||
|
||||
@ -80,14 +85,9 @@ class RegExpStatics
|
||||
friend class PreserveRegExpStatics;
|
||||
|
||||
public:
|
||||
inline RegExpStatics();
|
||||
|
||||
static JSObject *create(JSContext *cx, GlobalObject *parent);
|
||||
|
||||
/* Mutators. */
|
||||
|
||||
inline void updateLazily(JSContext *cx, JSLinearString *input,
|
||||
RegExpObject *regexp, size_t lastIndex);
|
||||
RegExpShared *shared, size_t lastIndex);
|
||||
inline bool updateFromMatchPairs(JSContext *cx, JSLinearString *input, MatchPairs &newPairs);
|
||||
inline void setMultiline(JSContext *cx, bool enabled);
|
||||
|
||||
@ -120,12 +120,16 @@ class RegExpStatics
|
||||
}
|
||||
|
||||
void mark(JSTracer *trc) {
|
||||
if (regexp)
|
||||
gc::MarkObject(trc, ®exp, "res->regexp");
|
||||
/*
|
||||
* Changes to this function must also be reflected in
|
||||
* RegExpStatics::AutoRooter::trace().
|
||||
*/
|
||||
if (pendingInput)
|
||||
MarkString(trc, &pendingInput, "res->pendingInput");
|
||||
if (matchesInput)
|
||||
MarkString(trc, &matchesInput, "res->matchesInput");
|
||||
if (regexp.initialized())
|
||||
regexp->trace(trc);
|
||||
}
|
||||
|
||||
/* Value creators. */
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsfriendapi.h"
|
||||
@ -477,6 +479,11 @@ class JSLinearString : public JSString
|
||||
JS_ASSERT(JSString::isLinear());
|
||||
return d.u1.chars;
|
||||
}
|
||||
|
||||
JS::TwoByteChars range() const {
|
||||
JS_ASSERT(JSString::isLinear());
|
||||
return JS::TwoByteChars(d.u1.chars, length());
|
||||
}
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
|
||||
|
@ -575,7 +575,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, buffer, length);
|
||||
JS_EncodeStringToBuffer(cx, str, buffer, length);
|
||||
buffer[length] = '\0';
|
||||
*((void**)d) = buffer;
|
||||
return true;
|
||||
@ -701,7 +701,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if (rs->Length() != uint32_t(length)) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, rs->BeginWriting(), length);
|
||||
JS_EncodeStringToBuffer(cx, str, rs->BeginWriting(), length);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1875,7 +1875,7 @@ XPCConvert::JSStringWithSize2Native(XPCCallContext& ccx, void* d, jsval s,
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, buffer, len);
|
||||
JS_EncodeStringToBuffer(cx, str, buffer, len);
|
||||
buffer[len] = '\0';
|
||||
*((char**)d) = buffer;
|
||||
|
||||
|
@ -122,7 +122,7 @@ XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
|
||||
if (length != size_t(-1)) {
|
||||
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
||||
if (self->mFunname) {
|
||||
JS_EncodeStringToBuffer(funid, self->mFunname, length);
|
||||
JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
|
||||
self->mFunname[length] = '\0';
|
||||
}
|
||||
}
|
||||
|
33
layout/reftests/bugs/817019-1.html
Normal file
33
layout/reftests/bugs/817019-1.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title></title>
|
||||
<script type="text/javascript">
|
||||
function paintCanvas() {
|
||||
var elem = document.getElementById("mycanv");
|
||||
var ctx = elem.getContext('2d');
|
||||
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, 200, 200);
|
||||
ctx.beginPath();
|
||||
ctx.arc(150, 150, 100, 0, Math.PI * 2, true);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
|
||||
// create radial gradient
|
||||
var grd = ctx.createRadialGradient(110, 110, 42, 110, 110, 121);
|
||||
grd.addColorStop(0, '#FFFFFF');
|
||||
grd.addColorStop(1, '#E5E5E5');
|
||||
|
||||
ctx.fillStyle = grd;
|
||||
// This should be completely clipped out!
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="paintCanvas();">
|
||||
<canvas width=200 height=200 moz-opaque="true" id="mycanv"></canvas>
|
||||
</body>
|
||||
</html>
|
@ -1740,3 +1740,4 @@ skip-if(B2G) == 814952-1.html 814952-1-ref.html
|
||||
skip-if(B2G) == 818276-1.html 818276-1-ref.html
|
||||
== 827577-1a.html 827577-1-ref.html
|
||||
== 827577-1b.html 827577-1-ref.html
|
||||
== 817019-1.html about:blank
|
||||
|
@ -2,5 +2,4 @@ This source is from the Speex library (http://git.xiph.org/speex.git/), from
|
||||
commit a6d05eb5.
|
||||
|
||||
It consists in the audio resampling code (resampler.c) and its header files
|
||||
dependancies. No changes have been made to those files, imported in the tree
|
||||
using the update.sh script.
|
||||
dependancies, imported into the tree using the update.sh script.
|
||||
|
@ -960,13 +960,15 @@ EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, co
|
||||
{
|
||||
spx_uint32_t i;
|
||||
int istride_save, ostride_save;
|
||||
spx_uint32_t bak_len = *out_len;
|
||||
spx_uint32_t bak_out_len = *out_len;
|
||||
spx_uint32_t bak_in_len = *in_len;
|
||||
istride_save = st->in_stride;
|
||||
ostride_save = st->out_stride;
|
||||
st->in_stride = st->out_stride = st->nb_channels;
|
||||
for (i=0;i<st->nb_channels;i++)
|
||||
{
|
||||
*out_len = bak_len;
|
||||
*out_len = bak_out_len;
|
||||
*in_len = bak_in_len;
|
||||
if (in != NULL)
|
||||
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
|
||||
else
|
||||
@ -981,13 +983,15 @@ EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, cons
|
||||
{
|
||||
spx_uint32_t i;
|
||||
int istride_save, ostride_save;
|
||||
spx_uint32_t bak_len = *out_len;
|
||||
spx_uint32_t bak_out_len = *out_len;
|
||||
spx_uint32_t bak_in_len = *in_len;
|
||||
istride_save = st->in_stride;
|
||||
ostride_save = st->out_stride;
|
||||
st->in_stride = st->out_stride = st->nb_channels;
|
||||
for (i=0;i<st->nb_channels;i++)
|
||||
{
|
||||
*out_len = bak_len;
|
||||
*out_len = bak_out_len;
|
||||
*in_len = bak_in_len;
|
||||
if (in != NULL)
|
||||
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
|
||||
else
|
||||
|
54
media/libspeex_resampler/truncation.patch
Normal file
54
media/libspeex_resampler/truncation.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 5adadc5626ee2d5d3a3ca21e70fd195b9d002a0b Mon Sep 17 00:00:00 2001
|
||||
From: Jean-Marc Valin <jmvalin@jmvalin.ca>
|
||||
Date: Wed, 1 Aug 2012 13:19:38 -0400
|
||||
Subject: [PATCH] Properly save in_len for multiple channels in the resampler.
|
||||
|
||||
This fixes issues with clicking in one channel and/or truncation
|
||||
with some unusual sample rates.
|
||||
---
|
||||
src/resample.c | 12 ++++++++----
|
||||
1 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/resample.c b/src/resample.c
|
||||
index 84aaf59..6e92bd0 100644
|
||||
--- a/src/resample.c
|
||||
+++ b/src/resample.c
|
||||
@@ -966,13 +966,15 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_float(SpeexResampler
|
||||
{
|
||||
spx_uint32_t i;
|
||||
int istride_save, ostride_save;
|
||||
- spx_uint32_t bak_len = *out_len;
|
||||
+ spx_uint32_t bak_out_len = *out_len;
|
||||
+ spx_uint32_t bak_in_len = *in_len;
|
||||
istride_save = st->in_stride;
|
||||
ostride_save = st->out_stride;
|
||||
st->in_stride = st->out_stride = st->nb_channels;
|
||||
for (i=0;i<st->nb_channels;i++)
|
||||
{
|
||||
- *out_len = bak_len;
|
||||
+ *out_len = bak_out_len;
|
||||
+ *in_len = bak_in_len;
|
||||
if (in != NULL)
|
||||
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
|
||||
else
|
||||
@@ -987,13 +989,15 @@ SPX_RESAMPLE_EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerSt
|
||||
{
|
||||
spx_uint32_t i;
|
||||
int istride_save, ostride_save;
|
||||
- spx_uint32_t bak_len = *out_len;
|
||||
+ spx_uint32_t bak_out_len = *out_len;
|
||||
+ spx_uint32_t bak_in_len = *in_len;
|
||||
istride_save = st->in_stride;
|
||||
ostride_save = st->out_stride;
|
||||
st->in_stride = st->out_stride = st->nb_channels;
|
||||
for (i=0;i<st->nb_channels;i++)
|
||||
{
|
||||
- *out_len = bak_len;
|
||||
+ *out_len = bak_out_len;
|
||||
+ *in_len = bak_in_len;
|
||||
if (in != NULL)
|
||||
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
|
||||
else
|
||||
--
|
||||
1.7.2.5
|
||||
|
@ -6,6 +6,7 @@
|
||||
#
|
||||
# Copies the needed files from a directory containing the original
|
||||
# libspeex sources that we need for HTML5 media playback rate change.
|
||||
|
||||
cp $1/libspeex/resample.c src
|
||||
cp $1/libspeex/arch.h src
|
||||
cp $1/libspeex/stack_alloc.h src
|
||||
@ -15,3 +16,6 @@ cp $1/include/speex/speex_types.h src
|
||||
sed -e 's/unsigned @SIZE16@/uint16_t/g' -e 's/unsigned @SIZE32@/uint32_t/g' -e 's/@SIZE16@/int16_t/g' -e 's/@SIZE32@/int32_t/g' < $1/include/speex/speex_config_types.h.in > src/speex_config_types.h
|
||||
cp $1/AUTHORS .
|
||||
cp $1/COPYING .
|
||||
|
||||
# apply outstanding local patches
|
||||
patch -p1 < truncation.patch
|
||||
|
@ -41,10 +41,14 @@ public:
|
||||
if (!observerService)
|
||||
return;
|
||||
|
||||
nsresult rv = observerService->AddObserver(this,
|
||||
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
false);
|
||||
MOZ_ASSERT(rv == NS_OK);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
rv = observerService->AddObserver(this,
|
||||
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
false);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
|
||||
#endif
|
||||
(void) rv;
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,9 @@ PeerConnectionImpl::PeerConnectionImpl()
|
||||
, mIdentity(NULL)
|
||||
, mSTSThread(NULL)
|
||||
, mMedia(new PeerConnectionMedia(this)) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
#endif
|
||||
}
|
||||
|
||||
PeerConnectionImpl::~PeerConnectionImpl()
|
||||
@ -288,10 +290,13 @@ NS_IMETHODIMP
|
||||
PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver,
|
||||
nsIDOMWindow* aWindow,
|
||||
nsIThread* aThread) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
#endif
|
||||
MOZ_ASSERT(aObserver);
|
||||
MOZ_ASSERT(aThread);
|
||||
mPCObserver = aObserver;
|
||||
|
||||
mPCObserver = do_GetWeakReference(aObserver);
|
||||
|
||||
nsresult res;
|
||||
|
||||
@ -521,8 +526,12 @@ PeerConnectionImpl::NotifyConnection()
|
||||
CSFLogDebugS(logTag, __FUNCTION__);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(mPCObserver,
|
||||
WrapRunnable(pco,
|
||||
&IPeerConnectionObserver::NotifyConnection),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
@ -536,10 +545,13 @@ PeerConnectionImpl::NotifyClosedConnection()
|
||||
CSFLogDebugS(logTag, __FUNCTION__);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(mPCObserver,
|
||||
&IPeerConnectionObserver::NotifyClosedConnection),
|
||||
NS_DISPATCH_NORMAL);
|
||||
WrapRunnable(pco, &IPeerConnectionObserver::NotifyClosedConnection),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -565,15 +577,20 @@ PeerConnectionImpl::NotifyDataChannel(already_AddRefed<mozilla::DataChannel> aCh
|
||||
CSFLogDebugS(logTag, __FUNCTION__ << ": channel: " << static_cast<void*>(aChannel.get()));
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsCOMPtr<nsIDOMDataChannel> domchannel;
|
||||
nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow,
|
||||
getter_AddRefs(domchannel));
|
||||
nsCOMPtr<nsIDOMDataChannel> domchannel;
|
||||
nsresult rv = NS_NewDOMDataChannel(aChannel, mWindow,
|
||||
getter_AddRefs(domchannel));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnableNM(NotifyDataChannel_m,
|
||||
domchannel.get(),
|
||||
mPCObserver),
|
||||
pco),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
}
|
||||
@ -996,16 +1013,20 @@ PeerConnectionImpl::onCallEvent(ccapi_call_event_e aCallEvent,
|
||||
break;
|
||||
}
|
||||
|
||||
if (mPCObserver) {
|
||||
PeerConnectionObserverDispatch* runnable =
|
||||
new PeerConnectionObserverDispatch(aInfo, this, mPCObserver);
|
||||
|
||||
if (mThread) {
|
||||
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
runnable->Run();
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
|
||||
PeerConnectionObserverDispatch* runnable =
|
||||
new PeerConnectionObserverDispatch(aInfo, this, pco);
|
||||
|
||||
if (mThread) {
|
||||
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
runnable->Run();
|
||||
delete runnable;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1016,7 +1037,11 @@ PeerConnectionImpl::ChangeReadyState(PeerConnectionImpl::ReadyState aReadyState)
|
||||
|
||||
// Note that we are passing an nsRefPtr<IPeerConnectionObserver> which
|
||||
// keeps the observer live.
|
||||
RUN_ON_THREAD(mThread, WrapRunnable(mPCObserver,
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
RUN_ON_THREAD(mThread, WrapRunnable(pco,
|
||||
&IPeerConnectionObserver::OnStateChange,
|
||||
// static_cast needed to work around old Android NDK r5c compiler
|
||||
static_cast<int>(IPeerConnectionObserver::kReadyState)),
|
||||
@ -1070,14 +1095,16 @@ PeerConnectionImpl::IceGatheringCompleted_m(NrIceCtx *aCtx)
|
||||
mIceState = kIceWaiting;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
if (mPCObserver) {
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(mPCObserver,
|
||||
&IPeerConnectionObserver::OnStateChange,
|
||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return NS_OK;
|
||||
}
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pco,
|
||||
&IPeerConnectionObserver::OnStateChange,
|
||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1105,14 +1132,16 @@ PeerConnectionImpl::IceCompleted_m(NrIceCtx *aCtx)
|
||||
mIceState = kIceConnected;
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
if (mPCObserver) {
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(mPCObserver,
|
||||
&IPeerConnectionObserver::OnStateChange,
|
||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
nsCOMPtr<IPeerConnectionObserver> pco = do_QueryReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return NS_OK;
|
||||
}
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pco,
|
||||
&IPeerConnectionObserver::OnStateChange,
|
||||
// static_cast required to work around old C++ compiler on Android NDK r5c
|
||||
static_cast<int>(IPeerConnectionObserver::kIceState)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include "prlock.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIWeakReferenceUtils.h" // for the definition of nsWeakPtr
|
||||
#include "IPeerConnection.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
@ -230,7 +232,9 @@ private:
|
||||
IceState mIceState;
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsCOMPtr<IPeerConnectionObserver> mPCObserver;
|
||||
// Weak pointer to IPeerConnectionObserver
|
||||
// This is only safe to use on the main thread
|
||||
nsWeakPtr mPCObserver;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// The SDP sent in from JS - here for debugging.
|
||||
|
@ -1779,6 +1779,8 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
||||
cc_sdp_t *sdp_p = dcb_p->sdp;
|
||||
uint16_t media_attr;
|
||||
uint16_t i;
|
||||
uint32 port;
|
||||
int sdpmode = 0;
|
||||
static const sdp_attr_e dir_attr_array[] = {
|
||||
SDP_ATTR_INACTIVE,
|
||||
SDP_ATTR_RECVONLY,
|
||||
@ -1791,6 +1793,8 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
||||
return direction;
|
||||
}
|
||||
|
||||
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||
|
||||
media_attr = 0; /* media level attr. count */
|
||||
/*
|
||||
* Now check for direction as a media attribute. If found, the
|
||||
@ -1842,6 +1846,17 @@ gsmsdp_get_remote_sdp_direction (fsmdef_dcb_t *dcb_p, uint16_t level,
|
||||
if (dest_addr->type == CPR_IP_ADDR_IPV4 &&
|
||||
dest_addr->u.ip4 == 0) {
|
||||
|
||||
/*
|
||||
* For WebRTC, we allow active media sections with IP=0.0.0.0, iff
|
||||
* port != 0. This is to allow interop with existing Trickle ICE
|
||||
* implementations. TODO: This may need to be updated to match the
|
||||
* spec once the Trickle ICE spec is finalized.
|
||||
*/
|
||||
port = sdp_get_media_portnum(sdp_p->dest_sdp, level);
|
||||
if (sdpmode && port != 0) {
|
||||
return direction;
|
||||
}
|
||||
|
||||
direction = SDP_DIRECTION_INACTIVE;
|
||||
} else {
|
||||
|
||||
|
@ -133,6 +133,7 @@ LOCAL_INCLUDES += \
|
||||
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
|
||||
-I$(topsrcdir)/media/webrtc/signaling/media-conduit\
|
||||
-I$(topsrcdir)/media/webrtc/trunk/third_party/libjingle/source/ \
|
||||
-I$(topsrcdir)/xpcom/base/ \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_TARGET),WINNT)
|
||||
|
@ -23,9 +23,11 @@ using namespace std;
|
||||
#include "FakeMediaStreams.h"
|
||||
#include "FakeMediaStreamsImpl.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "PeerConnectionCtx.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "nsStaticComponents.h"
|
||||
#include "nsIDOMRTCPeerConnection.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "mtransport_test_utils.h"
|
||||
MtransportTestUtils *test_utils;
|
||||
@ -118,7 +120,8 @@ enum offerAnswerFlags
|
||||
};
|
||||
|
||||
|
||||
class TestObserver : public IPeerConnectionObserver
|
||||
class TestObserver : public IPeerConnectionObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
enum Action {
|
||||
@ -163,7 +166,9 @@ private:
|
||||
std::vector<nsDOMMediaStream *> streams;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(TestObserver, IPeerConnectionObserver)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(TestObserver,
|
||||
IPeerConnectionObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
NS_IMETHODIMP
|
||||
TestObserver::OnCreateOfferSuccess(const char* offer)
|
||||
@ -489,7 +494,7 @@ class SignalingAgent {
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
void Init(nsCOMPtr<nsIThread> thread)
|
||||
void Init_m(nsCOMPtr<nsIThread> thread)
|
||||
{
|
||||
size_t found = 2;
|
||||
ASSERT_TRUE(found > 0);
|
||||
@ -502,6 +507,14 @@ class SignalingAgent {
|
||||
|
||||
ASSERT_EQ(pc->Initialize(pObserver, nullptr, thread), NS_OK);
|
||||
|
||||
}
|
||||
|
||||
void Init(nsCOMPtr<nsIThread> thread)
|
||||
{
|
||||
thread->Dispatch(
|
||||
WrapRunnable(this, &SignalingAgent::Init_m, thread),
|
||||
NS_DISPATCH_SYNC);
|
||||
|
||||
ASSERT_TRUE_WAIT(sipcc_state() == sipcc::PeerConnectionImpl::kStarted,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(ice_state() == sipcc::PeerConnectionImpl::kIceWaiting, 5000);
|
||||
@ -592,14 +605,18 @@ class SignalingAgent {
|
||||
// Now call CreateOffer as JS would
|
||||
pObserver->state = TestObserver::stateNoResponse;
|
||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
||||
offer_ = pObserver->lastString;
|
||||
}
|
||||
|
||||
void CreateOfferExpectError(sipcc::MediaConstraints& constraints) {
|
||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateError, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
}
|
||||
|
||||
void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
@ -628,7 +645,9 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
|
||||
pObserver->state = TestObserver::stateNoResponse;
|
||||
ASSERT_EQ(pc->CreateAnswer(constraints), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
SDPSanityCheck(pObserver->lastString, sdpCheck, false);
|
||||
|
||||
answer_ = pObserver->lastString;
|
||||
@ -653,7 +672,9 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
// Now call CreateOffer as JS would
|
||||
pObserver->state = TestObserver::stateNoResponse;
|
||||
ASSERT_EQ(pc->CreateOffer(constraints), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
SDPSanityCheck(pObserver->lastString, sdpCheck, true);
|
||||
offer_ = pObserver->lastString;
|
||||
}
|
||||
@ -661,13 +682,17 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
void SetRemote(TestObserver::Action action, std::string remote) {
|
||||
pObserver->state = TestObserver::stateNoResponse;
|
||||
ASSERT_EQ(pc->SetRemoteDescription(action, remote.c_str()), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
}
|
||||
|
||||
void SetLocal(TestObserver::Action action, std::string local) {
|
||||
pObserver->state = TestObserver::stateNoResponse;
|
||||
ASSERT_EQ(pc->SetLocalDescription(action, local.c_str()), NS_OK);
|
||||
ASSERT_TRUE_WAIT(pObserver->state == TestObserver::stateSuccess, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(pObserver->state != TestObserver::stateNoResponse,
|
||||
kDefaultTimeout);
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
}
|
||||
|
||||
void DoTrickleIce(ParsedSDP &sdp) {
|
||||
@ -734,6 +759,7 @@ public:
|
||||
private:
|
||||
void SDPSanityCheck(std::string sdp, uint32_t flags, bool offer)
|
||||
{
|
||||
ASSERT_TRUE(pObserver->state == TestObserver::stateSuccess);
|
||||
ASSERT_NE(sdp.find("v=0"), std::string::npos);
|
||||
ASSERT_NE(sdp.find("c=IN IP4"), std::string::npos);
|
||||
ASSERT_NE(sdp.find("a=fingerprint:sha-256"), std::string::npos);
|
||||
@ -1700,6 +1726,32 @@ TEST_F(SignalingTest, CheckTrickleSdpChange)
|
||||
ASSERT_EQ(a2_.getLocalDescription(),a1_.getRemoteDescription());
|
||||
}
|
||||
|
||||
TEST_F(SignalingTest, ipAddrAnyOffer)
|
||||
{
|
||||
sipcc::MediaConstraints constraints;
|
||||
std::string offer =
|
||||
"v=0\r\n"
|
||||
"o=- 1 1 IN IP4 127.0.0.1\r\n"
|
||||
"s=-\r\n"
|
||||
"b=AS:64\r\n"
|
||||
"t=0 0\r\n"
|
||||
"a=fingerprint:sha-256 F3:FA:20:C0:CD:48:C4:5F:02:5F:A5:D3:21:D0:2D:48:"
|
||||
"7B:31:60:5C:5A:D8:0D:CD:78:78:6C:6D:CE:CC:0C:67\r\n"
|
||||
"m=audio 9000 RTP/AVP 99\r\n"
|
||||
"c=IN IP4 0.0.0.0\r\n"
|
||||
"a=rtpmap:99 opus/48000/2\r\n"
|
||||
"a=ice-ufrag:cYuakxkEKH+RApYE\r\n"
|
||||
"a=ice-pwd:bwtpzLZD+3jbu8vQHvEa6Xuq\r\n"
|
||||
"a=sendrecv\r\n";
|
||||
|
||||
a2_.SetRemote(TestObserver::OFFER, offer);
|
||||
ASSERT_TRUE(a2_.pObserver->state == TestObserver::stateSuccess);
|
||||
a2_.CreateAnswer(constraints, offer, OFFER_AUDIO | ANSWER_AUDIO);
|
||||
ASSERT_TRUE(a2_.pObserver->state == TestObserver::stateSuccess);
|
||||
std::string answer = a2_.answer();
|
||||
ASSERT_NE(answer.find("a=sendrecv"), std::string::npos);
|
||||
}
|
||||
|
||||
} // End namespace test.
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@ -1720,6 +1772,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
::testing::AddGlobalTestEnvironment(new test::SignalingEnvironment);
|
||||
int result = RUN_ALL_TESTS();
|
||||
|
||||
// Because we don't initialize on the main thread, we can't register for
|
||||
// XPCOM shutdown callbacks (where the context is usually shut down) --
|
||||
// so we need to explictly destroy the context.
|
||||
sipcc::PeerConnectionCtx::Destroy();
|
||||
delete test_utils;
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
49
mfbt/Range.h
Normal file
49
mfbt/Range.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* 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_Range_h_
|
||||
#define mozilla_Range_h_
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Range<T> is a tuple containing a pointer and a length.
|
||||
template <typename T>
|
||||
class Range
|
||||
{
|
||||
RangedPtr<T> mStart;
|
||||
RangedPtr<T> mEnd;
|
||||
|
||||
typedef void (Range::* ConvertibleToBool)();
|
||||
void nonNull() {}
|
||||
|
||||
public:
|
||||
Range() : mStart(nullptr, 0), mEnd(nullptr, 0) {}
|
||||
Range(T* p, size_t len)
|
||||
: mStart(p, p, p + len),
|
||||
mEnd(p + len, p, p + len)
|
||||
{}
|
||||
|
||||
RangedPtr<T> start() const { return mStart; }
|
||||
RangedPtr<T> end() const { return mEnd; }
|
||||
size_t length() const { return mEnd - mStart; }
|
||||
|
||||
T& operator[](size_t offset) {
|
||||
return mStart[offset];
|
||||
}
|
||||
|
||||
operator ConvertibleToBool() const { return mStart ? &Range::nonNull : 0; }
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_Range_h_
|
||||
|
@ -46,6 +46,9 @@ class RangedPtr
|
||||
T* const rangeEnd;
|
||||
#endif
|
||||
|
||||
typedef void (RangedPtr::* ConvertibleToBool)();
|
||||
void nonNull() {}
|
||||
|
||||
void checkSanity() {
|
||||
MOZ_ASSERT(rangeStart <= ptr);
|
||||
MOZ_ASSERT(ptr <= rangeEnd);
|
||||
@ -97,7 +100,7 @@ class RangedPtr
|
||||
|
||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||
template<size_t N>
|
||||
RangedPtr(T arr[N])
|
||||
RangedPtr(T (&arr)[N])
|
||||
: ptr(arr)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(arr), rangeEnd(arr + N)
|
||||
@ -110,6 +113,8 @@ class RangedPtr
|
||||
return ptr;
|
||||
}
|
||||
|
||||
operator ConvertibleToBool() const { return ptr ? &RangedPtr::nonNull : 0; }
|
||||
|
||||
/*
|
||||
* You can only assign one RangedPtr into another if the two pointers have
|
||||
* the same valid range:
|
||||
@ -242,7 +247,6 @@ class RangedPtr
|
||||
private:
|
||||
RangedPtr() MOZ_DELETE;
|
||||
T* operator&() MOZ_DELETE;
|
||||
operator T*() const MOZ_DELETE;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
@ -25,6 +25,7 @@ EXPORTS_mozilla += \
|
||||
MathAlgorithms.h \
|
||||
MSStdInt.h \
|
||||
NullPtr.h \
|
||||
Range.h \
|
||||
RangedPtr.h \
|
||||
RefPtr.h \
|
||||
Scoped.h \
|
||||
|
@ -46,7 +46,6 @@ DEFINES += \
|
||||
-DAPP_NAME=$(MOZ_APP_NAME) \
|
||||
-DAPP_VERSION=$(MOZ_APP_VERSION) \
|
||||
-DMOZ_UPDATER=$(MOZ_UPDATER) \
|
||||
-DMOZ_APP_UA_NAME=$(MOZ_APP_UA_NAME) \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PKG_SPECIAL
|
||||
|
@ -573,8 +573,6 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
|
||||
pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
|
||||
pref("browser.safebrowsing.id", "@MOZ_APP_UA_NAME@");
|
||||
|
||||
// Name of the about: page contributed by safebrowsing to handle display of error
|
||||
// pages on phishing/malware hits. (bug 399233)
|
||||
pref("urlclassifier.alternate_error_page", "blocked");
|
||||
|
@ -39,4 +39,14 @@ EXTRA_COMPONENTS = \
|
||||
BlocklistPrompt.js \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_SAFE_BROWSING
|
||||
DEFINES += \
|
||||
-DMOZ_APP_UA_NAME=$(MOZ_APP_UA_NAME) \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_PP_JS_MODULES = \
|
||||
SafeBrowsing.jsm \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
182
mobile/android/components/SafeBrowsing.jsm
Normal file
182
mobile/android/components/SafeBrowsing.jsm
Normal file
@ -0,0 +1,182 @@
|
||||
/* 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/. */
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["SafeBrowsing"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const phishingList = "goog-phish-shavar";
|
||||
const malwareList = "goog-malware-shavar";
|
||||
|
||||
var debug = false;
|
||||
|
||||
function log(...stuff) {
|
||||
if (!debug)
|
||||
return;
|
||||
|
||||
let msg = "SafeBrowsing: " + stuff.join(" ");
|
||||
Services.console.logStringMessage(msg);
|
||||
dump(msg + "\n");
|
||||
}
|
||||
|
||||
this.SafeBrowsing = {
|
||||
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
log("Already initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
Services.prefs.addObserver("browser.safebrowsing", this.readPrefs, false);
|
||||
this.readPrefs();
|
||||
|
||||
// Register our two types of tables, and add custom Mozilla entries
|
||||
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||
getService(Ci.nsIUrlListManager);
|
||||
listManager.registerTable(phishingList, false);
|
||||
listManager.registerTable(malwareList, false);
|
||||
this.addMozEntries();
|
||||
|
||||
this.controlUpdateChecking();
|
||||
this.initialized = true;
|
||||
|
||||
log("init() finished");
|
||||
},
|
||||
|
||||
|
||||
initialized: false,
|
||||
phishingEnabled: false,
|
||||
malwareEnabled: false,
|
||||
|
||||
updateURL: null,
|
||||
keyURL: null,
|
||||
gethashURL: null,
|
||||
|
||||
reportURL: null,
|
||||
reportGenericURL: null,
|
||||
reportErrorURL: null,
|
||||
reportPhishURL: null,
|
||||
reportMalwareURL: null,
|
||||
reportMalwareErrorURL: null,
|
||||
|
||||
|
||||
getReportURL: function(kind) {
|
||||
return this["report" + kind + "URL"];
|
||||
},
|
||||
|
||||
|
||||
readPrefs: function() {
|
||||
log("reading prefs");
|
||||
|
||||
debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
|
||||
this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
|
||||
this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
|
||||
this.updateProviderURLs();
|
||||
|
||||
// XXX The listManager backend gets confused if this is called before the
|
||||
// lists are registered. So only call it here when a pref changes, and not
|
||||
// when doing initialization. I expect to refactor this later, so pardon the hack.
|
||||
if (this.initialized)
|
||||
this.controlUpdateChecking();
|
||||
},
|
||||
|
||||
|
||||
updateProviderURLs: function() {
|
||||
#ifdef USE_HISTORIC_SAFEBROWSING_ID
|
||||
let clientID = "navclient-auto-ffox";
|
||||
#else
|
||||
#expand let clientID = __MOZ_APP_UA_NAME__;
|
||||
#endif
|
||||
|
||||
log("initializing safe browsing URLs");
|
||||
let basePref = "browser.safebrowsing.";
|
||||
|
||||
// Urls to HTML report pages
|
||||
this.reportURL = Services.urlFormatter.formatURLPref(basePref + "reportURL");
|
||||
this.reportGenericURL = Services.urlFormatter.formatURLPref(basePref + "reportGenericURL");
|
||||
this.reportErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportErrorURL");
|
||||
this.reportPhishURL = Services.urlFormatter.formatURLPref(basePref + "reportPhishURL");
|
||||
this.reportMalwareURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareURL");
|
||||
this.reportMalwareErrorURL = Services.urlFormatter.formatURLPref(basePref + "reportMalwareErrorURL");
|
||||
|
||||
// Urls used to update DB
|
||||
this.updateURL = Services.urlFormatter.formatURLPref(basePref + "updateURL");
|
||||
this.keyURL = Services.urlFormatter.formatURLPref(basePref + "keyURL");
|
||||
this.gethashURL = Services.urlFormatter.formatURLPref(basePref + "gethashURL");
|
||||
|
||||
this.updateURL = this.updateURL.replace("SAFEBROWSING_ID", clientID);
|
||||
this.keyURL = this.keyURL.replace("SAFEBROWSING_ID", clientID);
|
||||
this.gethashURL = this.gethashURL.replace("SAFEBROWSING_ID", clientID);
|
||||
|
||||
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||
getService(Ci.nsIUrlListManager);
|
||||
|
||||
listManager.setUpdateUrl(this.updateURL);
|
||||
// XXX Bug 779317 - setKeyUrl has the side effect of fetching a key from the server.
|
||||
// This shouldn't happen if anti-phishing/anti-malware is disabled.
|
||||
if (this.phishingEnabled || this.malwareEnabled)
|
||||
listManager.setKeyUrl(this.keyURL);
|
||||
listManager.setGethashUrl(this.gethashURL);
|
||||
},
|
||||
|
||||
|
||||
controlUpdateChecking: function() {
|
||||
log("phishingEnabled:", this.phishingEnabled, "malwareEnabled:", this.malwareEnabled);
|
||||
|
||||
let listManager = Cc["@mozilla.org/url-classifier/listmanager;1"].
|
||||
getService(Ci.nsIUrlListManager);
|
||||
|
||||
if (this.phishingEnabled)
|
||||
listManager.enableUpdate(phishingList);
|
||||
else
|
||||
listManager.disableUpdate(phishingList);
|
||||
|
||||
if (this.malwareEnabled)
|
||||
listManager.enableUpdate(malwareList);
|
||||
else
|
||||
listManager.disableUpdate(malwareList);
|
||||
},
|
||||
|
||||
|
||||
addMozEntries: function() {
|
||||
// Add test entries to the DB.
|
||||
// XXX bug 779008 - this could be done by DB itself?
|
||||
const phishURL = "mozilla.org/firefox/its-a-trap.html";
|
||||
const malwareURL = "mozilla.org/firefox/its-an-attack.html";
|
||||
|
||||
let update = "n:1000\ni:test-malware-simple\nad:1\n" +
|
||||
"a:1:32:" + malwareURL.length + "\n" +
|
||||
malwareURL;
|
||||
update += "n:1000\ni:test-phish-simple\nad:1\n" +
|
||||
"a:1:32:" + phishURL.length + "\n" +
|
||||
phishURL;
|
||||
log("addMozEntries:", update);
|
||||
|
||||
let db = Cc["@mozilla.org/url-classifier/dbservice;1"].
|
||||
getService(Ci.nsIUrlClassifierDBService);
|
||||
|
||||
// nsIUrlClassifierUpdateObserver
|
||||
let dummyListener = {
|
||||
updateUrlRequested: function() { },
|
||||
streamFinished: function() { },
|
||||
updateError: function() { },
|
||||
updateSuccess: function() { }
|
||||
};
|
||||
|
||||
try {
|
||||
db.beginUpdate(dummyListener, "test-malware-simple,test-phish-simple", "");
|
||||
db.beginStream("", "");
|
||||
db.updateStream(update);
|
||||
db.finishStream();
|
||||
db.finishUpdate();
|
||||
} catch(ex) {
|
||||
// beginUpdate will throw harmlessly if there's an existing update in progress, ignore failures.
|
||||
log("addMozEntries failed!", ex);
|
||||
}
|
||||
},
|
||||
};
|
@ -297,8 +297,6 @@
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
||||
@BINPATH@/components/nsSidebar.manifest
|
||||
@BINPATH@/components/nsSidebar.js
|
||||
@BINPATH@/components/extensions.manifest
|
||||
|
@ -345,8 +345,6 @@
|
||||
@BINPATH@/components/nsDownloadManagerUI.js
|
||||
@BINPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@BINPATH@/components/NetworkGeolocationProvider.js
|
||||
@BINPATH@/components/GPSDGeolocationProvider.manifest
|
||||
@BINPATH@/components/GPSDGeolocationProvider.js
|
||||
@BINPATH@/components/nsSidebar.manifest
|
||||
@BINPATH@/components/nsSidebar.js
|
||||
@BINPATH@/components/extensions.manifest
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user