import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1163826 - Add remainder of top .jp sites to CSS unprefixing service whitelist. r=dholbert (8ed22f2638)
- Bug 1165834: Add alicdn.com (used by taobao.com) to the CSS Unprefixing Service whitelist. r=miketaylr (30d150c28c)
- Bug 1166792 - Add 3rd batch of top .jp sites to CSS unprefixing service whitelists. r=dholbert (e4073c1f09)
- Bug 1170375 - Add 4th batch of top .jp sites to CSS unprefixing service whitelists. r=dholbert (d741e57cb0)
- Bug 1207850 - Temporary fix for canceling the pump used by FetchBody. r=nsm (bc85cb1500)
- Bug 1224865: Don't set a document in FetchDriver for requests in workers. r=bkelly (7bcb0bd16b)
- Bug 1108181 - Make Headers iterable; r=bzbarsky (da8d6f8bb2)
- Bug 1217501 P5 Relax guard checking on Headers with existing headers. r=ehsan (75ec3b6ae5)
- Bug 1207882 - Use a separate build target for config/buildid. r=gps (ad9f536aac)
- Bug 1216697 - Unship Request.cache until the implementation is finished; r=bzbarsky (49264a21d8)
- Bug 1218119 - Simplify defining worker prefs; r=baku (8987aa23c3)
- namespace (d88c3b7fc6)
- Bug 1179489 - Don't count service workers towards an origin's max worker quota; r=nsm (ce5e1345ba)
- Bug 1151646 - Cleanup, r=khuey. (d119d19ea7)
- Bug 1118778 - Write upload properties from upload.py; r=glandium (f8745ffda8)
- Bug 1194741 - Display upload output; r=nalexander (7adaa41d11)
- Bug 1197293 - allow for TC builds that don't use 'make upload'; r=ted (e671e7c651)
- Bug 1137000 - Add support for SDK building to moz-automation.mk. r=mshal (69b7ccb3c8)
- Bug 1175895 - aid greppability of MOZ_AUTOMATION_*; r=ted (c9a099f168)
- Bug 1198179 - Kill gen_mach_buildprops.py; r=ted (fa74e1930f)
- Bug 1198179 - make upload.py write properties even if not uploading; r=ted (e7ca79b807)
- Bug 8623031 - Move desktop build logic to a container neutral location; r=dustin (81dc866373)
- Bug 1187139 (part 1) - Replace nsBaseHashtable::Enumerate() calls in accessible/ with iterators. r=tbsaunde. (7a75c73d17)
- Bug 1187139 (part 2) - Replace nsBaseHashtable::Enumerate() calls in accessible/ with iterators. r=tbsaunde. (c631350ddb)
- Bug 1187139 (part 3) - Replace nsBaseHashtable::Enumerate() calls in accessible/ with iterators. r=tbsaunde. (052cced2ca)
- Bug 1225396 part 4 - Remove @@iterator workaround in Codegen.py. r=bz (3b05ddc4f0)
- Bug 1048695 part 1. Pass the set of globals where a member should NOT be exposed to MemberCondition. r=peterv (d5c9040323)
- Bug 1048695 part 2. Make interface members not be exposed based on their nonExposedGlobals. r=peterv (e852319bd0)
- Bug 1229493 - Stop shell-only modules classes being reported as standard classes r=shu (4a6457af8d)
- Bug 1151646 - Fix static analysis bustage. (347564b4d2)
- Bug 1231051 - Moz2Dify nsNativeThemeCocoa::DrawWidgetBackground. r=mstange. (cbcbe17e30)
- Bug 1178984 - Crashes at nsMenuBarX::RemoveMenuAtIndex. r=spohl (6e5869ae28)
- leftovers of Bug 1151345 - Add debug logging to help decipher this bug. r=spohl (22d42fc66d)
This commit is contained in:
2023-04-04 12:14:15 +08:00
parent 09c7525bc8
commit f855ceaa31
71 changed files with 1003 additions and 781 deletions
+17 -23
View File
@@ -12,40 +12,34 @@
// Accessible cache utils
////////////////////////////////////////////////////////////////////////////////
/**
* Shutdown and removes the accessible from cache.
*/
template <class T>
static PLDHashOperator
ClearCacheEntry(const void* aKey, RefPtr<T>& aAccessible, void* aUserArg)
void
UnbindCacheEntriesFromDocument(
nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
NS_ASSERTION(aAccessible, "Calling ClearCacheEntry with a nullptr pointer!");
if (aAccessible && !aAccessible->IsDefunct())
aAccessible->Shutdown();
return PL_DHASH_REMOVE;
}
template <class T>
static PLDHashOperator
UnbindCacheEntryFromDocument(const void* aKey, RefPtr<T>& aAccessible,
void* aUserArg)
{
MOZ_ASSERT(aAccessible && !aAccessible->IsDefunct());
aAccessible->Document()->UnbindFromDocument(aAccessible);
return PL_DHASH_REMOVE;
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible && !accessible->IsDefunct());
accessible->Document()->UnbindFromDocument(accessible);
iter.Remove();
}
}
/**
* Clear the cache and shutdown the accessibles.
*/
template <class T>
static void
ClearCache(nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
aCache.Enumerate(ClearCacheEntry<T>, nullptr);
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible);
if (accessible && !accessible->IsDefunct()) {
accessible->Shutdown();
}
iter.Remove();
}
}
#endif
+4 -9
View File
@@ -195,17 +195,12 @@ xpcAccessibleDocument::GetAccessible(Accessible* aAccessible)
return xpcAcc;
}
static PLDHashOperator
ShutdownAndRemove(const Accessible* aKey, RefPtr<xpcAccessibleGeneric>& aValue,
void* aUnused)
{
aValue->Shutdown();
return PL_DHASH_REMOVE;
}
void
xpcAccessibleDocument::Shutdown()
{
mCache.Enumerate(ShutdownAndRemove, nullptr);
for (auto iter = mCache.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->Shutdown();
iter.Remove();
}
xpcAccessibleGeneric::Shutdown();
}
+7 -9
View File
@@ -145,8 +145,9 @@ XULTreeAccessible::Value(nsString& aValue)
void
XULTreeAccessible::Shutdown()
{
if (mDoc && !mDoc->IsDefunct())
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>, nullptr);
if (mDoc && !mDoc->IsDefunct()) {
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
mTree = nullptr;
mTreeView = nullptr;
@@ -550,8 +551,7 @@ XULTreeAccessible::InvalidateCache(int32_t aRow, int32_t aCount)
return;
if (!mTreeView) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
return;
}
@@ -609,8 +609,7 @@ XULTreeAccessible::TreeViewInvalidated(int32_t aStartRow, int32_t aEndRow,
return;
if (!mTreeView) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
return;
}
@@ -669,8 +668,7 @@ XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
Document()->FireDelayedEvent(reorderEvent);
// Clear cache.
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<Accessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
mTreeView = aView;
}
@@ -687,7 +685,7 @@ XULTreeAccessible::CreateTreeItemAccessible(int32_t aRow) const
return accessible.forget();
}
////////////////////////////////////////////////////////////////////////////////
// XULTreeItemAccessibleBase
////////////////////////////////////////////////////////////////////////////////
+1 -2
View File
@@ -277,8 +277,7 @@ void
XULTreeGridRowAccessible::Shutdown()
{
if (mDoc && !mDoc->IsDefunct()) {
mAccessibleCache.Enumerate(UnbindCacheEntryFromDocument<XULTreeGridCellAccessible>,
nullptr);
UnbindCacheEntriesFromDocument(mAccessibleCache);
}
XULTreeItemAccessibleBase::Shutdown();
-124
View File
@@ -1,124 +0,0 @@
#!/usr/bin/python
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import os
import hashlib
import json
import re
import errno
from argparse import ArgumentParser
def getFileHashAndSize(filename):
sha512Hash = 'UNKNOWN'
size = 'UNKNOWN'
try:
# open in binary mode to make sure we get consistent results
# across all platforms
f = open(filename, "rb")
shaObj = hashlib.sha512(f.read())
sha512Hash = shaObj.hexdigest()
size = os.path.getsize(filename)
except:
pass
return (sha512Hash, size)
def getMarProperties(filename, partial=False):
if not os.path.exists(filename):
return {}
(mar_hash, mar_size) = getFileHashAndSize(filename)
martype = 'partial' if partial else 'complete'
return {
'%sMarFilename' % martype: os.path.basename(filename),
'%sMarSize' % martype: mar_size,
'%sMarHash' % martype: mar_hash,
}
def getUrlProperties(filename, package):
# let's create a switch case using name-spaces/dict
# rather than a long if/else with duplicate code
property_conditions = [
# key: property name, value: condition
('testsUrl', lambda m: m.endswith(('tests.tar.bz2', 'tests.zip'))),
('unsignedApkUrl', lambda m: m.endswith('apk') and
'unsigned-unaligned' in m),
('robocopApkUrl', lambda m: m.endswith('apk') and 'robocop' in m),
('jsshellUrl', lambda m: 'jsshell-' in m and m.endswith('.zip')),
('completeMarUrl', lambda m: m.endswith('.complete.mar')),
('partialMarUrl', lambda m: m.endswith('.mar') and '.partial.' in m),
('codeCoverageURL', lambda m: m.endswith('code-coverage-gcno.zip')),
('sdkUrl', lambda m: m.endswith(('sdk.tar.bz2', 'sdk.zip'))),
('testPackagesUrl', lambda m: m.endswith('test_packages.json')),
('packageUrl', lambda m: m.endswith(package)),
]
url_re = re.compile(r'''^(https?://.*?\.(?:tar\.bz2|dmg|zip|apk|rpm|mar|tar\.gz|json))$''')
properties = {}
try:
with open(filename) as f:
for line in f:
m = url_re.match(line)
if m:
m = m.group(1)
for prop, condition in property_conditions:
if condition(m):
properties.update({prop: m})
break
except IOError as e:
if e.errno != errno.ENOENT:
raise
properties = {prop: 'UNKNOWN' for prop, condition in property_conditions}
return properties
def getPartialInfo(props):
return [{
"from_buildid": props.get("previous_buildid"),
"size": props.get("partialMarSize"),
"hash": props.get("partialMarHash"),
"url": props.get("partialMarUrl"),
}]
if __name__ == '__main__':
parser = ArgumentParser(description='Generate mach_build_properties.json for automation builds.')
parser.add_argument("--complete-mar-file", required=True,
action="store", dest="complete_mar_file",
help="Path to the complete MAR file, relative to the objdir.")
parser.add_argument("--partial-mar-file", required=False,
action="store", dest="partial_mar_file",
help="Path to the partial MAR file, relative to the objdir.")
parser.add_argument("--upload-output", required=True,
action="store", dest="upload_output",
help="Path to the text output of 'make upload'")
parser.add_argument("--upload-files", required=True, nargs="+",
action="store", dest="upload_files",
help="List of files to be uploaded.")
parser.add_argument("--package", required=True,
action="store", dest="package",
help="Filename of the build package")
args = parser.parse_args()
json_data = getMarProperties(args.complete_mar_file)
json_data.update(getUrlProperties(args.upload_output, args.package))
if args.partial_mar_file:
json_data.update(getMarProperties(args.partial_mar_file, partial=True))
# Pull the previous buildid from the partial mar filename.
res = re.match(r'.*\.([0-9]+)-[0-9]+.mar', args.partial_mar_file)
if res:
json_data['previous_buildid'] = res.group(1)
# Set partialInfo to be a collection of the partial mar properties
# useful for balrog.
json_data['partialInfo'] = getPartialInfo(json_data)
json_data['uploadFiles'] = args.upload_files
json_data['packageFilename'] = args.package
with open('mach_build_properties.json', 'w') as outfile:
json.dump(json_data, outfile, indent=4)
+33 -37
View File
@@ -17,46 +17,44 @@ include $(topsrcdir)/toolkit/mozapps/installer/upload-files.mk
# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
DIST_FILES =
# Log file from the 'make upload' step. We need this to parse out the URLs of
# the uploaded files.
AUTOMATION_UPLOAD_OUTPUT = $(DIST)/automation-upload.txt
# Helper variables to convert from MOZ_AUTOMATION_* variables to the
# corresponding the make target
tier_BUILD_SYMBOLS = buildsymbols
tier_L10N_CHECK = l10n-check
tier_PRETTY_L10N_CHECK = pretty-l10n-check
tier_INSTALLER = installer
tier_PRETTY_INSTALLER = pretty-installer
tier_PACKAGE = package
tier_PRETTY_PACKAGE = pretty-package
tier_PACKAGE_TESTS = package-tests
tier_PRETTY_PACKAGE_TESTS = pretty-package-tests
tier_UPDATE_PACKAGING = update-packaging
tier_PRETTY_UPDATE_PACKAGING = pretty-update-packaging
tier_UPLOAD_SYMBOLS = uploadsymbols
tier_UPLOAD = upload
tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols
tier_MOZ_AUTOMATION_L10N_CHECK = l10n-check
tier_MOZ_AUTOMATION_PRETTY_L10N_CHECK = pretty-l10n-check
tier_MOZ_AUTOMATION_INSTALLER = installer
tier_MOZ_AUTOMATION_PRETTY_INSTALLER = pretty-installer
tier_MOZ_AUTOMATION_PACKAGE = package
tier_MOZ_AUTOMATION_PRETTY_PACKAGE = pretty-package
tier_MOZ_AUTOMATION_PACKAGE_TESTS = package-tests
tier_MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS = pretty-package-tests
tier_MOZ_AUTOMATION_UPDATE_PACKAGING = update-packaging
tier_MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING = pretty-update-packaging
tier_MOZ_AUTOMATION_UPLOAD_SYMBOLS = uploadsymbols
tier_MOZ_AUTOMATION_UPLOAD = upload
tier_MOZ_AUTOMATION_SDK = sdk
# Automation build steps. Everything in MOZ_AUTOMATION_TIERS also gets used in
# TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted
# here in the order that they will be executed (since mach doesn't know of the
# dependencies between them).
moz_automation_symbols = \
PACKAGE_TESTS \
PRETTY_PACKAGE_TESTS \
BUILD_SYMBOLS \
UPLOAD_SYMBOLS \
PACKAGE \
PRETTY_PACKAGE \
INSTALLER \
PRETTY_INSTALLER \
UPDATE_PACKAGING \
PRETTY_UPDATE_PACKAGING \
L10N_CHECK \
PRETTY_L10N_CHECK \
UPLOAD \
MOZ_AUTOMATION_PACKAGE_TESTS \
MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS \
MOZ_AUTOMATION_BUILD_SYMBOLS \
MOZ_AUTOMATION_UPLOAD_SYMBOLS \
MOZ_AUTOMATION_PACKAGE \
MOZ_AUTOMATION_PRETTY_PACKAGE \
MOZ_AUTOMATION_INSTALLER \
MOZ_AUTOMATION_PRETTY_INSTALLER \
MOZ_AUTOMATION_UPDATE_PACKAGING \
MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING \
MOZ_AUTOMATION_L10N_CHECK \
MOZ_AUTOMATION_PRETTY_L10N_CHECK \
MOZ_AUTOMATION_UPLOAD \
MOZ_AUTOMATION_SDK \
$(NULL)
MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$(MOZ_AUTOMATION_$(sym))),$(tier_$(sym))))
MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$($(sym))),$(tier_$(sym))))
# Dependencies between automation build steps
automation/uploadsymbols: automation/buildsymbols
@@ -76,15 +74,17 @@ automation/upload: automation/package
automation/upload: automation/package-tests
automation/upload: automation/buildsymbols
automation/upload: automation/update-packaging
automation/upload: automation/sdk
# automation/{pretty-}package should depend on build (which is implicit due to
# the way client.mk invokes automation/build), but buildsymbols changes the
# binaries/libs, and that's what we package/test.
automation/pretty-package: automation/buildsymbols
# The installer and packager both run stage-package, and may conflict
# The installer, sdk and packager all run stage-package, and may conflict
# with each other.
automation/installer: automation/package
automation/sdk: automation/installer automation/package
# The 'pretty' versions of targets run before the regular ones to avoid
# conflicts in writing to the same files.
@@ -95,11 +95,7 @@ automation/l10n-check: automation/pretty-l10n-check
automation/update-packaging: automation/pretty-update-packaging
automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
$(PYTHON) $(topsrcdir)/build/gen_mach_buildprops.py --complete-mar-file $(DIST)/$(COMPLETE_MAR) $(addprefix --partial-mar-file ,$(wildcard $(DIST)/$(PARTIAL_MAR))) --upload-output $(AUTOMATION_UPLOAD_OUTPUT) --upload-files $(abspath $(UPLOAD_FILES)) --package $(PACKAGE)
# We need the log from make upload to grep it for urls in order to set
# properties.
AUTOMATION_EXTRA_CMDLINE-upload = 2>&1 | tee $(AUTOMATION_UPLOAD_OUTPUT)
@echo Automation steps completed.
# Note: We have to force -j1 here, at least until bug 1036563 is fixed.
AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1
+1
View File
@@ -17,6 +17,7 @@ mk_add_options "export MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}"
mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}"
mk_add_options "export MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-0}"
# If we are also building with MOZ_PKG_PRETTYNAMES, set the corresponding
# stages.
+121 -24
View File
@@ -8,7 +8,12 @@
# to be set:
# UPLOAD_HOST : host to upload files to
# UPLOAD_USER : username on that host
# and one of the following:
# UPLOAD_PATH : path on that host to put the files in
# UPLOAD_TO_TEMP : upload files to a new temporary directory
#
# If UPLOAD_HOST and UPLOAD_USER are not set, this script will simply write out
# the properties file.
#
# And will use the following optional environment variables if set:
# UPLOAD_SSH_KEY : path to a ssh private key to use
@@ -23,18 +28,14 @@
# to the base path.
import sys, os
import re
import json
import errno
import hashlib
from optparse import OptionParser
from subprocess import check_call, check_output
from subprocess import check_call, check_output, STDOUT
import redo
def RequireEnvironmentVariable(v):
"""Return the value of the environment variable named v, or print
an error and exit if it's unset (or empty)."""
if not v in os.environ or os.environ[v] == "":
print "Error: required environment variable %s not set" % v
sys.exit(1)
return os.environ[v]
def OptionalEnvironmentVariable(v):
"""Return the value of the environment variable named v, or None
if it's unset (or empty)."""
@@ -61,7 +62,9 @@ def WindowsPathToMsysPath(path):
"""Translate a Windows pathname to an MSYS pathname.
Necessary because we call out to ssh/scp, which are MSYS binaries
and expect MSYS paths."""
if sys.platform != 'win32':
# If we're not on Windows, or if we already have an MSYS path (starting
# with '/' instead of 'c:' or something), then just return.
if sys.platform != 'win32' or path.startswith('/'):
return path
(drive, path) = os.path.splitdrive(os.path.abspath(path))
return "/" + drive[0] + path.replace('\\','/')
@@ -85,7 +88,7 @@ def DoSSHCommand(command, user, host, port=None, ssh_key=None):
cmdline.extend(["%s@%s" % (user, host), command])
with redo.retrying(check_output, sleeptime=10) as f:
output = f(cmdline).strip()
output = f(cmdline, stderr=STDOUT).strip()
return output
raise Exception("Command %s returned non-zero exit code" % cmdline)
@@ -115,7 +118,71 @@ def GetRemotePath(path, local_file, base_path):
dir = dir[len(base_path)+1:].replace('\\','/')
return path + dir
def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None, base_path=None, upload_to_temp_dir=False, post_upload_command=None):
def GetFileHashAndSize(filename):
sha512Hash = 'UNKNOWN'
size = 'UNKNOWN'
try:
# open in binary mode to make sure we get consistent results
# across all platforms
with open(filename, "rb") as f:
shaObj = hashlib.sha512(f.read())
sha512Hash = shaObj.hexdigest()
size = os.path.getsize(filename)
except:
raise Exception("Unable to get filesize/hash from file: %s" % filename)
return (sha512Hash, size)
def GetMarProperties(filename):
if not os.path.exists(filename):
return {}
(mar_hash, mar_size) = GetFileHashAndSize(filename)
return {
'completeMarFilename': os.path.basename(filename),
'completeMarSize': mar_size,
'completeMarHash': mar_hash,
}
def GetUrlProperties(output, package):
# let's create a switch case using name-spaces/dict
# rather than a long if/else with duplicate code
property_conditions = [
# key: property name, value: condition
('symbolsUrl', lambda m: m.endswith('crashreporter-symbols.zip') or
m.endswith('crashreporter-symbols-full.zip')),
('testsUrl', lambda m: m.endswith(('tests.tar.bz2', 'tests.zip'))),
('unsignedApkUrl', lambda m: m.endswith('apk') and
'unsigned-unaligned' in m),
('robocopApkUrl', lambda m: m.endswith('apk') and 'robocop' in m),
('jsshellUrl', lambda m: 'jsshell-' in m and m.endswith('.zip')),
('completeMarUrl', lambda m: m.endswith('.complete.mar')),
('partialMarUrl', lambda m: m.endswith('.mar') and '.partial.' in m),
('codeCoverageURL', lambda m: m.endswith('code-coverage-gcno.zip')),
('sdkUrl', lambda m: m.endswith(('sdk.tar.bz2', 'sdk.zip'))),
('testPackagesUrl', lambda m: m.endswith('test_packages.json')),
('packageUrl', lambda m: m.endswith(package)),
]
url_re = re.compile(r'''^(https?://.*?\.(?:tar\.bz2|dmg|zip|apk|rpm|mar|tar\.gz|json))$''')
properties = {}
try:
for line in output.splitlines():
m = url_re.match(line.strip())
if m:
m = m.group(1)
for prop, condition in property_conditions:
if condition(m):
properties.update({prop: m})
break
except IOError as e:
if e.errno != errno.ENOENT:
raise
properties = {prop: 'UNKNOWN' for prop, condition in property_conditions}
return properties
def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None, base_path=None, upload_to_temp_dir=False, post_upload_command=None, package=None):
"""Upload each file in the list files to user@host:path. Optionally pass
port and ssh_key to the ssh commands. If base_path is not None, upload
files including their path relative to base_path. If upload_to_temp_dir is
@@ -126,6 +193,13 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
after uploading all files, passing it the upload path, and the full paths to
all files uploaded.
If verbose is True, print status updates while working."""
if not host or not user:
return {}
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
"defined."
sys.exit(1)
if upload_to_temp_dir:
path = DoSSHCommand("mktemp -d", user, host, port=port, ssh_key=ssh_key)
if not path.endswith("/"):
@@ -133,6 +207,7 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
if base_path is not None:
base_path = os.path.abspath(base_path)
remote_files = []
properties = {}
try:
for file in files:
file = os.path.abspath(file)
@@ -149,17 +224,31 @@ def UploadFiles(user, host, path, files, verbose=False, port=None, ssh_key=None,
if verbose:
print "Running post-upload command: " + post_upload_command
file_list = '"' + '" "'.join(remote_files) + '"'
DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
output = DoSSHCommand('%s "%s" %s' % (post_upload_command, path, file_list), user, host, port=port, ssh_key=ssh_key)
# We print since mozharness may parse URLs from the output stream.
print output
properties = GetUrlProperties(output, package)
finally:
if upload_to_temp_dir:
DoSSHCommand("rm -rf %s" % path, user, host, port=port,
ssh_key=ssh_key)
if verbose:
print "Upload complete"
return properties
def WriteProperties(files, properties_file, url_properties, package):
properties = url_properties
for file in files:
if file.endswith('.complete.mar'):
properties.update(GetMarProperties(file))
with open(properties_file, 'w') as outfile:
properties['packageFilename'] = package
properties['uploadFiles'] = [os.path.abspath(f) for f in files]
json.dump(properties, outfile, indent=4)
if __name__ == '__main__':
host = RequireEnvironmentVariable('UPLOAD_HOST')
user = RequireEnvironmentVariable('UPLOAD_USER')
host = OptionalEnvironmentVariable('UPLOAD_HOST')
user = OptionalEnvironmentVariable('UPLOAD_USER')
path = OptionalEnvironmentVariable('UPLOAD_PATH')
upload_to_temp_dir = OptionalEnvironmentVariable('UPLOAD_TO_TEMP')
port = OptionalEnvironmentVariable('UPLOAD_PORT')
@@ -167,10 +256,7 @@ if __name__ == '__main__':
port = int(port)
key = OptionalEnvironmentVariable('UPLOAD_SSH_KEY')
post_upload_command = OptionalEnvironmentVariable('POST_UPLOAD_CMD')
if (not path and not upload_to_temp_dir) or (path and upload_to_temp_dir):
print "One (and only one of UPLOAD_PATH or UPLOAD_TO_TEMP must be " + \
"defined."
sys.exit(1)
if sys.platform == 'win32':
if path is not None:
path = FixupMsysPath(path)
@@ -179,17 +265,28 @@ if __name__ == '__main__':
parser = OptionParser(usage="usage: %prog [options] <files>")
parser.add_option("-b", "--base-path",
action="store", dest="base_path",
action="store",
help="Preserve file paths relative to this path when uploading. If unset, all files will be uploaded directly to UPLOAD_PATH.")
parser.add_option("--properties-file",
action="store",
help="Path to the properties file to store the upload properties.")
parser.add_option("--package",
action="store",
help="Name of the main package.")
(options, args) = parser.parse_args()
if len(args) < 1:
print "You must specify at least one file to upload"
sys.exit(1)
if not options.properties_file:
print "You must specify a --properties-file"
sys.exit(1)
try:
UploadFiles(user, host, path, args, base_path=options.base_path,
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
post_upload_command=post_upload_command,
verbose=True)
url_properties = UploadFiles(user, host, path, args, base_path=options.base_path,
port=port, ssh_key=key, upload_to_temp_dir=upload_to_temp_dir,
post_upload_command=post_upload_command,
package=options.package,
verbose=True)
WriteProperties(args, options.properties_file, url_properties, options.package)
except IOError, (strerror):
print strerror
sys.exit(1)
+17 -1
View File
@@ -494,17 +494,20 @@ IsOnFullDomainWhitelist(nsIURI* aURI)
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("m.video.baidu.com"),
NS_LITERAL_CSTRING("imgcache.gtimg.cn"), // for m.v.qq.com
NS_LITERAL_CSTRING("s.tabelog.jp"),
NS_LITERAL_CSTRING("s.yimg.jp"), // for s.tabelog.jp
NS_LITERAL_CSTRING("i.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("ai.yimg.jp"), // for *.yahoo.co.jp
NS_LITERAL_CSTRING("m.finance.yahoo.co.jp"),
NS_LITERAL_CSTRING("daily.c.yimg.jp"), // for sp.daily.co.jp
NS_LITERAL_CSTRING("stat100.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("user.ameba.jp"), // for ameblo.jp
NS_LITERAL_CSTRING("www.goo.ne.jp"),
NS_LITERAL_CSTRING("s.tabelog.jp"),
NS_LITERAL_CSTRING("x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("c.x.gnst.jp"), // for mobile.gnavi.co.jp
NS_LITERAL_CSTRING("www.smbc-card.com"),
NS_LITERAL_CSTRING("static.card.jp.rakuten-static.com"), // for rakuten-card.co.jp
NS_LITERAL_CSTRING("img.travel.rakuten.co.jp"), // for travel.rakuten.co.jp
NS_LITERAL_CSTRING("img.mixi.net"), // for mixi.jp
NS_LITERAL_CSTRING("girlschannel.net"),
NS_LITERAL_CSTRING("www.fancl.co.jp"),
@@ -520,6 +523,16 @@ IsOnFullDomainWhitelist(nsIURI* aURI)
NS_LITERAL_CSTRING("mw.nikkei.com"),
NS_LITERAL_CSTRING("www.nhk.or.jp"),
NS_LITERAL_CSTRING("www.tokyo-sports.co.jp"),
NS_LITERAL_CSTRING("www.bellemaison.jp"),
NS_LITERAL_CSTRING("www.kuronekoyamato.co.jp"),
NS_LITERAL_CSTRING("formassist.jp"), // for orico.jp
NS_LITERAL_CSTRING("sp.m.reuters.co.jp"),
NS_LITERAL_CSTRING("www.atre.co.jp"),
NS_LITERAL_CSTRING("www.jtb.co.jp"),
NS_LITERAL_CSTRING("www.sharp.co.jp"),
NS_LITERAL_CSTRING("www.biccamera.com"),
NS_LITERAL_CSTRING("weathernews.jp"),
NS_LITERAL_CSTRING("cache.ymail.jp"), // for www.yamada-denkiweb.com
};
static const size_t sNumFullDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sFullDomainsOnWhitelist);
@@ -545,8 +558,11 @@ IsOnBaseDomainWhitelist(nsIURI* aURI)
// 0th entry only active when testing:
NS_LITERAL_CSTRING("test2.example.org"),
NS_LITERAL_CSTRING("tbcdn.cn"), // for m.taobao.com
NS_LITERAL_CSTRING("alicdn.com"), // for m.taobao.com
NS_LITERAL_CSTRING("dpfile.com"), // for m.dianping.com
NS_LITERAL_CSTRING("hao123img.com"), // for hao123.com
NS_LITERAL_CSTRING("tabelog.k-img.com"), // for s.tabelog.com
NS_LITERAL_CSTRING("tsite.jp"), // for *.tsite.jp
};
static const size_t sNumBaseDomainsOnWhitelist =
MOZ_ARRAY_LENGTH(sBaseDomainsOnWhitelist);
+3 -1
View File
@@ -45,7 +45,9 @@ ifndef JS_STANDALONE
ifndef MOZ_PROFILE_USE
# Generate a new buildid every time we "export" in config... that's only
# supposed to be once per-build!
export::
export:: buildid
buildid: FORCE
ifdef MOZ_BUILD_DATE
printf '%s' $(MOZ_BUILD_DATE) > buildid
else
+49
View File
@@ -2540,6 +2540,55 @@ CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissio
return true;
}
bool
IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
uint32_t aNonExposedGlobals)
{
MOZ_ASSERT(aNonExposedGlobals, "Why did we get called?");
MOZ_ASSERT((aNonExposedGlobals &
~(GlobalNames::Window |
GlobalNames::BackstagePass |
GlobalNames::DedicatedWorkerGlobalScope |
GlobalNames::SharedWorkerGlobalScope |
GlobalNames::ServiceWorkerGlobalScope |
GlobalNames::WorkerDebuggerGlobalScope)) == 0,
"Unknown non-exposed global type");
const char* name = js::GetObjectClass(aGlobal)->name;
if ((aNonExposedGlobals & GlobalNames::Window) &&
!strcmp(name, "Window")) {
return true;
}
if ((aNonExposedGlobals & GlobalNames::BackstagePass) &&
!strcmp(name, "BackstagePass")) {
return true;
}
if ((aNonExposedGlobals & GlobalNames::DedicatedWorkerGlobalScope) &&
!strcmp(name, "DedicatedWorkerGlobalScope")) {
return true;
}
if ((aNonExposedGlobals & GlobalNames::SharedWorkerGlobalScope) &&
!strcmp(name, "SharedWorkerGlobalScope")) {
return true;
}
if ((aNonExposedGlobals & GlobalNames::ServiceWorkerGlobalScope) &&
!strcmp(name, "ServiceWorkerGlobalScope")) {
return true;
}
if ((aNonExposedGlobals & GlobalNames::WorkerDebuggerGlobalScope) &&
!strcmp(name, "WorkerDebuggerGlobalScopex")) {
return true;
}
return false;
}
void
HandlePrerenderingViolation(nsPIDOMWindow* aWindow)
{
-10
View File
@@ -3163,16 +3163,6 @@ AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitinfo,
JS::Handle<JS::Value> aValue);
#endif
// Returns true if aObj's global has any of the permissions named in aPermissions
// set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
bool
CheckAnyPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
// Returns true if aObj's global has all of the permissions named in aPermissions
// set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
bool
CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
// This function is called by the bindings layer for methods/getters/setters
// that are not safe to be called in prerendering mode. It checks to make sure
// that the |this| object is not running in a global that is in prerendering
+61 -36
View File
@@ -1906,16 +1906,26 @@ def getAvailableInTestFunc(obj):
class MemberCondition:
"""
An object representing the condition for a member to actually be
exposed. Any of pref, func, and available can be None. If not
None, they should be strings that have the pref name (for "pref")
or function name (for "func" and "available").
exposed. Any of the arguments can be None. If not
None, they should have the following types:
pref: The name of the preference.
func: The name of the function.
available: A string indicating where we should be available.
checkAnyPermissions: An integer index for the anypermissions_* to use.
checkAllPermissions: An integer index for the allpermissions_* to use.
nonExposedGlobals: A set of names of globals. Can be empty, in which case
it's treated the same way as None.
"""
def __init__(self, pref, func, available=None, checkAnyPermissions=None, checkAllPermissions=None):
def __init__(self, pref=None, func=None, available=None,
checkAnyPermissions=None, checkAllPermissions=None,
nonExposedGlobals=None):
assert pref is None or isinstance(pref, str)
assert func is None or isinstance(func, str)
assert available is None or isinstance(available, str)
assert checkAnyPermissions is None or isinstance(checkAnyPermissions, int)
assert checkAllPermissions is None or isinstance(checkAllPermissions, int)
assert nonExposedGlobals is None or isinstance(nonExposedGlobals, set)
self.pref = pref
def toFuncPtr(val):
@@ -1933,11 +1943,20 @@ class MemberCondition:
else:
self.checkAllPermissions = "allpermissions_%i" % checkAllPermissions
if nonExposedGlobals:
# Nonempty set
self.nonExposedGlobals = " | ".join(
map(lambda g: "GlobalNames::%s" % g,
sorted(nonExposedGlobals)))
else:
self.nonExposedGlobals = "0"
def __eq__(self, other):
return (self.pref == other.pref and self.func == other.func and
self.available == other.available and
self.checkAnyPermissions == other.checkAnyPermissions and
self.checkAllPermissions == other.checkAllPermissions)
self.checkAllPermissions == other.checkAllPermissions and
self.nonExposedGlobals == other.nonExposedGlobals)
def __ne__(self, other):
return not self.__eq__(other)
@@ -2000,13 +2019,34 @@ class PropertyDefiner:
@staticmethod
def getControllingCondition(interfaceMember, descriptor):
return MemberCondition(PropertyDefiner.getStringAttr(interfaceMember,
"Pref"),
PropertyDefiner.getStringAttr(interfaceMember,
"Func"),
getAvailableInTestFunc(interfaceMember),
descriptor.checkAnyPermissionsIndicesForMembers.get(interfaceMember.identifier.name),
descriptor.checkAllPermissionsIndicesForMembers.get(interfaceMember.identifier.name))
# We do a slightly complicated thing for exposure sets to deal nicely
# with the situation of an [Exposed=Window] thing on an interface
# exposed in workers that has a worker-specific descriptor. In that
# situation, we already skip generation of the member entirely in the
# worker binding, and shouldn't need to check for the various worker
# scopes in the non-worker binding.
interface = descriptor.interface
nonExposureSet = interface.exposureSet - interfaceMember.exposureSet
# Skip getting the descriptor if we're just exposed everywhere or not
# looking at the non-worker descriptor.
if len(nonExposureSet) and not descriptor.workers:
workerProvider = descriptor.config.getDescriptorProvider(True)
workerDesc = workerProvider.getDescriptor(interface.identifier.name)
if workerDesc.workers:
# Just drop all the worker interface names from the
# nonExposureSet, since we know we'll have a mainthread global
# of some sort.
nonExposureSet.difference_update(interface.getWorkerExposureSet())
return MemberCondition(
PropertyDefiner.getStringAttr(interfaceMember,
"Pref"),
PropertyDefiner.getStringAttr(interfaceMember,
"Func"),
getAvailableInTestFunc(interfaceMember),
descriptor.checkAnyPermissionsIndicesForMembers.get(interfaceMember.identifier.name),
descriptor.checkAllPermissionsIndicesForMembers.get(interfaceMember.identifier.name),
nonExposureSet)
def generatePrefableArray(self, array, name, specFormatter, specTerminator,
specType, getCondition, getDataTuple, doIdArrays):
@@ -2044,7 +2084,7 @@ class PropertyDefiner:
specs = []
prefableSpecs = []
prefableTemplate = ' { true, %s, %s, %s, %s, &%s[%d] }'
prefableTemplate = ' { true, %s, %s, %s, %s, %s, &%s[%d] }'
prefCacheTemplate = '&%s[%d].enabled'
def switchToCondition(props, condition):
@@ -2056,7 +2096,8 @@ class PropertyDefiner:
prefCacheTemplate % (name, len(prefableSpecs))))
# Set up pointers to the new sets of specs inside prefableSpecs
prefableSpecs.append(prefableTemplate %
(condition.func,
(condition.nonExposedGlobals,
condition.func,
condition.available,
condition.checkAnyPermissions,
condition.checkAllPermissions,
@@ -2075,7 +2116,7 @@ class PropertyDefiner:
# And the actual spec
specs.append(specFormatter(getDataTuple(member)))
specs.append(specTerminator)
prefableSpecs.append(" { false, nullptr }")
prefableSpecs.append(" { false, 0, nullptr, nullptr, nullptr, nullptr, nullptr }")
specType = "const " + specType
arrays = fill(
@@ -2198,7 +2239,7 @@ class MethodDefiner(PropertyDefiner):
"methodInfo": False,
"length": 1,
"flags": "0",
"condition": MemberCondition(None, condition)
"condition": MemberCondition(func=condition)
})
continue
@@ -2252,23 +2293,7 @@ class MethodDefiner(PropertyDefiner):
"selfHostedName": "ArrayValues",
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": MemberCondition(None, None)
})
# Output an @@iterator for generated iterator interfaces. This should
# not be necessary, but
# https://bugzilla.mozilla.org/show_bug.cgi?id=1091945 means that
# %IteratorPrototype%[@@iterator] is a broken puppy.
if (not static and
not unforgeable and
descriptor.interface.isIteratorInterface()):
self.regular.append({
"name": "@@iterator",
"methodInfo": False,
"selfHostedName": "IteratorIdentity",
"length": 0,
"flags": "0",
"condition": MemberCondition(None, None)
"condition": MemberCondition()
})
# Generate the maplike/setlike iterator, if one wasn't already
@@ -2341,7 +2366,7 @@ class MethodDefiner(PropertyDefiner):
"length": 0,
"flags": "JSPROP_ENUMERATE", # readonly/permanent added
# automatically.
"condition": MemberCondition(None, None)
"condition": MemberCondition()
})
if descriptor.interface.isJSImplemented():
@@ -2353,7 +2378,7 @@ class MethodDefiner(PropertyDefiner):
"methodInfo": False,
"length": 2,
"flags": "0",
"condition": MemberCondition(None, None)
"condition": MemberCondition()
})
else:
for m in clearableCachedAttrs(descriptor):
@@ -2364,7 +2389,7 @@ class MethodDefiner(PropertyDefiner):
"methodInfo": False,
"length": "0",
"flags": "0",
"condition": MemberCondition(None, None)
"condition": MemberCondition()
})
self.unforgeable = unforgeable
+40
View File
@@ -39,12 +39,24 @@ typedef bool
JS::Handle<JSObject*> obj,
JS::AutoIdVector& props);
// Returns true if aObj's global has any of the permissions named in
// aPermissions set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be
// null-terminated.
bool
CheckAnyPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
// Returns true if aObj's global has all of the permissions named in
// aPermissions set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be
// null-terminated.
bool
CheckAllPermissions(JSContext* aCx, JSObject* aObj, const char* const aPermissions[]);
// Returns true if the given global is of a type whose bit is set in
// aNonExposedGlobals.
bool
IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
uint32_t aNonExposedGlobals);
struct ConstantSpec
{
const char* name;
@@ -53,9 +65,35 @@ struct ConstantSpec
typedef bool (*PropertyEnabled)(JSContext* cx, JSObject* global);
namespace GlobalNames {
// The names of our possible globals. These are the names of the actual
// interfaces, not of the global names used to refer to them in IDL [Exposed]
// annotations.
static const uint32_t Window = 1u << 0;
static const uint32_t BackstagePass = 1u << 1;
static const uint32_t DedicatedWorkerGlobalScope = 1u << 2;
static const uint32_t SharedWorkerGlobalScope = 1u << 3;
static const uint32_t ServiceWorkerGlobalScope = 1u << 4;
static const uint32_t WorkerDebuggerGlobalScope = 1u << 5;
} // namespace GlobalNames
template<typename T>
struct Prefable {
inline bool isEnabled(JSContext* cx, JS::Handle<JSObject*> obj) const {
// Reading "enabled" on a worker thread is technically undefined behavior,
// because it's written only on main threads, with no barriers of any sort.
// So we want to avoid doing that. But we don't particularly want to make
// expensive NS_IsMainThread calls here.
//
// The good news is that "enabled" is only written for things that have a
// Pref annotation, and such things can never be exposed on non-Window
// globals; our IDL parser enforces that. So as long as we check our
// exposure set before checking "enabled" we will be ok.
if (nonExposedGlobals &&
IsNonExposedGlobal(cx, js::GetGlobalForObjectCrossCompartment(obj),
nonExposedGlobals)) {
return false;
}
if (!enabled) {
return false;
}
@@ -85,6 +123,8 @@ struct Prefable {
// A boolean indicating whether this set of specs is enabled
bool enabled;
// Bitmask of global names that we should not be exposed in.
uint32_t nonExposedGlobals;
// A function pointer to a function that can say the property is disabled
// even if "enabled" is set to true. If the pointer is null the value of
// "enabled" is used as-is unless availableFunc overrides.
+9 -11
View File
@@ -136,11 +136,6 @@ public:
nsCOMPtr<nsILoadGroup> loadGroup = proxy->GetWorkerPrivate()->GetLoadGroup();
MOZ_ASSERT(loadGroup);
RefPtr<FetchDriver> fetch = new FetchDriver(mRequest, principal, loadGroup);
nsIDocument* doc = proxy->GetWorkerPrivate()->GetDocument();
if (doc) {
fetch->SetDocument(doc);
}
nsresult rv = fetch->Fetch(mResolver);
// Right now we only support async fetch, which should never directly fail.
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -662,17 +657,15 @@ public:
uint8_t* nonconstResult = const_cast<uint8_t*>(aResult);
if (mFetchBody->mWorkerPrivate) {
// This way if the runnable dispatch fails, the body is still released.
AutoFailConsumeBody<Derived> autoFail(mFetchBody);
RefPtr<ContinueConsumeBodyRunnable<Derived>> r =
new ContinueConsumeBodyRunnable<Derived>(mFetchBody,
aStatus,
aResultLength,
nonconstResult);
AutoSafeJSContext cx;
if (r->Dispatch(cx)) {
autoFail.DontFail();
} else {
if (!r->Dispatch(cx)) {
// XXXcatalinb: The worker is shutting down, the pump will be canceled
// by FetchBodyFeature::Notify.
NS_WARNING("Could not dispatch ConsumeBodyRunnable");
// Return failure so that aResult is freed.
return NS_ERROR_FAILURE;
@@ -742,10 +735,12 @@ class FetchBodyFeature final : public workers::WorkerFeature
// This is addrefed before the feature is created, and is released in ContinueConsumeBody()
// so we can hold a rawptr.
FetchBody<Derived>* mBody;
bool mWasNotified;
public:
explicit FetchBodyFeature(FetchBody<Derived>* aBody)
: mBody(aBody)
, mWasNotified(false)
{ }
~FetchBodyFeature()
@@ -754,7 +749,10 @@ public:
bool Notify(JSContext* aCx, workers::Status aStatus) override
{
MOZ_ASSERT(aStatus > workers::Running);
mBody->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr);
if (!mWasNotified) {
mWasNotified = true;
mBody->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr);
}
return true;
}
};
+2 -4
View File
@@ -245,10 +245,8 @@ FetchDriver::HttpFetch()
MOZ_ASSERT(mLoadGroup);
nsCOMPtr<nsIChannel> chan;
// For dedicated workers mDocument refers to the parent document of the
// worker (why do we do that?). In that case we don't want to use the
// document here since that is not the correct principal.
if (mDocument && mDocument->NodePrincipal() == mPrincipal) {
if (mDocument) {
MOZ_ASSERT(mDocument->NodePrincipal() == mPrincipal);
rv = NS_NewChannel(getter_AddRefs(chan),
uri,
mDocument,
+13
View File
@@ -102,6 +102,19 @@ public:
mInternalHeaders->Set(aName, aValue, aRv);
}
uint32_t GetIterableLength() const
{
return mInternalHeaders->GetIterableLength();
}
const nsString GetKeyAtIndex(unsigned aIndex) const
{
return mInternalHeaders->GetKeyAtIndex(aIndex);
}
const nsString GetValueAtIndex(unsigned aIndex) const
{
return mInternalHeaders->GetValueAtIndex(aIndex);
}
// ChromeOnly
HeadersGuardEnum Guard() const
{
+2 -7
View File
@@ -151,13 +151,8 @@ InternalHeaders::Clear()
void
InternalHeaders::SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
{
// Rather than re-validate all current headers, just require code to set
// this prior to populating the InternalHeaders object. Allow setting immutable
// late, though, as that is pretty much required to have a useful, immutable
// headers object.
if (aGuard != HeadersGuardEnum::Immutable && mList.Length() > 0) {
aRv.Throw(NS_ERROR_FAILURE);
}
// The guard is only checked during ::Set() and ::Append() in the spec. It
// does not require revalidating headers already set.
mGuard = aGuard;
}
+15
View File
@@ -73,6 +73,21 @@ public:
bool Has(const nsACString& aName, ErrorResult& aRv) const;
void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
uint32_t GetIterableLength() const
{
return mList.Length();
}
const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) const
{
MOZ_ASSERT(aIndex < mList.Length());
return NS_ConvertASCIItoUTF16(mList[aIndex].mName);
}
const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) const
{
MOZ_ASSERT(aIndex < mList.Length());
return NS_ConvertASCIItoUTF16(mList[aIndex].mValue);
}
void Clear();
HeadersGuardEnum Guard() const { return mGuard; }
+19
View File
@@ -64,6 +64,25 @@ Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
return workerPrivate->RequestContextEnabled();
}
// static
bool
Request::RequestCacheEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.requestcache.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->RequestCacheEnabled();
}
already_AddRefed<InternalRequest>
Request::GetInternalRequest()
{
+2
View File
@@ -36,6 +36,8 @@ public:
static bool
RequestContextEnabled(JSContext* aCx, JSObject* aObj);
static bool
RequestCacheEnabled(JSContext* aCx, JSObject* aObj);
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
+1 -1
View File
@@ -19,7 +19,7 @@
namespace mozilla {
namespace ipc {
class PrincipalInfo;
}
} // namespace ipc
namespace dom {
+1
View File
@@ -319,6 +319,7 @@ IDBFactory::CreateForJSInternal(JSContext* aCx,
if (aPrincipalInfo->type() != PrincipalInfo::TContentPrincipalInfo &&
aPrincipalInfo->type() != PrincipalInfo::TSystemPrincipalInfo) {
NS_WARNING("IndexedDB not allowed for this principal!");
aPrincipalInfo = nullptr;
*aFactory = nullptr;
return NS_OK;
}
@@ -7,7 +7,8 @@ function testScript(script) {
function setupPrefs() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({
"set": [["dom.requestcontext.enabled", true],
"set": [["dom.requestcache.enabled", true],
["dom.requestcontext.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]
+1
View File
@@ -36,6 +36,7 @@ skip-if = e10s || buildapp == 'b2g' # Bug 1173163 for e10s, bug 1137683 for b2g
[test_formdataparsing_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683
[test_request.html]
[test_request_cache.html]
[test_request_context.html]
[test_request_sw_reroute.html]
skip-if = buildapp == 'b2g' # Bug 1137683
+2 -1
View File
@@ -10,7 +10,8 @@ function testScript(script) {
}
SpecialPowers.pushPrefEnv({
"set": [["dom.serviceWorkers.enabled", true],
"set": [["dom.requestcache.enabled", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.interception.opaque.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]
@@ -13,16 +13,27 @@ function shouldThrow(func, expected, msg) {
}
}
function recursiveArrayCompare(actual, expected) {
is(Array.isArray(actual), Array.isArray(expected), "Both should either be arrays, or not");
if (Array.isArray(actual) && Array.isArray(expected)) {
var diff = actual.length !== expected.length;
for (var i = 0, n = actual.length; !diff && i < n; ++i) {
diff = recursiveArrayCompare(actual[i], expected[i]);
}
return diff;
} else {
return actual !== expected;
}
}
function arrayEquals(actual, expected, msg) {
if (actual === expected) {
return;
}
var diff = actual.length !== expected.length;
for (var i = 0, n = actual.length; !diff && i < n; ++i) {
diff = actual[i] !== expected[i];
}
var diff = recursiveArrayCompare(actual, expected);
ok(!diff, msg);
if (diff) {
@@ -169,8 +180,60 @@ function TestFilledHeaders() {
}, TypeError, "Fill with non-tuple sequence should throw TypeError.");
}
function iterate(iter) {
var result = [];
for (var val = iter.next(); !val.done;) {
result.push(val.value);
val = iter.next();
}
return result;
}
function iterateForOf(iter) {
var result = [];
for (var value of iter) {
result.push(value);
}
return result;
}
function byteInflate(str) {
var encoder = new TextEncoder("utf-8");
var encoded = encoder.encode(str);
var result = "";
for (var i = 0; i < encoded.length; ++i) {
result += String.fromCharCode(encoded[i]);
}
return result
}
function TestHeadersIterator() {
var ehsanInflated = byteInflate("احسان");
var headers = new Headers();
headers.set("foo0", "bar0");
headers.append("foo", "bar");
headers.append("foo", ehsanInflated);
headers.append("Foo2", "bar2");
headers.set("Foo2", "baz2");
headers.set("foo3", "bar3");
headers.delete("foo0");
headers.delete("foo3");
var key_iter = headers.keys();
var value_iter = headers.values();
var entries_iter = headers.entries();
arrayEquals(iterate(key_iter), ["foo", "foo", "foo2"], "Correct key iterator");
arrayEquals(iterate(value_iter), ["bar", ehsanInflated, "baz2"], "Correct value iterator");
arrayEquals(iterate(entries_iter), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(headers), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
arrayEquals(iterateForOf(new Headers(headers)), [["foo", "bar"], ["foo", ehsanInflated], ["foo2", "baz2"]], "Correct entries iterator");
}
function runTest() {
TestEmptyHeaders();
TestFilledHeaders();
TestHeadersIterator();
return Promise.resolve();
}
@@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Make sure that Request.cache is not exposed by default</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script>
var req = new Request("");
ok(!("cache" in req), "Request.cache should not be exposed by default");
</script>
</body>
</html>
+1 -1
View File
@@ -49,6 +49,6 @@ partial interface EventTarget {
// chrome easier. This returns the window which can be used to create
// events to fire at this EventTarget, or null if there isn't one.
partial interface EventTarget {
[ChromeOnly, Exposed=Window, BinaryName="ownerGlobalForBindings"]
[ChromeOnly, Exposed=(Window,System), BinaryName="ownerGlobalForBindings"]
readonly attribute WindowProxy? ownerGlobal;
};
+1
View File
@@ -27,6 +27,7 @@ interface Headers {
[Throws] sequence<ByteString> getAll(ByteString name);
[Throws] boolean has(ByteString name);
[Throws] void set(ByteString name, ByteString value);
iterable<ByteString, ByteString>;
// Used to test different guard states from mochitest.
// Note: Must be set prior to populating headers or will throw.
+1
View File
@@ -22,6 +22,7 @@ interface Request {
readonly attribute DOMString referrer;
readonly attribute RequestMode mode;
readonly attribute RequestCredentials credentials;
[Func="mozilla::dom::Request::RequestCacheEnabled"]
readonly attribute RequestCache cache;
readonly attribute RequestRedirect redirect;
+101 -226
View File
@@ -122,10 +122,6 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define CC_REQUEST_OBSERVER_TOPIC "child-cc-request"
#define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
#define PREF_GENERAL_APPNAME_OVERRIDE "general.appname.override"
#define PREF_GENERAL_APPVERSION_OVERRIDE "general.appversion.override"
#define PREF_GENERAL_PLATFORM_OVERRIDE "general.platform.override"
#define BROADCAST_ALL_WORKERS(_func, ...) \
PR_BEGIN_MACRO \
AssertIsOnMainThread(); \
@@ -152,27 +148,6 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_MEM_OPTIONS_PREFIX "mem."
#define PREF_GCZEAL "gcZeal"
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
#define DUMP_CONTROLLED_BY_PREF 1
#define PREF_DOM_WINDOW_DUMP_ENABLED "browser.dom.window.dump.enabled"
#endif
#define PREF_DOM_CACHES_ENABLED "dom.caches.enabled"
#define PREF_DOM_CACHES_TESTING_ENABLED "dom.caches.testing.enabled"
#define PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED "dom.performance.enable_user_timing_logging"
#define PREF_DOM_WORKERNOTIFICATION_ENABLED "dom.webnotifications.enabled"
#define PREF_DOM_SERVICEWORKERNOTIFICATION_ENABLED "dom.webnotifications.serviceworker.enabled"
#define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
#define PREF_INTL_ACCEPT_LANGUAGES "intl.accept_languages"
#define PREF_SERVICEWORKERS_ENABLED "dom.serviceWorkers.enabled"
#define PREF_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
#define PREF_INTERCEPTION_ENABLED "dom.serviceWorkers.interception.enabled"
#define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
#define PREF_OPEN_WINDOW_ENABLED "dom.serviceWorkers.openWindow.enabled"
#define PREF_PUSH_ENABLED "dom.push.enabled"
#define PREF_REQUESTCONTEXT_ENABLED "dom.requestcontext.enabled"
#define PREF_OFFSCREENCANVAS_ENABLED "gfx.offscreencanvas.enabled"
namespace {
const uint32_t kNoIndex = uint32_t(-1);
@@ -763,9 +738,48 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
aSize, aMemory, aHandle);
}
struct WorkerThreadRuntimePrivate : public PerThreadAtomCache
class WorkerJSRuntime;
class WorkerThreadRuntimePrivate : private PerThreadAtomCache
{
friend class WorkerJSRuntime;
WorkerPrivate* mWorkerPrivate;
public:
// This can't return null, but we can't lose the "Get" prefix in the name or
// it will be ambiguous with the WorkerPrivate class name.
WorkerPrivate*
GetWorkerPrivate() const
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mWorkerPrivate);
return mWorkerPrivate;
}
private:
explicit
WorkerThreadRuntimePrivate(WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
{
MOZ_ASSERT(!NS_IsMainThread());
// Zero out the base class members.
memset(this, 0, sizeof(PerThreadAtomCache));
MOZ_ASSERT(mWorkerPrivate);
}
~WorkerThreadRuntimePrivate()
{
MOZ_ASSERT(!NS_IsMainThread());
}
WorkerThreadRuntimePrivate(const WorkerThreadRuntimePrivate&) = delete;
WorkerThreadRuntimePrivate&
operator=(const WorkerThreadRuntimePrivate&) = delete;
};
JSContext*
@@ -814,11 +828,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
return nullptr;
}
auto rtPrivate = new WorkerThreadRuntimePrivate();
memset(rtPrivate, 0, sizeof(WorkerThreadRuntimePrivate));
rtPrivate->mWorkerPrivate = aWorkerPrivate;
JS_SetRuntimePrivate(aRuntime, rtPrivate);
JS_SetErrorReporter(aRuntime, ErrorReporter);
JS_SetInterruptCallback(aRuntime, InterruptCallback);
@@ -883,16 +892,23 @@ public:
WORKER_DEFAULT_NURSERY_SIZE),
mWorkerPrivate(aWorkerPrivate)
{
js::SetPreserveWrapperCallback(Runtime(), PreserveWrapper);
JS_InitDestroyPrincipalsCallback(Runtime(), DestroyWorkerPrincipals);
JS_SetWrapObjectCallbacks(Runtime(), &WrapObjectCallbacks);
JSRuntime* rt = Runtime();
MOZ_ASSERT(rt);
JS_SetRuntimePrivate(rt, new WorkerThreadRuntimePrivate(aWorkerPrivate));
js::SetPreserveWrapperCallback(rt, PreserveWrapper);
JS_InitDestroyPrincipalsCallback(rt, DestroyWorkerPrincipals);
JS_SetWrapObjectCallbacks(rt, &WrapObjectCallbacks);
}
~WorkerJSRuntime()
{
auto rtPrivate = static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(Runtime()));
delete rtPrivate;
JS_SetRuntimePrivate(Runtime(), nullptr);
JSRuntime* rt = Runtime();
MOZ_ASSERT(rt);
delete static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(rt));
JS_SetRuntimePrivate(rt, nullptr);
// The worker global should be unrooted and the shutdown cycle collection
// should break all remaining cycles. The superclass destructor will run
@@ -1141,7 +1157,7 @@ AppNameOverrideChanged(const char* /* aPrefName */, void* /* aClosure */)
AssertIsOnMainThread();
const nsAdoptingString& override =
mozilla::Preferences::GetString(PREF_GENERAL_APPNAME_OVERRIDE);
mozilla::Preferences::GetString("general.appname.override");
RuntimeService* runtime = RuntimeService::GetService();
if (runtime) {
@@ -1155,7 +1171,7 @@ AppVersionOverrideChanged(const char* /* aPrefName */, void* /* aClosure */)
AssertIsOnMainThread();
const nsAdoptingString& override =
mozilla::Preferences::GetString(PREF_GENERAL_APPVERSION_OVERRIDE);
mozilla::Preferences::GetString("general.appversion.override");
RuntimeService* runtime = RuntimeService::GetService();
if (runtime) {
@@ -1169,7 +1185,7 @@ PlatformOverrideChanged(const char* /* aPrefName */, void* /* aClosure */)
AssertIsOnMainThread();
const nsAdoptingString& override =
mozilla::Preferences::GetString(PREF_GENERAL_PLATFORM_OVERRIDE);
mozilla::Preferences::GetString("general.platform.override");
RuntimeService* runtime = RuntimeService::GetService();
if (runtime) {
@@ -1303,7 +1319,8 @@ GetWorkerPrivateFromContext(JSContext* aCx)
void* rtPrivate = JS_GetRuntimePrivate(rt);
MOZ_ASSERT(rtPrivate);
return static_cast<WorkerThreadRuntimePrivate*>(rtPrivate)->mWorkerPrivate;
return
static_cast<WorkerThreadRuntimePrivate*>(rtPrivate)->GetWorkerPrivate();
}
WorkerPrivate*
@@ -1322,7 +1339,8 @@ GetCurrentThreadWorkerPrivate()
void* rtPrivate = JS_GetRuntimePrivate(rt);
MOZ_ASSERT(rtPrivate);
return static_cast<WorkerThreadRuntimePrivate*>(rtPrivate)->mWorkerPrivate;
return
static_cast<WorkerThreadRuntimePrivate*>(rtPrivate)->GetWorkerPrivate();
}
bool
@@ -1645,7 +1663,7 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
}
}
if (!domainInfo->ActiveWorkerCount()) {
if (domainInfo->HasNoWorkers()) {
MOZ_ASSERT(domainInfo->mQueuedWorkers.IsEmpty());
mDomainMap.Remove(domain);
}
@@ -1841,11 +1859,6 @@ RuntimeService::Init()
WORKER_DEFAULT_ALLOCATION_THRESHOLD);
}
// If dump is not controlled by pref, it's set to true.
#ifndef DUMP_CONTROLLED_BY_PREF
sDefaultPreferences[WORKERPREF_DUMP] = true;
#endif
mIdleThreadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_STATE(mIdleThreadTimer);
@@ -1894,95 +1907,29 @@ RuntimeService::Init()
LoadGCZealOptions,
PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadGCZealOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
#endif
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_CACHES_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_WORKERNOTIFICATION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_WORKERNOTIFICATION))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_SERVICEWORKERNOTIFICATION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_SERVICEWORKERNOTIFICATION))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_SERVICEWORKERS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_INTERCEPTION_OPAQUE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_OPAQUE_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_DOM_CACHES_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES_TESTING))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PERFORMANCE_LOGGING_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_SERVICEWORKERS_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS_TESTING))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_OFFSCREENCANVAS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
#define WORKER_SIMPLE_PREF(name, getter, NAME) \
NS_FAILED(Preferences::RegisterCallbackAndCall( \
WorkerPrefChanged, \
name, \
reinterpret_cast<void*>(WORKERPREF_##NAME))) ||
#define WORKER_PREF(name, callback) \
NS_FAILED(Preferences::RegisterCallbackAndCall( \
callback, \
name, \
nullptr)) ||
#include "WorkerPrefs.h"
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
NS_FAILED(Preferences::RegisterCallbackAndCall(
LoadRuntimeOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(PrefLanguagesChanged,
PREF_INTL_ACCEPT_LANGUAGES,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
AppNameOverrideChanged,
PREF_GENERAL_APPNAME_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
AppVersionOverrideChanged,
PREF_GENERAL_APPVERSION_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
PlatformOverrideChanged,
PREF_GENERAL_PLATFORM_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr))) {
NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr))) {
NS_WARNING("Failed to register pref callbacks!");
}
@@ -2132,93 +2079,32 @@ RuntimeService::Cleanup()
NS_ASSERTION(!mWindowMap.Count(), "All windows should have been released!");
if (mObserved) {
if (NS_FAILED(Preferences::UnregisterCallback(JSVersionChanged,
PREF_WORKERS_LATEST_JS_VERSION,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(AppNameOverrideChanged,
PREF_GENERAL_APPNAME_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
AppVersionOverrideChanged,
PREF_GENERAL_APPVERSION_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
PlatformOverrideChanged,
PREF_GENERAL_PLATFORM_OVERRIDE,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
if (NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
PREF_JS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
PREF_WORKERS_OPTIONS_PREFIX,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_SERVICEWORKERS_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS_TESTING))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_CACHES_TESTING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES_TESTING))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_WORKERS_PERFORMANCE_LOGGING_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PERFORMANCE_LOGGING_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_INTERCEPTION_OPAQUE_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_OPAQUE_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_SERVICEWORKERS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_SERVICEWORKERS))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_CACHES_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_CACHES))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_WORKERNOTIFICATION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_WORKERNOTIFICATION))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_SERVICEWORKERNOTIFICATION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DOM_SERVICEWORKERNOTIFICATION))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_PUSH_ENABLED,
reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_REQUESTCONTEXT_ENABLED,
reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_OFFSCREENCANVAS_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
#if DUMP_CONTROLLED_BY_PREF
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_DOM_WINDOW_DUMP_ENABLED,
reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
#endif
#define WORKER_SIMPLE_PREF(name, getter, NAME) \
NS_FAILED(Preferences::UnregisterCallback( \
WorkerPrefChanged, \
name, \
reinterpret_cast<void*>(WORKERPREF_##NAME))) ||
#define WORKER_PREF(name, callback) \
NS_FAILED(Preferences::UnregisterCallback( \
callback, \
name, \
nullptr)) ||
#include "WorkerPrefs.h"
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
#ifdef JS_GC_ZEAL
NS_FAILED(Preferences::UnregisterCallback(
LoadGCZealOptions,
PREF_JS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
NS_FAILED(Preferences::UnregisterCallback(
LoadGCZealOptions,
PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL,
nullptr)) ||
#endif
NS_FAILED(Preferences::UnregisterCallback(
LoadJSGCMemoryOptions,
@@ -2710,22 +2596,11 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
static_cast<WorkerPreference>(reinterpret_cast<uintptr_t>(aClosure));
switch (key) {
case WORKERPREF_DOM_CACHES:
case WORKERPREF_DOM_CACHES_TESTING:
case WORKERPREF_DOM_WORKERNOTIFICATION:
case WORKERPREF_DOM_SERVICEWORKERNOTIFICATION:
case WORKERPREF_PERFORMANCE_LOGGING_ENABLED:
#ifdef DUMP_CONTROLLED_BY_PREF
case WORKERPREF_DUMP:
#endif
case WORKERPREF_INTERCEPTION_ENABLED:
case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
case WORKERPREF_OPEN_WINDOW_ENABLED:
case WORKERPREF_SERVICEWORKERS:
case WORKERPREF_SERVICEWORKERS_TESTING:
case WORKERPREF_PUSH:
case WORKERPREF_REQUESTCONTEXT:
case WORKERPREF_OFFSCREENCANVAS:
#define WORKER_SIMPLE_PREF(name, getter, NAME) case WORKERPREF_##NAME:
#define WORKER_PREF(name, callback)
#include "WorkerPrefs.h"
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);
break;
@@ -2745,7 +2620,7 @@ RuntimeService::JSVersionChanged(const char* /* aPrefName */, void* /* aClosure
{
AssertIsOnMainThread();
bool useLatest = Preferences::GetBool(PREF_WORKERS_LATEST_JS_VERSION, false);
bool useLatest = Preferences::GetBool("dom.workers.latestJSVersion", false);
JS::CompartmentOptions& options = sDefaultJSSettings.content.compartmentOptions;
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
}
+13 -1
View File
@@ -56,9 +56,21 @@ class RuntimeService final : public nsIObserver
ActiveWorkerCount() const
{
return mActiveWorkers.Length() +
mActiveServiceWorkers.Length() +
mChildWorkerCount;
}
uint32_t
ActiveServiceWorkerCount() const
{
return mActiveServiceWorkers.Length();
}
bool
HasNoWorkers() const
{
return ActiveWorkerCount() == 0 &&
ActiveServiceWorkerCount() == 0;
}
};
struct IdleThreadInfo;
+48
View File
@@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 is the list of the preferences that are exposed to workers.
// The format is as follows:
//
// WORKER_SIMPLE_PREF("foo.bar", FooBar, FOO_BAR, UpdaterFunction)
//
// * First argument is the name of the pref.
// * The name of the getter function. This defines a FindName()
// function that returns the value of the pref on WorkerPrivate.
// * The macro version of the name. This defines a WORKERPREF_FOO_BAR
// macro in Workers.h.
// * The name of the function that updates the new value of a pref.
//
// WORKER_PREF("foo.bar", UpdaterFunction)
//
// * First argument is the name of the pref.
// * The name of the function that updates the new value of a pref.
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
WORKER_SIMPLE_PREF("browser.dom.window.dump.enabled", DumpEnabled, DUMP)
#endif
WORKER_SIMPLE_PREF("dom.caches.enabled", DOMCachesEnabled, DOM_CACHES)
WORKER_SIMPLE_PREF("dom.caches.testing.enabled", DOMCachesTestingEnabled, DOM_CACHES_TESTING)
WORKER_SIMPLE_PREF("dom.performance.enable_user_timing_logging", PerformanceLoggingEnabled, PERFORMANCE_LOGGING_ENABLED)
WORKER_SIMPLE_PREF("dom.webnotifications.enabled", DOMWorkerNotificationEnabled, DOM_WORKERNOTIFICATION)
WORKER_SIMPLE_PREF("dom.webnotifications.serviceworker.enabled", DOMServiceWorkerNotificationEnabled, DOM_SERVICEWORKERNOTIFICATION)
WORKER_SIMPLE_PREF("dom.serviceWorkers.enabled", ServiceWorkersEnabled, SERVICEWORKERS_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.testing.enabled", ServiceWorkersTestingEnabled, SERVICEWORKERS_TESTING_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.interception.enabled", InterceptionEnabled, INTERCEPTION_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.interception.opaque.enabled", OpaqueInterceptionEnabled, INTERCEPTION_OPAQUE_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, OPEN_WINDOW_ENABLED)
WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcache.enabled", RequestCacheEnabled, REQUESTCACHE_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged)
WORKER_PREF("general.platform.override", PlatformOverrideChanged)
#ifdef JS_GC_ZEAL
WORKER_PREF("dom.workers.options.gcZeal", LoadGCZealOptions)
#endif
+10 -97
View File
@@ -1230,104 +1230,17 @@ public:
bool
RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
bool
DumpEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DUMP];
}
bool
DOMCachesEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DOM_CACHES];
}
bool
ServiceWorkersEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_SERVICEWORKERS];
}
// Determine if the SW testing browser-wide pref is set
bool
ServiceWorkersTestingEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_SERVICEWORKERS_TESTING];
}
bool
InterceptionEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_INTERCEPTION_ENABLED];
}
bool
OpenWindowEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_OPEN_WINDOW_ENABLED];
}
bool
OpaqueInterceptionEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_INTERCEPTION_OPAQUE_ENABLED];
}
bool
DOMWorkerNotificationEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DOM_WORKERNOTIFICATION];
}
bool
DOMServiceWorkerNotificationEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DOM_SERVICEWORKERNOTIFICATION];
}
bool
DOMCachesTestingEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_DOM_CACHES_TESTING];
}
bool
PerformanceLoggingEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_PERFORMANCE_LOGGING_ENABLED];
}
bool
PushEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_PUSH];
}
bool
RequestContextEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_REQUESTCONTEXT];
}
bool
OffscreenCanvasEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_OFFSCREENCANVAS];
#define WORKER_SIMPLE_PREF(name, getter, NAME) \
bool \
getter() const \
{ \
AssertIsOnWorkerThread(); \
return mPreferences[WORKERPREF_##NAME]; \
}
#define WORKER_PREF(name, callback)
#include "WorkerPrefs.h"
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
bool
OnLine() const
+2
View File
@@ -318,9 +318,11 @@ WorkerGlobalScope::Dump(const Optional<nsAString>& aString) const
return;
}
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
if (!mWorkerPrivate->DumpEnabled()) {
return;
}
#endif
NS_ConvertUTF16toUTF8 str(aString.Value());
+5 -14
View File
@@ -197,20 +197,11 @@ struct JSSettings
enum WorkerPreference
{
WORKERPREF_DUMP = 0, // browser.dom.window.dump.enabled
WORKERPREF_DOM_CACHES, // dom.caches.enabled
WORKERPREF_SERVICEWORKERS, // dom.serviceWorkers.enabled
WORKERPREF_INTERCEPTION_ENABLED, // dom.serviceWorkers.interception.enabled
WORKERPREF_OPEN_WINDOW_ENABLED, // dom.serviceWorkers.openWindow.enabled
WORKERPREF_DOM_WORKERNOTIFICATION, // dom.webnotifications.workers.enabled
WORKERPREF_DOM_SERVICEWORKERNOTIFICATION, // dom.webnotifications.serviceworker.enabled
WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled
WORKERPREF_SERVICEWORKERS_TESTING, // dom.serviceWorkers.testing.enabled
WORKERPREF_INTERCEPTION_OPAQUE_ENABLED, // dom.serviceWorkers.interception.opaque.enabled
WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
WORKERPREF_PUSH, // dom.push.enabled
WORKERPREF_REQUESTCONTEXT, // dom.requestcontext.enabled
WORKERPREF_OFFSCREENCANVAS, // gfx.offscreencanvas.enabled
#define WORKER_SIMPLE_PREF(name, getter, NAME) WORKERPREF_ ## NAME,
#define WORKER_PREF(name, callback)
#include "mozilla/dom/WorkerPrefs.h"
#undef WORKER_SIMPLE_PREF
#undef WORKER_PREF
WORKERPREF_COUNT
};
+1
View File
@@ -12,6 +12,7 @@ EXPORTS.mozilla.dom += [
'ServiceWorkerMessageEvent.h',
'ServiceWorkerRegistrar.h',
'ServiceWorkerRegistration.h',
'WorkerPrefs.h',
'WorkerPrivate.h',
'WorkerRunnable.h',
'WorkerScope.h',
+1 -1
View File
@@ -719,7 +719,7 @@ struct JSClass {
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 33)
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 36)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
+42 -44
View File
@@ -72,7 +72,6 @@ ModuleValueGetter(JSContext* cx, unsigned argc, Value* vp)
ImportEntryObject::class_ = {
"ImportEntry",
JSCLASS_HAS_RESERVED_SLOTS(ImportEntryObject::SlotCount) |
JSCLASS_HAS_CACHED_PROTO(JSProto_ImportEntry) |
JSCLASS_IS_ANONYMOUS
};
@@ -90,8 +89,8 @@ ImportEntryObject::isInstance(HandleValue value)
return value.isObject() && value.toObject().is<ImportEntryObject>();
}
/* static */ JSObject*
ImportEntryObject::initClass(JSContext* cx, HandleObject obj)
/* static */ bool
GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
{
static const JSPropertySpec protoAccessors[] = {
JS_PSG("moduleRequest", ImportEntryObject_moduleRequestGetter, 0),
@@ -100,22 +99,15 @@ ImportEntryObject::initClass(JSContext* cx, HandleObject obj)
JS_PS_END
};
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
if (!proto)
return nullptr;
return false;
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
return nullptr;
return false;
global->setPrototype(JSProto_ImportEntry, ObjectValue(*proto));
return proto;
}
JSObject*
js::InitImportEntryClass(JSContext* cx, HandleObject obj)
{
return ImportEntryObject::initClass(cx, obj);
global->setReservedSlot(IMPORT_ENTRY_PROTO, ObjectValue(*proto));
return true;
}
/* static */ ImportEntryObject*
@@ -124,9 +116,12 @@ ImportEntryObject::create(JSContext* cx,
HandleAtom importName,
HandleAtom localName)
{
RootedImportEntry self(cx, NewBuiltinClassInstance<ImportEntryObject>(cx));
if (!self)
RootedObject proto(cx, cx->global()->getImportEntryPrototype());
RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
if (!obj)
return nullptr;
RootedImportEntry self(cx, &obj->as<ImportEntryObject>());
self->initReservedSlot(ModuleRequestSlot, StringValue(moduleRequest));
self->initReservedSlot(ImportNameSlot, StringValue(importName));
self->initReservedSlot(LocalNameSlot, StringValue(localName));
@@ -140,7 +135,6 @@ ImportEntryObject::create(JSContext* cx,
ExportEntryObject::class_ = {
"ExportEntry",
JSCLASS_HAS_RESERVED_SLOTS(ExportEntryObject::SlotCount) |
JSCLASS_HAS_CACHED_PROTO(JSProto_ExportEntry) |
JSCLASS_IS_ANONYMOUS
};
@@ -160,8 +154,8 @@ ExportEntryObject::isInstance(HandleValue value)
return value.isObject() && value.toObject().is<ExportEntryObject>();
}
/* static */ JSObject*
ExportEntryObject::initClass(JSContext* cx, HandleObject obj)
/* static */ bool
GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
{
static const JSPropertySpec protoAccessors[] = {
JS_PSG("exportName", ExportEntryObject_exportNameGetter, 0),
@@ -171,22 +165,15 @@ ExportEntryObject::initClass(JSContext* cx, HandleObject obj)
JS_PS_END
};
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
if (!proto)
return nullptr;
return false;
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
return nullptr;
return false;
global->setPrototype(JSProto_ExportEntry, ObjectValue(*proto));
return proto;
}
JSObject*
js::InitExportEntryClass(JSContext* cx, HandleObject obj)
{
return ExportEntryObject::initClass(cx, obj);
global->setReservedSlot(EXPORT_ENTRY_PROTO, ObjectValue(*proto));
return true;
}
static Value
@@ -202,9 +189,12 @@ ExportEntryObject::create(JSContext* cx,
HandleAtom maybeImportName,
HandleAtom maybeLocalName)
{
RootedExportEntry self(cx, NewBuiltinClassInstance<ExportEntryObject>(cx));
if (!self)
RootedObject proto(cx, cx->global()->getExportEntryPrototype());
RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
if (!obj)
return nullptr;
RootedExportEntry self(cx, &obj->as<ExportEntryObject>());
self->initReservedSlot(ExportNameSlot, StringOrNullValue(maybeExportName));
self->initReservedSlot(ModuleRequestSlot, StringOrNullValue(maybeModuleRequest));
self->initReservedSlot(ImportNameSlot, StringOrNullValue(maybeImportName));
@@ -544,7 +534,6 @@ void FunctionDeclaration::trace(JSTracer* trc)
ModuleObject::class_ = {
"Module",
JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Module) |
JSCLASS_IS_ANONYMOUS,
nullptr, /* addProperty */
nullptr, /* delProperty */
@@ -553,7 +542,7 @@ ModuleObject::class_ = {
nullptr, /* enumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
nullptr, /* finalize */
ModuleObject::finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
@@ -582,10 +571,12 @@ ModuleObject::isInstance(HandleValue value)
/* static */ ModuleObject*
ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope)
{
Rooted<ModuleObject*> self(cx, NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject));
if (!self)
RootedObject proto(cx, cx->global()->getModulePrototype());
RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto));
if (!obj)
return nullptr;
RootedModuleObject self(cx, &obj->as<ModuleObject>());
self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(enclosingStaticScope));
Zone* zone = cx->zone();
@@ -855,8 +846,8 @@ DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot
DEFINE_GETTER_FUNCTIONS(ModuleObject, indirectExportEntries, IndirectExportEntriesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, starExportEntries, StarExportEntriesSlot)
JSObject*
js::InitModuleClass(JSContext* cx, HandleObject obj)
/* static */ bool
GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
{
static const JSPropertySpec protoAccessors[] = {
JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
@@ -877,17 +868,24 @@ js::InitModuleClass(JSContext* cx, HandleObject obj)
JS_FS_END
};
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
if (!proto)
return nullptr;
return false;
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, protoFunctions))
return nullptr;
return false;
global->setPrototype(JSProto_Module, ObjectValue(*proto));
return proto;
global->setReservedSlot(MODULE_PROTO, ObjectValue(*proto));
return true;
}
bool
js::InitModuleClasses(JSContext* cx, HandleObject obj)
{
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
return GlobalObject::initModuleProto(cx, global) &&
GlobalObject::initImportEntryProto(cx, global) &&
GlobalObject::initExportEntryProto(cx, global);
}
#undef DEFINE_GETTER_FUNCTIONS
+1 -3
View File
@@ -306,9 +306,7 @@ class MOZ_STACK_CLASS ModuleBuilder
ArrayObject* createArray(const TraceableVector<T>& vector);
};
JSObject* InitModuleClass(JSContext* cx, HandleObject obj);
JSObject* InitImportEntryClass(JSContext* cx, HandleObject obj);
JSObject* InitExportEntryClass(JSContext* cx, HandleObject obj);
bool InitModuleClasses(JSContext* cx, HandleObject obj);
} // namespace js
-3
View File
@@ -112,9 +112,6 @@ IF_SAB(real,imaginary)(SharedUint8ClampedArray, 51, InitViaClassSpec,
real(TypedArray, 52, InitViaClassSpec, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
IF_SAB(real,imaginary)(Atomics, 53, InitAtomicsClass, OCLASP(Atomics)) \
real(SavedFrame, 54, InitViaClassSpec, &js::SavedFrame::class_) \
real(Module, 55, InitModuleClass, OCLASP(Module)) \
real(ImportEntry, 56, InitImportEntryClass, OCLASP(ImportEntry)) \
real(ExportEntry, 57, InitExportEntryClass, OCLASP(ExportEntry)) \
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
+3
View File
@@ -6077,6 +6077,9 @@ NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
/* Initialize FakeDOMObject.prototype */
InitDOMObject(domProto);
if (!js::InitModuleClasses(cx, glob))
return nullptr;
}
JS_FireOnNewGlobalObject(cx, glob);
+20
View File
@@ -108,6 +108,9 @@ class GlobalObject : public NativeObject
COLLATOR_PROTO,
NUMBER_FORMAT_PROTO,
DATE_TIME_FORMAT_PROTO,
MODULE_PROTO,
IMPORT_ENTRY_PROTO,
EXPORT_ENTRY_PROTO,
REGEXP_STATICS,
WARNED_ONCE_FLAGS,
RUNTIME_CODEGEN_ENABLED,
@@ -467,6 +470,18 @@ class GlobalObject : public NativeObject
return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
}
JSObject* getModulePrototype() {
return &getSlot(MODULE_PROTO).toObject();
}
JSObject* getImportEntryPrototype() {
return &getSlot(IMPORT_ENTRY_PROTO).toObject();
}
JSObject* getExportEntryPrototype() {
return &getSlot(EXPORT_ENTRY_PROTO).toObject();
}
static JSFunction*
getOrCreateTypedArrayConstructor(JSContext* cx, Handle<GlobalObject*> global) {
if (!ensureConstructor(cx, global, JSProto_TypedArray))
@@ -679,6 +694,11 @@ class GlobalObject : public NativeObject
static bool initNumberFormatProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initDateTimeFormatProto(JSContext* cx, Handle<GlobalObject*> global);
// Implemented in builtin/ModuleObject.cpp
static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
// Implemented in builtin/TypedObject.cpp
static bool initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global);
+3
View File
@@ -5418,6 +5418,9 @@ pref("media.useAudioChannelAPI", false);
// Turn rewriting of youtube embeds on/off
pref("plugins.rewrite_youtube_embeds", true);
// Expose Request.cache. Currently disabled since the implementation is incomplete.
pref("dom.requestcache.enabled", false);
// Expose Request.context. Currently disabled since the spec is in flux.
pref("dom.requestcontext.enabled", false);
+12
View File
@@ -0,0 +1,12 @@
#! /bin/bash -vex
set -x -e -v
####
# The default build works for any fx_desktop_build based mozharness job:
# via linux-build.sh
####
. $HOME/bin/checkout-sources.sh
. $WORKSPACE/build/src/testing/taskcluster/scripts/builder/build-linux.sh
@@ -0,0 +1,54 @@
#! /bin/bash -vex
set -x -e
# Inputs, with defaults
# mozharness builds use three repositories: gecko (source), mozharness (build
# scripts) and tools (miscellaneous) for each, specify *_REPOSITORY. If the
# revision is not in the standard repo for the codebase, specify *_BASE_REPO as
# the canonical repo to clone and *_HEAD_REPO as the repo containing the
# desired revision. For Mercurial clones, only *_HEAD_REV is required; for Git
# clones, specify the branch name to fetch as *_HEAD_REF and the desired sha1
# as *_HEAD_REV. For compatibility, we also accept MOZHARNESS_{REV,REF}
: GECKO_REPOSITORY ${GECKO_REPOSITORY:=https://hg.mozilla.org/mozilla-central}
: GECKO_BASE_REPOSITORY ${GECKO_BASE_REPOSITORY:=${GECKO_REPOSITORY}}
: GECKO_HEAD_REPOSITORY ${GECKO_HEAD_REPOSITORY:=${GECKO_REPOSITORY}}
: GECKO_HEAD_REV ${GECKO_HEAD_REV:=default}
: GECKO_HEAD_REF ${GECKO_HEAD_REF:=${GECKO_HEAD_REV}}
: MOZHARNESS_REPOSITORY ${MOZHARNESS_REPOSITORY:=https://hg.mozilla.org/build/mozharness}
: MOZHARNESS_BASE_REPOSITORY ${MOZHARNESS_BASE_REPOSITORY:=${MOZHARNESS_REPOSITORY}}
: MOZHARNESS_HEAD_REPOSITORY ${MOZHARNESS_HEAD_REPOSITORY:=${MOZHARNESS_REPOSITORY}}
: MOZHARNESS_REV ${MOZHARNESS_REV:=production}
: MOZHARNESS_REF ${MOZHARNESS_REF:=${MOZHARNESS_REV}}
: MOZHARNESS_HEAD_REV ${MOZHARNESS_HEAD_REV:=${MOZHARNESS_REV}}
: MOZHARNESS_HEAD_REF ${MOZHARNESS_HEAD_REF:=${MOZHARNESS_REF}}
: TOOLS_REPOSITORY ${TOOLS_REPOSITORY:=https://hg.mozilla.org/build/tools}
: TOOLS_BASE_REPOSITORY ${TOOLS_BASE_REPOSITORY:=${TOOLS_REPOSITORY}}
: TOOLS_HEAD_REPOSITORY ${TOOLS_HEAD_REPOSITORY:=${TOOLS_REPOSITORY}}
: TOOLS_HEAD_REV ${TOOLS_HEAD_REV:=default}
: TOOLS_HEAD_REF ${TOOLS_HEAD_REF:=${TOOLS_HEAD_REV}}
: MH_CUSTOM_BUILD_VARIANT_CFG ${MH_CUSTOM_BUILD_VARIANT_CFG}
: MH_BRANCH ${MH_BRANCH:=mozilla-central}
: MH_BUILD_POOL ${MH_BUILD_POOL:=staging}
: WORKSPACE ${WORKSPACE:=/home/worker/workspace}
set -v
# check out mozharness
tc-vcs checkout mozharness $MOZHARNESS_BASE_REPOSITORY $MOZHARNESS_HEAD_REPOSITORY $MOZHARNESS_HEAD_REV $MOZHARNESS_HEAD_REF
# check out tools where mozharness expects it to be ($PWD/build/tools and $WORKSPACE/build/tools)
tc-vcs checkout $WORKSPACE/build/tools $TOOLS_BASE_REPOSITORY $TOOLS_HEAD_REPOSITORY $TOOLS_HEAD_REV $TOOLS_HEAD_REF
if [ ! -d build ]; then
mkdir -p build
ln -s $WORKSPACE/build/tools build/tools
fi
# and check out mozilla-central where mozharness will use it as a cache (/builds/hg-shared)
tc-vcs checkout $WORKSPACE/build/src $GECKO_BASE_REPOSITORY $GECKO_HEAD_REPOSITORY $GECKO_HEAD_REV $GECKO_HEAD_REF
@@ -1273,15 +1273,15 @@ or run without that action (ie: --no-{action})"
def _query_props_set_by_mach(self, console_output=True, error_level=FATAL):
mach_properties_path = os.path.join(
self.query_abs_dirs()['abs_obj_dir'], 'mach_build_properties.json'
self.query_abs_dirs()['abs_obj_dir'], 'dist', 'mach_build_properties.json'
)
self.info("setting properties set by mach build. Looking in path: %s"
% mach_properties_path)
if os.path.exists(mach_properties_path):
with self.opened(mach_properties_path, error_level=error_level) as (fh, err):
build_props = json.load(fh)
if not build_props or err:
self.log("%s exists but there was an error finding any "
if err:
self.log("%s exists but there was an error reading the "
"properties. props: `%s` - error: "
"`%s`" % (mach_properties_path,
build_props or 'None',
@@ -1294,9 +1294,7 @@ or run without that action (ie: --no-{action})"
if prop != 'UNKNOWN':
self.set_buildbot_property(key, prop, write_to_file=True)
else:
self.log("Could not determine path for build properties. "
"Does this exist: `%s` ?" % mach_properties_path,
level=error_level)
self.info("No mach_build_properties.json found - not importing properties.")
def generate_build_props(self, console_output=True, halt_on_failure=False):
"""sets props found from mach build and, in addition, buildid,
@@ -1607,7 +1605,7 @@ or run without that action (ie: --no-{action})"
self._run_tooltool()
self._create_mozbuild_dir()
mach_props = os.path.join(
self.query_abs_dirs()['abs_obj_dir'], 'mach_build_properties.json'
self.query_abs_dirs()['abs_obj_dir'], 'dist', 'mach_build_properties.json'
)
if os.path.exists(mach_props):
self.info("Removing previous mach property file: %s" % mach_props)
@@ -0,0 +1,153 @@
#! /bin/bash -vex
set -x -e
####
# Taskcluster friendly wrapper for performing fx desktop builds via mozharness.
####
# Inputs, with defaults
: MOZHARNESS_SCRIPT ${MOZHARNESS_SCRIPT}
: MOZHARNESS_CONFIG ${MOZHARNESS_CONFIG}
: TOOLTOOL_CACHE ${TOOLTOOL_CACHE:=/home/worker/tooltool-cache}
: RELENGAPI_TOKEN ${RELENGAPI_TOKEN+HIDDEN}
: NEED_XVFB ${NEED_XVFB:=false}
: MH_CUSTOM_BUILD_VARIANT_CFG ${MH_CUSTOM_BUILD_VARIANT_CFG}
: MH_BRANCH ${MH_BRANCH:=mozilla-central}
: MH_BUILD_POOL ${MH_BUILD_POOL:=staging}
: WORKSPACE ${WORKSPACE:=/home/worker/workspace}
# files to be "uploaded" (moved to ~/artifacts) from obj-firefox/dist
: DIST_UPLOADS ${DIST_UPLOADS:=""}
# files which will be be prefixed with target before being sent to artifacts
# e.g. DIST_TARGET_UPLOADS="a.zip" runs mv v2.0.a.zip mv artifacts/target.a.zip
: DIST_TARGET_UPLOADS ${DIST_TARGET_UPLOADS:=""}
set -v
# Don't run the upload step; this is passed through mozharness to mach. Once
# the mozharness scripts are not run in Buildbot anymore, this can be moved to
# Mozharness (or the upload step removed from mach entirely)
export MOZ_AUTOMATION_UPLOAD=0
export MOZ_CRASHREPORTER_NO_REPORT=1
export MOZ_OBJDIR=obj-firefox
export MOZ_SYMBOLS_EXTRA_BUILDID=linux64
export POST_SYMBOL_UPLOAD_CMD=/usr/local/bin/post-symbol-upload.py
export TINDERBOX_OUTPUT=1
# Ensure that in tree libraries can be found
export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
# test required parameters are supplied
if [[ -z ${MOZHARNESS_SCRIPT} ]]; then exit 1; fi
if [[ -z ${MOZHARNESS_CONFIG} ]]; then exit 1; fi
cleanup() {
if [ -n "$xvfb_pid" ]; then
kill $xvfb_pid || true
fi
}
trap cleanup EXIT INT
# run mozharness in XVfb, if necessary; this is an array to maintain the quoting in the -s argument
if $NEED_XVFB; then
# Some mozharness scripts set DISPLAY=:2
Xvfb :2 -screen 0 1024x768x24 &
export DISPLAY=:2
xvfb_pid=$!
# Only error code 255 matters, because it signifies that no
# display could be opened. As long as we can open the display
# tests should work. We'll retry a few times with a sleep before
# failing.
retry_count=0
max_retries=2
xvfb_test=0
until [ $retry_count -gt $max_retries ]; do
xvinfo || xvfb_test=$?
if [ $xvfb_test != 255 ]; then
retry_count=$(($max_retries + 1))
else
retry_count=$(($retry_count + 1))
echo "Failed to start Xvfb, retry: $retry_count"
sleep 2
fi done
if [ $xvfb_test == 255 ]; then exit 255; fi
fi
# set up mozharness configuration, via command line, env, etc.
debug_flag=""
if [ 0$DEBUG -ne 0 ]; then
debug_flag='--debug'
fi
custom_build_variant_cfg_flag=""
if [ -n "${MH_CUSTOM_BUILD_VARIANT_CFG}" ]; then
custom_build_variant_cfg_flag="--custom-build-variant-cfg=${MH_CUSTOM_BUILD_VARIANT_CFG}"
fi
set +x
# mozharness scripts look for the relengapi token at this location, so put it there,
# if specified
if [ -n "${RELENGAPI_TOKEN}" ]; then
echo 'Storing $RELENGAPI_TOKEN in /builds/relengapi.tok'
echo ${RELENGAPI_TOKEN} > /builds/relengapi.tok
# unset it so that mozharness doesn't "helpfully" log it
unset RELENGAPI_TOKEN
fi
set -x
# $TOOLTOOL_CACHE bypasses mozharness completely and is read by tooltool_wrapper.sh to set the
# cache. However, only some mozharness scripts use tooltool_wrapper.sh, so this may not be
# entirely effective.
export TOOLTOOL_CACHE
# support multiple, space delimited, config files
config_cmds=""
for cfg in $MOZHARNESS_CONFIG; do
config_cmds="${config_cmds} --config ${cfg}"
done
# Mozharness would ordinarily do the checkouts itself, but they are disabled
# here (--no-checkout-sources, --no-clone-tools) as the checkout is performed above.
./${MOZHARNESS_SCRIPT} ${config_cmds} \
$debug_flag \
$custom_build_variant_cfg_flag \
--disable-mock \
--no-setup-mock \
--no-checkout-sources \
--no-clone-tools \
--no-clobber \
--no-update \
--no-upload-files \
--no-sendchange \
--log-level=debug \
--work-dir=$WORKSPACE/build \
--no-action=generate-build-stats \
--branch=${MH_BRANCH} \
--build-pool=${MH_BUILD_POOL}
mkdir -p /home/worker/artifacts
# upload auxiliary files
cd $WORKSPACE/build/src/obj-firefox/dist
for file in $DIST_UPLOADS
do
mv $file $HOME/artifacts/$file
done
# Discard version numbers from packaged files, they just make it hard to write
# the right filename in the task payload where artifacts are declared
for file in $DIST_TARGET_UPLOADS
do
mv *.$file $HOME/artifacts/target.$file
done
@@ -0,0 +1 @@
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-add.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-delete.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,6 +0,0 @@
[cache-match.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
[Cache.match and Cache.matchAll]
expected: FAIL
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,6 +0,0 @@
[cache-put.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
[Cache.put with request URLs containing embedded credentials]
expected: FAIL
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,3 +0,0 @@
[cache-storage-keys.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-storage-match.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-storage.https.html]
type: testharness
prefs: [dom.serviceWorkers.enabled: true, dom.serviceWorkers.interception.enabled: true, dom.serviceWorkers.exemptFromPerDomainMax:true, dom.caches.enabled:true]
@@ -1,5 +0,0 @@
[cache-match.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
expected: ERROR
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,6 +0,0 @@
[cache-put.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
[Cache.put with request URLs containing embedded credentials]
expected: FAIL
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,3 +0,0 @@
[cache-storage-match.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
@@ -0,0 +1 @@
prefs: [dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-add.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-delete.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
@@ -1,5 +0,0 @@
[cache-match.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
expected: ERROR
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,6 +0,0 @@
[cache-put.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
[Cache.put with request URLs containing embedded credentials]
expected: FAIL
bug: https://github.com/w3c/web-platform-tests/issues/2098
@@ -1,3 +0,0 @@
[cache-storage-keys.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-storage-match.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
@@ -1,3 +0,0 @@
[cache-storage.https.html]
type: testharness
prefs: [dom.caches.enabled:true]
+2
View File
@@ -194,6 +194,8 @@ checksum:
upload: checksum
$(PYTHON) $(MOZILLA_DIR)/build/upload.py --base-path $(DIST) \
--package $(PACKAGE) \
--properties-file $(DIST)/mach_build_properties.json \
$(UPLOAD_FILES) \
$(CHECKSUM_FILES)
+9 -4
View File
@@ -248,7 +248,10 @@ void nsMenuBarX::RemoveMenuAtIndex(uint32_t aIndex)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NS_ASSERTION(aIndex < mMenuArray.Length(), "Attempting submenu removal with bad index!");
if (mMenuArray.Length() <= aIndex) {
NS_ERROR("Attempting submenu removal with bad index!");
return;
}
// Our native menu and our internal menu object array might be out of sync.
// This happens, for example, when a submenu is hidden. Because of this we
@@ -570,12 +573,14 @@ NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
nsCOMPtr<nsIDocument> doc = inMenu->Content()->GetUncomposedDoc();
if (!doc)
if (!doc) {
return nil;
}
nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(doc));
if (!domdoc)
if (!domdoc) {
return nil;
}
// Get information from the gecko menu item
nsAutoString label;
@@ -634,7 +639,7 @@ NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString
MenuItemInfo * info = [[MenuItemInfo alloc] initWithMenuGroupOwner:this];
[newMenuItem setRepresentedObject:info];
[info release];
return newMenuItem;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
+3 -7
View File
@@ -6,6 +6,7 @@
#include "nsNativeThemeCocoa.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Helpers.h"
#include "nsDeviceContext.h"
#include "nsLayoutUtils.h"
#include "nsObjCExceptions.h"
@@ -2428,19 +2429,14 @@ nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
if (nativeWidgetRect.IsEmpty())
return NS_OK; // Don't attempt to draw invisible widgets.
gfxContext* thebesCtx = aContext->ThebesContext();
if (!thebesCtx)
return NS_ERROR_FAILURE;
gfxContextMatrixAutoSaveRestore save(thebesCtx);
AutoRestoreTransform autoRestoreTransform(&aDrawTarget);
bool hidpi = IsHiDPIContext(aFrame->PresContext());
if (hidpi) {
// Use high-resolution drawing.
nativeWidgetRect.Scale(0.5f);
nativeDirtyRect.Scale(0.5f);
thebesCtx->SetMatrix(
thebesCtx->CurrentMatrix().Scale(2.0f, 2.0f));
aDrawTarget.SetTransform(aDrawTarget.GetTransform().PreScale(2.0f, 2.0f));
}
gfxQuartzNativeDrawing nativeDrawing(aDrawTarget, nativeDirtyRect);