merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-10-31 14:07:48 +01:00
commit 52411c0726
106 changed files with 863 additions and 425 deletions

View File

@ -10,6 +10,7 @@
#include "ApplicationAccessibleWrap.h"
#include "InterfaceInitFuncs.h"
#include "nsAccUtils.h"
#include "mozilla/a11y/PDocAccessible.h"
#include "ProxyAccessible.h"
#include "RootAccessible.h"
#include "nsMai.h"
@ -771,7 +772,27 @@ AtkAttributeSet *
getAttributesCB(AtkObject *aAtkObj)
{
AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
return accWrap ? GetAttributeSet(accWrap) : nullptr;
if (accWrap)
return GetAttributeSet(accWrap);
ProxyAccessible* proxy = GetProxy(aAtkObj);
if (!proxy)
return nullptr;
nsAutoTArray<Attribute, 10> attrs;
proxy->Attributes(&attrs);
if (attrs.IsEmpty())
return nullptr;
AtkAttributeSet* objAttributeSet = nullptr;
for (uint32_t i = 0; i < attrs.Length(); i++) {
AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
objAttr->name = g_strdup(attrs[i].Name().get());
objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(attrs[i].Value()).get());
objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
}
return objAttributeSet;
}
const gchar*

View File

@ -49,3 +49,5 @@ if CONFIG['MOZ_ENABLE_GTK']:
if CONFIG['MOZ_ENABLE_DBUS']:
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -8,6 +8,9 @@
#include "Accessible-inl.h"
#include "nsIPersistentProperties2.h"
#include "nsISimpleEnumerator.h"
namespace mozilla {
namespace a11y {
@ -76,5 +79,43 @@ DocAccessibleChild::RecvDescription(const uint64_t& aID, nsString* aDesc)
acc->Description(*aDesc);
return true;
}
bool
DocAccessibleChild::RecvAttributes(const uint64_t& aID, nsTArray<Attribute>* aAttributes)
{
Accessible* acc = mDoc->GetAccessibleByUniqueID((void*)aID);
if (!acc)
return true;
nsCOMPtr<nsIPersistentProperties> props = acc->Attributes();
if (!props)
return true;
nsCOMPtr<nsISimpleEnumerator> propEnum;
nsresult rv = props->Enumerate(getter_AddRefs(propEnum));
NS_ENSURE_SUCCESS(rv, false);
bool hasMore;
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> sup;
rv = propEnum->GetNext(getter_AddRefs(sup));
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
NS_ENSURE_TRUE(propElem, false);
nsAutoCString name;
rv = propElem->GetKey(name);
NS_ENSURE_SUCCESS(rv, false);
nsAutoString value;
rv = propElem->GetValue(value);
NS_ENSURE_SUCCESS(rv, false);
aAttributes->AppendElement(Attribute(name, value));
}
return true;
}
}
}

View File

@ -48,6 +48,8 @@ public:
*/
virtual bool RecvDescription(const uint64_t& aID, nsString* aDesc) MOZ_OVERRIDE;
virtual bool RecvAttributes(const uint64_t& aID, nsTArray<Attribute> *aAttributes) MOZ_OVERRIDE;
private:
DocAccessible* mDoc;
};

View File

@ -23,6 +23,12 @@ struct ShowEventData
AccessibleData[] NewTree;
};
struct Attribute
{
nsCString Name;
nsString Value;
};
prio(normal upto high) sync protocol PDocAccessible
{
manager PContent;
@ -42,6 +48,7 @@ child:
prio(high) sync State(uint64_t aID) returns(uint64_t states);
prio(high) sync Name(uint64_t aID) returns(nsString name);
prio(high) sync Description(uint64_t aID) returns(nsString desc);
prio(high) sync Attributes(uint64_t aID) returns(Attribute[] attributes);
};
}

View File

@ -59,5 +59,11 @@ ProxyAccessible::Description(nsString& aDesc) const
{
unused << mDoc->SendDescription(mID, &aDesc);
}
void
ProxyAccessible::Attributes(nsTArray<Attribute> *aAttrs) const
{
unused << mDoc->SendAttributes(mID, aAttrs);
}
}
}

View File

@ -14,6 +14,7 @@
namespace mozilla {
namespace a11y {
class Attribute;
class DocAccessibleParent;
class ProxyAccessible
@ -68,6 +69,11 @@ public:
*/
void Description(nsString& aDesc) const;
/**
* Get the set of attributes on the proxied accessible.
*/
void Attributes(nsTArray<Attribute> *aAttrs) const;
/**
* Allow the platform to store a pointers worth of data on us.
*/

View File

@ -7,20 +7,11 @@ module.metadata = {
"stability": "experimental"
};
// This is known as @@iterator in the ES6 spec. Until it is bound to
// some well-known name, find the @@iterator object by expecting it as
// the first property accessed on a for-of iterable.
const iteratorSymbol = (function() {
try {
for (var _ of Proxy.create({get: function(_, name) { throw name; } }))
break;
} catch (name) {
return name;
}
throw new TypeError;
})();
exports.iteratorSymbol = iteratorSymbol;
// This is known as @@iterator in the ES6 spec. In builds that have ES6
// Symbols, use Symbol.iterator; otherwise use the legacy method name,
// "@@iterator".
const JS_HAS_SYMBOLS = typeof Symbol === "function";
exports.iteratorSymbol = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
// An adaptor that, given an object that is iterable with for-of, is
// suitable for being bound to __iterator__ in order to make the object

View File

@ -50,6 +50,13 @@ const kSubviewEvents = [
"ViewHiding"
];
/**
* The method name to use for ES6 iteration. If Symbols are enabled in
* this build, use Symbol.iterator; otherwise "@@iterator".
*/
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const kIteratorSymbol = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
/**
* The current version. We can use this to auto-add new default widgets as necessary.
* (would be const but isn't because of testing purposes)
@ -2679,7 +2686,7 @@ this.CustomizableUI = {
* for (let window of CustomizableUI.windows) { ... }
*/
windows: {
"@@iterator": function*() {
*[kIteratorSymbol]() {
for (let [window,] of gBuildWindows)
yield window;
}

View File

@ -3260,10 +3260,15 @@ LineResults.prototype = {
/**
* A generator-iterator over the global, source or line results.
*
* The method name depends on whether symbols are enabled in
* this build. If so, use Symbol.iterator; otherwise "@@iterator".
*/
GlobalResults.prototype["@@iterator"] =
SourceResults.prototype["@@iterator"] =
LineResults.prototype["@@iterator"] = function*() {
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
GlobalResults.prototype[ITERATOR_SYMBOL] =
SourceResults.prototype[ITERATOR_SYMBOL] =
LineResults.prototype[ITERATOR_SYMBOL] = function*() {
yield* this._store;
};

View File

@ -25,6 +25,13 @@ const EventEmitter = devtools.require("devtools/toolkit/event-emitter");
const FORBIDDEN_IDS = new Set(["toolbox", ""]);
const MAX_ORDINAL = 99;
/**
* The method name to use for ES6 iteration. If symbols are enabled in this
* build, use Symbol.iterator; otherwise "@@iterator".
*/
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
/**
* DevTools is a class that represents a set of developer tools, it holds a
* set of tools and keeps track of open toolboxes in the browser.
@ -486,7 +493,7 @@ DevTools.prototype = {
/**
* Iterator that yields each of the toolboxes.
*/
'@@iterator': function*() {
*[ITERATOR_SYMBOL]() {
for (let toolbox of this._toolboxes) {
yield toolbox;
}

View File

@ -18,6 +18,13 @@ const PAGE_SIZE_MAX_JUMPS = 30;
const SEARCH_ACTION_MAX_DELAY = 300; // ms
const ITEM_FLASH_DURATION = 300 // ms
/**
* The method name to use for ES6 iteration. If symbols are enabled in
* this build, use Symbol.iterator; otherwise "@@iterator".
*/
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
@ -3056,10 +3063,10 @@ Property.prototype = Heritage.extend(Variable.prototype, {
/**
* A generator-iterator over the VariablesView, Scopes, Variables and Properties.
*/
VariablesView.prototype["@@iterator"] =
Scope.prototype["@@iterator"] =
Variable.prototype["@@iterator"] =
Property.prototype["@@iterator"] = function*() {
VariablesView.prototype[ITERATOR_SYMBOL] =
Scope.prototype[ITERATOR_SYMBOL] =
Variable.prototype[ITERATOR_SYMBOL] =
Property.prototype[ITERATOR_SYMBOL] = function*() {
yield* this._store;
};

View File

@ -13,6 +13,13 @@ const PANE_APPEARANCE_DELAY = 50;
const PAGE_SIZE_ITEM_COUNT_RATIO = 5;
const WIDGET_FOCUSABLE_NODES = new Set(["vbox", "hbox"]);
/**
* The method name to use for ES6 iteration. If symbols are enabled in
* this build, use Symbol.iterator; otherwise "@@iterator".
*/
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
@ -1729,7 +1736,7 @@ this.WidgetMethods = {
/**
* A generator-iterator over all the items in this container.
*/
Item.prototype["@@iterator"] =
WidgetMethods["@@iterator"] = function*() {
Item.prototype[ITERATOR_SYMBOL] =
WidgetMethods[ITERATOR_SYMBOL] = function*() {
yield* this._itemsByElement.values();
};

View File

@ -6559,6 +6559,9 @@ case "$OS_TARGET:$NIGHTLY_BUILD" in
WINNT:1)
MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX
;;
Darwin:1)
MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX
;;
*)
MOZ_ARG_ENABLE_BOOL(content-sandbox,
[ --enable-content-sandbox Enable sandboxing support for content-processes],

View File

@ -815,6 +815,7 @@ class CSPReportSenderRunnable MOZ_FINAL : public nsRunnable
, mInnerWindowID(aInnerWindowID)
, mCSPContext(aCSPContext)
{
NS_ASSERTION(!aViolatedDirective.IsEmpty(), "Can not send reports without a violated directive");
// the observer subject is an nsISupports: either an nsISupportsCString
// from the arg passed in directly, or if that's empty, it's the blocked
// source.

View File

@ -927,16 +927,34 @@ nsCSPPolicy::directiveExists(enum CSPDirective aDir) const
return false;
}
/*
* Use this function only after ::allows() returned 'false'. Most and
* foremost it's used to get the violated directive before sending reports.
* The parameter outDirective is the equivalent of 'outViolatedDirective'
* for the ::permits() function family.
*/
void
nsCSPPolicy::getDirectiveStringForContentType(nsContentPolicyType aContentType,
nsAString& outDirective) const
{
nsCSPDirective* defaultDir = nullptr;
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
if (mDirectives[i]->restrictsContentType(aContentType)) {
mDirectives[i]->toString(outDirective);
return;
}
if (mDirectives[i]->isDefaultDirective()) {
defaultDir = mDirectives[i];
}
}
// if we haven't found a matching directive yet,
// the contentType must be restricted by the default directive
if (defaultDir) {
defaultDir->toString(outDirective);
return;
}
NS_ASSERTION(false, "Can not query directive string for contentType!");
outDirective.AppendASCII("couldNotQueryViolatedDirective");
}
void

View File

@ -58,9 +58,14 @@
ok(data.s === "hello", "string property");
ok(data.x.i === 10, "nested property");
ok(data.f() === 99, "function call");
is(Object.getOwnPropertyDescriptor(data, "doesn't exist"), undefined,
"getOwnPropertyDescriptor returns undefined for non-existant properties");
ok(Object.getOwnPropertyDescriptor(data, "i").value, 5,
"getOwnPropertyDescriptor.value works");
let obj = new data.ctor();
ok(obj.a === 3, "constructor call");
ok(document.title === "Hello, Kitty", "document node");
is(typeof document.cookie, "string", "can get document.cookie");
data.i = 6;
data.b = false;

View File

@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=548193
/*
* Description of the test:
* We try to load an inline-src using a policy that constrains
* all scripts from running (script-src 'none'). We verify that
* all scripts from running (default-src 'none'). We verify that
* the generated csp-report contains the expceted values. If any
* of the JSON is not formatted properly (e.g. not properly escaped)
* then JSON.parse will fail, which allows to pinpoint such errors
@ -29,10 +29,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=548193
const testfile = "tests/dom/base/test/csp/file_csp_report.html";
const reportURI = "http://mochi.test:8888/foo.sjs";
const policy = "script-src 'none'; report-uri " + reportURI;
const policy = "default-src 'none'; report-uri " + reportURI;
const docUri = "http://mochi.test:8888/tests/dom/base/test/csp/file_csp_testserver.sjs" +
"?file=tests/dom/base/test/csp/file_csp_report.html" +
"&csp=script-src%20%27none%27%3B%20report-uri%20http%3A//mochi.test%3A8888/foo.sjs";
"&csp=default-src%20%27none%27%3B%20report-uri%20http%3A//mochi.test%3A8888/foo.sjs";
window.checkResults = function(reportObj) {
var cspReport = reportObj["csp-report"];
@ -50,9 +50,9 @@ window.checkResults = function(reportObj) {
is(cspReport["blocked-uri"], "self", "Incorrect blocked-uri");
is(cspReport["violated-directive"], "script-src 'none'", "Incorrect violated-directive");
is(cspReport["violated-directive"], "default-src 'none'", "Incorrect violated-directive");
is(cspReport["original-policy"], "script-src 'none'; report-uri http://mochi.test:8888/foo.sjs",
is(cspReport["original-policy"], "default-src 'none'; report-uri http://mochi.test:8888/foo.sjs",
"Incorrect original-policy");
is(cspReport["source-file"], docUri, "Incorrect source-file");

View File

@ -16,9 +16,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1082672
</div>
<pre id="test">
<script type="application/javascript">
var sym = Symbol("ponies");
Object.defineProperty(window, sym, {configurable: true, value: 3});
is(window[sym], 3);
if (typeof Symbol === "function") {
var sym = Symbol("ponies");
Object.defineProperty(window, sym, {configurable: true, value: 3});
is(window[sym], 3);
} else {
ok(true, "no Symbols in this build");
}
</script>
</pre>
</body>

View File

@ -2014,7 +2014,7 @@ class PropertyDefiner:
getAvailableInTestFunc(interfaceMember),
descriptor.checkPermissionsIndicesForMembers.get(interfaceMember.identifier.name))
def generatePrefableArray(self, array, name, specTemplate, specTerminator,
def generatePrefableArray(self, array, name, specFormatter, specTerminator,
specType, getCondition, getDataTuple, doIdArrays):
"""
This method generates our various arrays.
@ -2023,7 +2023,8 @@ class PropertyDefiner:
name is the name as passed to generateArray
specTemplate is a template for each entry of the spec array
specFormatter is a function that takes a single argument, a tuple,
and returns a string, a spec array entry
specTerminator is a terminator for the spec array (inserted every time
our controlling pref changes and at the end of the array)
@ -2034,7 +2035,7 @@ class PropertyDefiner:
returns the corresponding MemberCondition.
getDataTuple is a callback function that takes an array entry and
returns a tuple suitable for substitution into specTemplate.
returns a tuple suitable to be passed to specFormatter.
"""
# We want to generate a single list of specs, but with specTerminator
@ -2077,7 +2078,7 @@ class PropertyDefiner:
switchToCondition(self, curCondition)
lastCondition = curCondition
# And the actual spec
specs.append(specTemplate % getDataTuple(member))
specs.append(specFormatter(getDataTuple(member)))
specs.append(specTerminator)
prefableSpecs.append(" { false, nullptr }")
@ -2354,9 +2355,15 @@ class MethodDefiner(PropertyDefiner):
return (m["name"], accessor, jitinfo, m["length"], flags(m), selfHostedName)
def formatSpec(fields):
if fields[0].startswith("@@"):
fields = (fields[0][2:],) + fields[1:]
return ' JS_SYM_FNSPEC(%s, %s, %s, %s, %s, %s)' % fields
return ' JS_FNSPEC("%s", %s, %s, %s, %s, %s)' % fields
return self.generatePrefableArray(
array, name,
' JS_FNSPEC("%s", %s, %s, %s, %s, %s)',
formatSpec,
' JS_FS_END',
'JSFunctionSpec',
condition, specData, doIdArrays)
@ -2460,7 +2467,7 @@ class AttrDefiner(PropertyDefiner):
return self.generatePrefableArray(
array, name,
' { "%s", %s, %s, %s}',
lambda fields: ' { "%s", %s, %s, %s}' % fields,
' JS_PS_END',
'JSPropertySpec',
PropertyDefiner.getControllingCondition, specData, doIdArrays)
@ -2488,7 +2495,7 @@ class ConstDefiner(PropertyDefiner):
return self.generatePrefableArray(
array, name,
' { "%s", %s }',
lambda fields: ' { "%s", %s }' % fields,
' { 0, JS::UndefinedValue() }',
'ConstantSpec',
PropertyDefiner.getControllingCondition, specData, doIdArrays)

View File

@ -16,18 +16,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1066432
var testInterfaceJS = new TestInterfaceJS();
ok(testInterfaceJS, "got a TestInterfaceJS object");
var nonIterableObject = { "@@iterator": 5 };
if (typeof Symbol === "function") {
// Make this test fail if Symbol.iterator is correctly implemented.
// This is here to make sure this test is updated when bug 918828 lands,
// at which point the correct code will be:
// var JS_HAS_SYMBOLS = typeof Symbol === "function";
// var std_iterator = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
// var nonIterableObject = { [std_iterator]: 5};
// Otherwise, fixing bug 918828 would cause this test to silently stop
// testing what it's supposed to be testing.
nonIterableObject[Symbol.iterator] = Array.prototype[Symbol.iterator];
}
var JS_HAS_SYMBOLS = typeof Symbol === "function";
var std_iterator = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
var nonIterableObject = {[std_iterator]: 5};
try {
testInterfaceJS.testSequenceOverload(nonIterableObject);

View File

@ -444,7 +444,7 @@ HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
NS_IMETHODIMP_(bool)
HTMLTextAreaElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry attributes[] {
static const MappedAttributeEntry attributes[] = {
{ &nsGkAtoms::wrap },
{ nullptr }
};

View File

@ -32,7 +32,9 @@ names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 10, "Should have 10 enumerated names");
var JS_HAS_SYMBOLS = typeof Symbol === "function";
is(names.length, JS_HAS_SYMBOLS ? 9 : 10,
"Should have 9 enumerated names (or 10 with '@@iterator')");
is(names[0], "0", "Enum entry 1");
is(names[1], "1", "Enum entry 2");
is(names[2], "2", "Enum entry 3");
@ -41,8 +43,12 @@ is(names[4], "4", "Enum entry 5");
is(names[5], "something", "Enum entry 6");
is(names[6], "namedItem", "Enum entry 7");
is(names[7], "item", "Enum entry 8");
is(names[8], "@@iterator", "Enum entry 9");
is(names[9], "length", "Enum entry 10");
if (JS_HAS_SYMBOLS) {
is(names[8], "length", "Enum entry 9");
} else {
is(names[8], "@@iterator", "Enum entry 9");
is(names[9], "length", "Enum entry 10");
}
names = Object.getOwnPropertyNames(x);
is(names.length, 10, "Should have 10 items");

View File

@ -28,7 +28,9 @@ var names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 9, "Should have 9 enumerated names");
var JS_HAS_SYMBOLS = typeof Symbol === "function";
is(names.length, JS_HAS_SYMBOLS ? 8 : 9,
"Should have 8 enumerated names (or 9 with '@@iterator')");
is(names[0], "0", "Enum entry 1")
is(names[1], "1", "Enum entry 2")
is(names[2], "2", "Enum entry 3")
@ -36,8 +38,12 @@ is(names[3], "3", "Enum entry 4")
is(names[4], "something", "Enum entry 5")
is(names[5], "item", "Enum entry 6")
is(names[6], "namedItem", "Enum entry 7")
is(names[7], "@@iterator", "Enum entry 8")
is(names[8], "length", "Enum entry 9")
if (JS_HAS_SYMBOLS) {
is(names[7], "length", "Enum entry 8");
} else {
is(names[7], "@@iterator", "Enum entry 8");
is(names[8], "length", "Enum entry 9");
}
names = Object.getOwnPropertyNames(x);
is(names.length, 9, "Should have 9 items");

View File

@ -42,7 +42,9 @@ var names2 = [];
for (var name in opt) {
names2.push(name);
}
is(names2.length, 12, "Should have twelve enumerated names");
var JS_HAS_SYMBOLS = typeof Symbol === "function";
is(names2.length, JS_HAS_SYMBOLS ? 11 : 12,
"Should have eleven enumerated names (or twelve with '@@iterator')");
is(names2[0], "0", "Enum entry 1")
is(names2[1], "1", "Enum entry 2")
is(names2[2], "2", "Enum entry 3")
@ -54,7 +56,9 @@ is(names2[7], "length", "Enum entry 8")
is(names2[8], "selectedIndex", "Enum entry 9")
is(names2[9], "item", "Enum entry 10")
is(names2[10], "namedItem", "Enum entry 11")
is(names2[11], "@@iterator", "Enum entry 12")
if (!JS_HAS_SYMBOLS) {
is(names2[11], "@@iterator", "Enum entry 12");
}
</script>
</pre>

View File

@ -38,7 +38,9 @@ var names = [];
for (var name in x) {
names.push(name);
}
is(names.length, 11, "Should have 11 enumerated names");
var JS_HAS_SYMBOLS = typeof Symbol === "function";
is(names.length, JS_HAS_SYMBOLS ? 10 : 11,
"Should have 10 enumerated names (or 11 with '@@iterator')");
is(names[0], "0", "Enum entry 1")
is(names[1], "1", "Enum entry 2")
is(names[2], "2", "Enum entry 3")
@ -48,8 +50,12 @@ is(names[5], "5", "Enum entry 6")
is(names[6], "something", "Enum entry 7")
is(names[7], "item", "Enum entry 8")
is(names[8], "namedItem", "Enum entry 9")
is(names[9], "@@iterator", "Enum entry 10")
is(names[10], "length", "Enum entry 11")
if (JS_HAS_SYMBOLS) {
is(names[9], "length", "Enum entry 10");
} else {
is(names[9], "@@iterator", "Enum entry 10");
is(names[10], "length", "Enum entry 11");
}
names = Object.getOwnPropertyNames(x);
is(names.length, 11, "Should have 11 items");

View File

@ -2206,6 +2206,14 @@ SetDefaultPragmas(mozIStorageConnection* aConnection)
return rv;
}
if (IndexedDatabaseManager::FullSynchronous()) {
rv = aConnection->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("PRAGMA synchronous = FULL;"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}

View File

@ -212,6 +212,7 @@ IndexedDatabaseManager::~IndexedDatabaseManager()
}
bool IndexedDatabaseManager::sIsMainProcess = false;
bool IndexedDatabaseManager::sFullSynchronousMode = false;
mozilla::Atomic<bool> IndexedDatabaseManager::sLowDiskSpaceMode(false);
// static
@ -299,6 +300,14 @@ IndexedDatabaseManager::Init()
Preferences::RegisterCallbackAndCall(TestingPrefChangedCallback,
kTestingPref);
// By default IndexedDB uses SQLite with PRAGMA synchronous = NORMAL. This
// guarantees (unlike synchronous = OFF) atomicity and consistency, but not
// necessarily durability in situations such as power loss. This preference
// allows enabling PRAGMA synchronous = FULL on SQLite, which does guarantee
// durability, but with an extra fsync() and the corresponding performance
// hit.
sFullSynchronousMode = Preferences::GetBool("dom.indexedDB.fullSynchronous");
return NS_OK;
}
@ -502,6 +511,16 @@ IndexedDatabaseManager::InTestingMode()
return gTestingMode;
}
// static
bool
IndexedDatabaseManager::FullSynchronous()
{
MOZ_ASSERT(gDBManager,
"FullSynchronous() called before indexedDB has been initialized!");
return sFullSynchronousMode;
}
already_AddRefed<FileManager>
IndexedDatabaseManager::GetFileManager(PersistenceType aPersistenceType,
const nsACString& aOrigin,

View File

@ -80,6 +80,9 @@ public:
static bool
InTestingMode();
static bool
FullSynchronous();
already_AddRefed<FileManager>
GetFileManager(PersistenceType aPersistenceType,
const nsACString& aOrigin,
@ -162,6 +165,7 @@ private:
mozilla::Mutex mFileMutex;
static bool sIsMainProcess;
static bool sFullSynchronousMode;
static mozilla::Atomic<bool> sLowDiskSpaceMode;
};

View File

@ -50,7 +50,7 @@
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxTarget.h"
#include "nsDirectoryServiceDefs.h"
#elif defined(XP_LINUX)
#elif defined(XP_LINUX) || defined(XP_MACOSX)
#include "mozilla/Sandbox.h"
#endif
#endif
@ -552,6 +552,76 @@ NS_INTERFACE_MAP_BEGIN(ContentChild)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
static bool
GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath)
{
nsAutoCString appPath;
nsAutoCString appBinaryPath(
(CommandLine::ForCurrentProcess()->argv()[0]).c_str());
nsAutoCString::const_iterator start, end;
appBinaryPath.BeginReading(start);
appBinaryPath.EndReading(end);
if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
end = start;
++end; ++end; ++end; ++end;
appBinaryPath.BeginReading(start);
appPath.Assign(Substring(start, end));
} else {
return false;
}
nsCOMPtr<nsIFile> app, appBinary;
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
true, getter_AddRefs(app));
if (NS_FAILED(rv)) {
return false;
}
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
true, getter_AddRefs(appBinary));
if (NS_FAILED(rv)) {
return false;
}
bool isLink;
app->IsSymlink(&isLink);
if (isLink) {
app->GetNativeTarget(aAppPath);
} else {
app->GetNativePath(aAppPath);
}
appBinary->IsSymlink(&isLink);
if (isLink) {
appBinary->GetNativeTarget(aAppBinaryPath);
} else {
appBinary->GetNativePath(aAppBinaryPath);
}
return true;
}
void
ContentChild::OnChannelConnected(int32_t aPid)
{
nsAutoCString appPath, appBinaryPath;
if (!GetAppPaths(appPath, appBinaryPath)) {
MOZ_CRASH("Error resolving child process path");
}
MacSandboxInfo info;
info.type = MacSandboxType_Content;
info.appPath.Assign(appPath);
info.appBinaryPath.Assign(appBinaryPath);
nsAutoCString err;
if (!mozilla::StartMacSandbox(info, err)) {
NS_WARNING(err.get());
MOZ_CRASH("sandbox_init() failed");
}
}
#endif
bool
ContentChild::Init(MessageLoop* aIOLoop,
base::ProcessHandle aParentHandle,
@ -586,7 +656,9 @@ ContentChild::Init(MessageLoop* aIOLoop,
return false;
}
Open(aChannel, aParentHandle, aIOLoop);
if (!Open(aChannel, aParentHandle, aIOLoop)) {
return false;
}
sSingleton = this;
// Make sure there's an nsAutoScriptBlocker on the stack when dispatching

View File

@ -74,6 +74,10 @@ public:
nsCString vendor;
};
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
void OnChannelConnected(int32_t aPid);
#endif
bool Init(MessageLoop* aIOLoop,
base::ProcessHandle aParentHandle,
IPC::Channel* aChannel);

View File

@ -69,7 +69,7 @@ union MaybeNativeKeyBinding
void_t;
};
prio(normal upto high) intr protocol PBrowser
prio(normal upto urgent) intr protocol PBrowser
{
manager PContent or PContentBridge;
@ -141,7 +141,7 @@ parent:
* preference Native widget preference for IME updates
* seqno Current seqno value on the chrome side
*/
sync NotifyIMEFocus(bool focus)
prio(urgent) sync NotifyIMEFocus(bool focus)
returns (nsIMEUpdatePreference preference, uint32_t seqno);
/**
@ -157,8 +157,9 @@ parent:
* for insertion, offset == end
* for deletion, offset == newEnd
*/
NotifyIMETextChange(uint32_t offset, uint32_t end, uint32_t newEnd,
bool causedByComposition);
prio(urgent) async NotifyIMETextChange(uint32_t offset, uint32_t end,
uint32_t newEnd,
bool causedByComposition);
/**
* Notifies chrome that there is a IME compostion rect updated
@ -168,8 +169,10 @@ parent:
* caretOffset The offset of caret position
* caretRect The rect of IME caret
*/
NotifyIMESelectedCompositionRect(uint32_t offset, nsIntRect[] rect,
uint32_t caretOffset, nsIntRect caretRect);
prio(urgent) async NotifyIMESelectedCompositionRect(uint32_t offset,
nsIntRect[] rect,
uint32_t caretOffset,
nsIntRect caretRect);
/**
* Notifies chrome that there has been a change in selection
@ -180,22 +183,22 @@ parent:
* focus Offset where the caret is
* causedByComposition true if the change is caused by composition
*/
NotifyIMESelection(uint32_t seqno, uint32_t anchor, uint32_t focus,
bool causedByComposition);
prio(urgent) async NotifyIMESelection(uint32_t seqno, uint32_t anchor,
uint32_t focus, bool causedByComposition);
/**
* Notifies chrome to refresh its text cache
*
* text The entire content of the text field
*/
NotifyIMETextHint(nsString text);
prio(urgent) async NotifyIMETextHint(nsString text);
/**
* Notifies IME of mouse button event on a character in focused editor.
*
* Returns true if the mouse button event is consumd by IME.
*/
sync NotifyIMEMouseButtonEvent(IMENotification notification)
prio(urgent) sync NotifyIMEMouseButtonEvent(IMENotification notification)
returns (bool consumedByIME);
/**
@ -209,7 +212,7 @@ parent:
* if cancel is PR_FALSE,
* widget should return the current composition text
*/
sync EndIMEComposition(bool cancel) returns (nsString composition);
prio(urgent) sync EndIMEComposition(bool cancel) returns (nsString composition);
/**
* Request that the parent process move focus to the browser's frame. If
@ -217,16 +220,17 @@ parent:
*/
RequestFocus(bool canRaise);
sync GetInputContext() returns (int32_t IMEEnabled, int32_t IMEOpen,
intptr_t NativeIMEContext);
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
int32_t IMEOpen,
intptr_t NativeIMEContext);
SetInputContext(int32_t IMEEnabled,
int32_t IMEOpen,
nsString type,
nsString inputmode,
nsString actionHint,
int32_t cause,
int32_t focusChange);
prio(urgent) async SetInputContext(int32_t IMEEnabled,
int32_t IMEOpen,
nsString type,
nsString inputmode,
nsString actionHint,
int32_t cause,
int32_t focusChange);
sync IsParentWindowMainWidgetVisible() returns (bool visible);

View File

@ -330,7 +330,7 @@ union MaybeFileDesc {
void_t;
};
prio(normal upto high) intr protocol PContent
prio(normal upto urgent) intr protocol PContent
{
parent spawns PPluginModule;

View File

@ -28,7 +28,7 @@ namespace dom {
* allocate the PContentBridgeChild. This protocol allows these processes to
* share PBrowsers and send messages to each other.
*/
prio(normal upto high) intr protocol PContentBridge
prio(normal upto urgent) intr protocol PContentBridge
{
bridges PContent, PContent;

View File

@ -28,6 +28,7 @@ UDPSocketChildBase::ReleaseIPDLReference()
{
MOZ_ASSERT(mIPCOpen);
mIPCOpen = false;
mSocket = nullptr;
this->Release();
}

View File

@ -243,6 +243,14 @@ nsPluginHost::nsPluginHost()
// No need to initialize members to nullptr, false etc because this class
// has a zeroing operator new.
{
// Bump the pluginchanged epoch on startup. This insures content gets a
// good plugin list the first time it requests it. Normally we'd just
// init this to 1, but due to the unique nature of our ctor we need to do
// this manually.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
IncrementChromeEpoch();
}
// check to see if pref is set at startup to let plugins take over in
// full page mode for certain image mime types that we handle internally
mOverrideInternalTypes =

View File

@ -692,23 +692,6 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
return true;
}
struct AutoDeferMessages
{
typedef IPC::Message Message;
std::deque<Message>& mQueue;
mozilla::Vector<Message> mDeferred;
AutoDeferMessages(std::deque<Message>& queue) : mQueue(queue) {}
~AutoDeferMessages() {
mQueue.insert(mQueue.begin(), mDeferred.begin(), mDeferred.end());
}
void Defer(Message aMsg) {
mDeferred.append(aMsg);
}
};
bool
MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
{
@ -728,16 +711,28 @@ MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
mLink->SendMessage(msg.forget());
AutoDeferMessages defer(mPending);
while (true) {
while (!mPending.empty()) {
Message msg = mPending.front();
mPending.pop_front();
if (ShouldDeferMessage(msg))
defer.Defer(msg);
else
ProcessPendingRequest(msg);
// Loop until there aren't any more priority messages to process.
for (;;) {
mozilla::Vector<Message> toProcess;
for (MessageQueue::iterator it = mPending.begin(); it != mPending.end(); ) {
Message &msg = *it;
if (!ShouldDeferMessage(msg)) {
toProcess.append(msg);
it = mPending.erase(it);
continue;
}
it++;
}
if (toProcess.empty())
break;
// Processing these messages could result in more messages, so we
// loop around to check for more afterwards.
for (auto it = toProcess.begin(); it != toProcess.end(); it++)
ProcessPendingRequest(*it);
}
// See if we've received a reply.
@ -860,7 +855,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
// If the message is not Interrupt, we can dispatch it as normal.
if (!recvd.is_interrupt()) {
{
AutoEnterTransaction transaction(this, &recvd);
AutoEnterTransaction transaction(this, recvd);
MonitorAutoUnlock unlock(*mMonitor);
CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
DispatchMessage(recvd);
@ -947,7 +942,7 @@ MessageChannel::InterruptEventOccurred()
}
bool
MessageChannel::ProcessPendingRequest(Message aUrgent)
MessageChannel::ProcessPendingRequest(const Message &aUrgent)
{
AssertWorkerThread();
mMonitor->AssertCurrentThreadOwns();
@ -965,7 +960,7 @@ MessageChannel::ProcessPendingRequest(Message aUrgent)
{
// In order to send the parent RPC messages and guarantee it will
// wake up, we must re-use its transaction.
AutoEnterTransaction transaction(this, &aUrgent);
AutoEnterTransaction transaction(this, aUrgent);
MonitorAutoUnlock unlock(*mMonitor);
DispatchMessage(aUrgent);
@ -1029,7 +1024,7 @@ MessageChannel::OnMaybeDequeueOne()
{
// We should not be in a transaction yet if we're not blocked.
MOZ_ASSERT(mCurrentTransaction == 0);
AutoEnterTransaction transaction(this, &recvd);
AutoEnterTransaction transaction(this, recvd);
MonitorAutoUnlock unlock(*mMonitor);

View File

@ -45,7 +45,6 @@ class MessageChannel : HasResultCodes
{
friend class ProcessLink;
friend class ThreadLink;
friend class AutoEnterRPCTransaction;
class CxxStackFrame;
class InterruptFrame;
@ -228,7 +227,7 @@ class MessageChannel : HasResultCodes
bool InterruptEventOccurred();
bool ProcessPendingRequest(Message aUrgent);
bool ProcessPendingRequest(const Message &aUrgent);
void MaybeUndeferIncall();
void EnqueuePendingMessages();
@ -510,18 +509,18 @@ class MessageChannel : HasResultCodes
if (mChan->mCurrentTransaction == 0)
mChan->mCurrentTransaction = mChan->NextSeqno();
}
explicit AutoEnterTransaction(MessageChannel *aChan, Message *message)
explicit AutoEnterTransaction(MessageChannel *aChan, const Message &aMessage)
: mChan(aChan),
mOldTransaction(mChan->mCurrentTransaction)
{
mChan->mMonitor->AssertCurrentThreadOwns();
if (!message->is_sync())
if (!aMessage.is_sync())
return;
MOZ_ASSERT_IF(mChan->mSide == ParentSide && mOldTransaction != message->transaction_id(),
!mOldTransaction || message->priority() > mChan->AwaitingSyncReplyPriority());
mChan->mCurrentTransaction = message->transaction_id();
MOZ_ASSERT_IF(mChan->mSide == ParentSide && mOldTransaction != aMessage.transaction_id(),
!mOldTransaction || aMessage.priority() > mChan->AwaitingSyncReplyPriority());
mChan->mCurrentTransaction = aMessage.transaction_id();
}
~AutoEnterTransaction() {
mChan->mMonitor->AssertCurrentThreadOwns();

View File

@ -678,7 +678,7 @@ function ArrayFrom(arrayLike, mapfn=undefined, thisArg=undefined) {
var attrs = ATTR_CONFIGURABLE | ATTR_ENUMERABLE | ATTR_WRITABLE;
// Steps 6-8.
var usingIterator = items["@@iterator"];
var usingIterator = items[std_iterator];
if (usingIterator !== undefined) {
// Steps 8.a-c.
var A = IsConstructor(C) ? new C() : [];

View File

@ -878,7 +878,7 @@ const Class MapIteratorObject::class_ = {
};
const JSFunctionSpec MapIteratorObject::methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
JS_FN("next", next, 0, 0),
JS_FS_END
};
@ -1076,8 +1076,14 @@ MapObject::initClass(JSContext *cx, JSObject *obj)
// Define its alias.
RootedValue funval(cx, ObjectValue(*fun));
#if JS_HAS_SYMBOLS
RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0))
return nullptr;
#else
if (!JS_DefineProperty(cx, proto, js_std_iterator_str, funval, 0))
return nullptr;
#endif
}
return proto;
}
@ -1528,7 +1534,7 @@ const Class SetIteratorObject::class_ = {
};
const JSFunctionSpec SetIteratorObject::methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
JS_FN("next", next, 0, 0),
JS_FS_END
};
@ -1702,8 +1708,15 @@ SetObject::initClass(JSContext *cx, JSObject *obj)
RootedValue funval(cx, ObjectValue(*fun));
if (!JS_DefineProperty(cx, proto, "keys", funval, 0))
return nullptr;
#if JS_HAS_SYMBOLS
RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0))
return nullptr;
#else
if (!JS_DefineProperty(cx, proto, js_std_iterator_str, funval, 0))
return nullptr;
#endif
}
return proto;
}

View File

@ -31,7 +31,6 @@
//
// The few items below here are either self-hosted or installing them under a
// std_Foo name would require ugly contortions, so they just get aliased here.
var std_iterator = '@@iterator'; // FIXME: Change to be a symbol.
var std_Array_indexOf = ArrayIndexOf;
// WeakMap is a bare constructor without properties or methods.
var std_WeakMap = WeakMap;

View File

@ -2488,11 +2488,6 @@ EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
if (Emit1(cx, bce, op) < 0)
return false;
CheckTypeSet(cx, bce, op);
if (op == JSOP_CALLELEM) {
if (Emit1(cx, bce, JSOP_SWAP) < 0)
return false;
}
return true;
}
@ -4730,9 +4725,16 @@ EmitIterator(ExclusiveContext *cx, BytecodeEmitter *bce)
// Convert iterable to iterator.
if (Emit1(cx, bce, JSOP_DUP) < 0) // OBJ OBJ
return false;
if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // OBJ @@ITERATOR
#ifdef JS_HAS_SYMBOLS
if (Emit2(cx, bce, JSOP_SYMBOL, jsbytecode(JS::SymbolCode::iterator)) < 0) // OBJ OBJ @@ITERATOR
return false;
if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR OBJ
if (!EmitElemOpBase(cx, bce, JSOP_CALLELEM)) // OBJ ITERFN
return false;
#else
if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // OBJ ITERFN
return false;
#endif
if (Emit1(cx, bce, JSOP_SWAP) < 0) // ITERFN OBJ
return false;
if (EmitCall(cx, bce, JSOP_CALL, 0) < 0) // ITER
return false;
@ -5598,17 +5600,8 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter, Parse
if (!EmitTree(cx, bce, iter)) // ITERABLE
return false;
// Convert iterable to iterator.
if (Emit1(cx, bce, JSOP_DUP) < 0) // ITERABLE ITERABLE
if (!EmitIterator(cx, bce)) // ITER
return false;
if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // ITERABLE @@ITERATOR
return false;
if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR ITERABLE
return false;
if (EmitCall(cx, bce, JSOP_CALL, 0, iter) < 0) // ITER
return false;
CheckTypeSet(cx, bce, JSOP_CALL);
// Initial send value is undefined.
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // ITER RECEIVED
@ -6052,6 +6045,10 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
case PNK_ELEM:
if (!EmitElemOp(cx, pn2, callop ? JSOP_CALLELEM : JSOP_GETELEM, bce))
return false;
if (callop) {
if (Emit1(cx, bce, JSOP_SWAP) < 0)
return false;
}
break;
case PNK_FUNCTION:
/*

View File

@ -5,8 +5,8 @@
load(libdir + "asserts.js");
// FIXME: Import from std::iteration.
const std_iterator = '@@iterator';
const JS_HAS_SYMBOLS = typeof Symbol === "function";
const std_iterator = JS_HAS_SYMBOLS ? Symbol.iterator : '@@iterator';
if (typeof assertIteratorResult === 'undefined') {
var assertIteratorResult = function assertIteratorResult(result, value, done) {

View File

@ -1,7 +1,8 @@
// See bug 763313
load(libdir + "iteration.js");
function f([a]) a
var i = 0;
var o = {'@@iterator': function () { i++; return {
var o = {[std_iterator]: function () { i++; return {
next: function () { i++; return {value: 42, done: false}; }}}};
assertEq(f(o), 42);
assertEq(i, 2);

View File

@ -1,4 +1,5 @@
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function check_one(expected, f, err) {
var failed = true;
@ -109,8 +110,11 @@ check("o[- (o)]");
// A few one off tests
check_one("6", (function () { 6() }), " is not a function");
check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
check_one("(intermediate value)['@@iterator'](...).next(...).value", function () { var [{ x }] = [null, {}]; }, " is null");
check_one("(intermediate value)['@@iterator'](...).next(...).value", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
var ITERATOR = JS_HAS_SYMBOLS ? "Symbol.iterator" : "'@@iterator'";
check_one(`(intermediate value)[${ITERATOR}](...).next(...).value`,
function () { var [{ x }] = [null, {}]; }, " is null");
check_one(`(intermediate value)[${ITERATOR}](...).next(...).value`,
function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
// Check fallback behavior
assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError);

View File

@ -1,4 +1,5 @@
load(libdir + "asserts.js");
load(libdir + "iteration.js");
function testMethod(name) {
var method = WeakSet.prototype[name];
@ -15,7 +16,7 @@ testMethod("delete");
testMethod("clear");
assertThrowsInstanceOf(function() { var ws = new WeakSet(); ws.add(1); }, TypeError);
assertThrowsInstanceOf(function() { new WeakSet({"@@iterator": 2}) }, TypeError);
assertEq(typeof []["@@iterator"], "function"); // Make sure we fail when @@iterator is removed
assertThrowsInstanceOf(function() { new WeakSet({[std_iterator]: 2}) }, TypeError);
assertEq(typeof [][std_iterator], "function");
assertThrowsInstanceOf(function() { WeakSet(); }, TypeError);

View File

@ -7,7 +7,8 @@ function test(constructor) {
var proto = Object.getPrototypeOf(constructor()[std_iterator]());
var names = Object.getOwnPropertyNames(proto);
names.sort();
assertDeepEq(names, [std_iterator, 'next']);
assertDeepEq(names, JS_HAS_SYMBOLS ? ['next'] : ['@@iterator', 'next']);
assertEq(proto.hasOwnProperty(std_iterator), true);
var desc = Object.getOwnPropertyDescriptor(proto, 'next');
assertEq(desc.configurable, true);

View File

@ -0,0 +1,6 @@
var arr = [1, 2, 3];
var y = 0;
for (var i = 0; i < 10; i++)
for (var x of arr)
y += x;
assertEq(y, 60);

View File

@ -8,6 +8,6 @@ load(libdir + "asserts.js");
load(libdir + "iteration.js");
var g = newGlobal();
g.eval("var it = [1, 2]['" + std_iterator + "']();");
g.eval(`var it = [1, 2][${uneval(std_iterator)}]();`);
assertIteratorNext(g.it, 1);
assertThrowsInstanceOf([][std_iterator]().next.bind(g.it), TypeError)

View File

@ -3,7 +3,10 @@
load(libdir + "iteration.js");
var g = newGlobal();
var it = g.eval("({ '" + std_iterator + "': function () { return this; }, " +
"next: function () { return { done: true } } });");
for (x of it)
g.eval(`
var obj = {};
obj[${uneval(std_iterator)}] = function () { return this; };
obj.next = function () { return { done: true }; };
`);
for (x of g.obj)
throw 'FAIL';

View File

@ -57,7 +57,9 @@ var iterProto = Object.getPrototypeOf(iter);
assertEq(Object.getPrototypeOf(iterProto), Object.prototype);
// Own properties for StringIterator.prototype: "next" and @@iterator
arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next", std_iterator].sort());
arraysEqual(Object.getOwnPropertyNames(iterProto).sort(),
JS_HAS_SYMBOLS ? ["next"] : ["@@iterator", "next"]);
assertEq(iterProto.hasOwnProperty(std_iterator), true);
// StringIterator.prototype[@@iterator] is a built-in function
assertBuiltinFunction(iterProto, std_iterator, 0);

View File

@ -0,0 +1,14 @@
// |jit-test| error: ReferenceError
function eq(e, a) {
passed = (a == e);
}
function f(e, a) {
fail();
eq(e, a);
}
try {
f();
} catch (exc1) {}
eq(.1, .1);
var sym = Symbol("method");
evaluate("f(test, sym, 0)", {compileAndGo: true});

View File

@ -1259,6 +1259,15 @@ BaselineCompiler::emit_JSOP_STRING()
return true;
}
bool
BaselineCompiler::emit_JSOP_SYMBOL()
{
unsigned which = GET_UINT8(pc);
JS::Symbol *sym = cx->runtime()->wellKnownSymbols->get(which);
frame.push(SymbolValue(sym));
return true;
}
typedef NativeObject *(*DeepCloneObjectLiteralFn)(JSContext *, HandleNativeObject, NewObjectKind);
static const VMFunction DeepCloneObjectLiteralInfo =
FunctionInfo<DeepCloneObjectLiteralFn>(DeepCloneObjectLiteral);

View File

@ -61,6 +61,7 @@ namespace jit {
_(JSOP_UINT24) \
_(JSOP_DOUBLE) \
_(JSOP_STRING) \
_(JSOP_SYMBOL) \
_(JSOP_OBJECT) \
_(JSOP_CALLSITEOBJ) \
_(JSOP_REGEXP) \

View File

@ -3417,8 +3417,8 @@ IsCacheableGetPropReadSlot(JSObject *obj, JSObject *holder, Shape *shape, bool i
}
static bool
IsCacheableGetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape, bool *isScripted,
bool isDOMProxy=false)
IsCacheableGetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape,
bool *isScripted, bool *isTemporarilyUnoptimizable, bool isDOMProxy=false)
{
MOZ_ASSERT(isScripted);
@ -3439,8 +3439,10 @@ IsCacheableGetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
#ifdef JSGC_GENERATIONAL
// Information from get prop call ICs may be used directly from Ion code,
// and should not be nursery allocated.
if (IsInsideNursery(holder) || IsInsideNursery(func))
if (IsInsideNursery(holder) || IsInsideNursery(func)) {
*isTemporarilyUnoptimizable = true;
return false;
}
#endif
if (func->isNative()) {
@ -3448,8 +3450,10 @@ IsCacheableGetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
return true;
}
if (!func->hasJITCode())
if (!func->hasJITCode()) {
*isTemporarilyUnoptimizable = true;
return false;
}
*isScripted = true;
return true;
@ -3533,7 +3537,8 @@ IsCacheableSetPropAddSlot(JSContext *cx, HandleObject obj, HandleShape oldShape,
}
static bool
IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape, Shape* oldShape, bool *isScripted)
IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *shape,
Shape* oldShape, bool *isScripted, bool *isTemporarilyUnoptimizable)
{
MOZ_ASSERT(isScripted);
@ -3565,8 +3570,10 @@ IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
#ifdef JSGC_GENERATIONAL
// Information from set prop call ICs may be used directly from Ion code,
// and should not be nursery allocated.
if (IsInsideNursery(holder) || IsInsideNursery(func))
if (IsInsideNursery(holder) || IsInsideNursery(func)) {
*isTemporarilyUnoptimizable = true;
return false;
}
#endif
if (func->isNative()) {
@ -3574,8 +3581,10 @@ IsCacheableSetPropCall(JSContext *cx, JSObject *obj, JSObject *holder, Shape *sh
return true;
}
if (!func->hasJITCode())
if (!func->hasJITCode()) {
*isTemporarilyUnoptimizable = true;
return false;
}
*isScripted = true;
return true;
@ -3817,7 +3826,9 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt
}
bool getterIsScripted = false;
if (IsCacheableGetPropCall(cx, obj, holder, shape, &getterIsScripted, /*isDOMProxy=*/false)) {
bool isTemporarilyUnoptimizable = false;
if (IsCacheableGetPropCall(cx, obj, holder, shape, &getterIsScripted,
&isTemporarilyUnoptimizable, /*isDOMProxy=*/false)) {
RootedFunction getter(cx, &shape->getterObject()->as<JSFunction>());
#if JS_HAS_NO_SUCH_METHOD
@ -4063,6 +4074,9 @@ DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub_
if (!TryAttachGetElemStub(cx, frame->script(), pc, stub, lhs, rhs, res))
return false;
// If we ever add a way to note unoptimizable accesses here, propagate the
// isTemporarilyUnoptimizable state from TryAttachNativeGetElemStub to here.
return true;
}
@ -5840,7 +5854,9 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
// changes we need to make sure IonBuilder::getPropTryCommonGetter (which
// requires a Baseline stub) handles non-outerized this objects correctly.
bool isScripted;
if (IsCacheableGetPropCall(cx, global, current, shape, &isScripted) && !isScripted)
bool isTemporarilyUnoptimizable = false;
if (IsCacheableGetPropCall(cx, global, current, shape, &isScripted, &isTemporarilyUnoptimizable) &&
!isScripted)
{
ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
RootedFunction getter(cx, &shape->getterObject()->as<JSFunction>());
@ -6020,6 +6036,9 @@ DoGetNameFallback(JSContext *cx, BaselineFrame *frame, ICGetName_Fallback *stub_
return false;
}
// If we ever add a way to note unoptimizable accesses here, propagate the
// isTemporarilyUnoptimizable state from TryAttachGlobalNameStub to here.
return true;
}
@ -6396,9 +6415,11 @@ static bool
TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
ICGetProp_Fallback *stub, HandlePropertyName name,
HandleValue val, HandleShape oldShape,
HandleValue res, bool *attached)
HandleValue res, bool *attached,
bool *isTemporarilyUnoptimizable)
{
MOZ_ASSERT(!*attached);
MOZ_ASSERT(!*isTemporarilyUnoptimizable);
if (!val.isObject())
return true;
@ -6459,7 +6480,8 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
}
bool isScripted = false;
bool cacheableCall = IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted, isDOMProxy);
bool cacheableCall = IsCacheableGetPropCall(cx, obj, holder, shape, &isScripted,
isTemporarilyUnoptimizable, isDOMProxy);
// Try handling scripted getters.
if (cacheableCall && isScripted && !isDOMProxy) {
@ -6766,6 +6788,11 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_
}
bool attached = false;
// There are some reasons we can fail to attach a stub that are temporary.
// We want to avoid calling noteUnoptimizableAccess() if the reason we
// failed to attach a stub is one of those temporary reasons, since we might
// end up attaching a stub for the exact same access later.
bool isTemporarilyUnoptimizable = false;
if (op == JSOP_LENGTH) {
if (!TryAttachLengthStub(cx, frame->script(), stub, val, res, &attached))
@ -6782,7 +6809,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_
RootedScript script(cx, frame->script());
if (!TryAttachNativeGetPropStub(cx, script, pc, stub, name, val, oldShape,
res, &attached))
res, &attached, &isTemporarilyUnoptimizable))
return false;
if (attached)
return true;
@ -6803,7 +6830,8 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_
}
MOZ_ASSERT(!attached);
stub->noteUnoptimizableAccess();
if (!isTemporarilyUnoptimizable)
stub->noteUnoptimizableAccess();
return true;
}
@ -7699,9 +7727,11 @@ BaselineScript::noteAccessedGetter(uint32_t pcOffset)
static bool
TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetProp_Fallback *stub,
HandleObject obj, HandleShape oldShape, HandleTypeObject oldType, uint32_t oldSlots,
HandlePropertyName name, HandleId id, HandleValue rhs, bool *attached)
HandlePropertyName name, HandleId id, HandleValue rhs, bool *attached,
bool *isTemporarilyUnoptimizable)
{
MOZ_ASSERT(!*attached);
MOZ_ASSERT(!*isTemporarilyUnoptimizable);
if (!obj->isNative() || obj->watched())
return true;
@ -7780,7 +7810,8 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
}
bool isScripted = false;
bool cacheableCall = IsCacheableSetPropCall(cx, obj, holder, shape, oldShape, &isScripted);
bool cacheableCall = IsCacheableSetPropCall(cx, obj, holder, shape, oldShape,
&isScripted, isTemporarilyUnoptimizable);
// Try handling scripted setters.
if (cacheableCall && isScripted) {
@ -7906,8 +7937,13 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
}
bool attached = false;
// There are some reasons we can fail to attach a stub that are temporary.
// We want to avoid calling noteUnoptimizableAccess() if the reason we
// failed to attach a stub is one of those temporary reasons, since we might
// end up attaching a stub for the exact same access later.
bool isTemporarilyUnoptimizable = false;
if (!TryAttachSetPropStub(cx, script, pc, stub, obj, oldShape, oldType, oldSlots,
name, id, rhs, &attached))
name, id, rhs, &attached, &isTemporarilyUnoptimizable))
{
return false;
}
@ -7915,7 +7951,8 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
return true;
MOZ_ASSERT(!attached);
stub->noteUnoptimizableAccess();
if (!isTemporarilyUnoptimizable)
stub->noteUnoptimizableAccess();
return true;
}

View File

@ -8,9 +8,9 @@
#include "jsapi-tests/tests.h"
#ifdef JS_HAS_SYMBOLS
#define IF_JS_HAS_SYMBOLS(x) x
#define STD_ITERATOR "Symbol.iterator"
#else
#define IF_JS_HAS_SYMBOLS(x)
#define STD_ITERATOR "'@@iterator'"
#endif
BEGIN_TEST(testForOfIterator_basicNonIterable)
@ -18,9 +18,7 @@ BEGIN_TEST(testForOfIterator_basicNonIterable)
JS::RootedValue v(cx);
// Hack to make it simple to produce an object that has a property
// named Symbol.iterator.
EVAL("var obj = {'@@iterator': 5"
IF_JS_HAS_SYMBOLS(", [Symbol.iterator]: Array.prototype[Symbol.iterator]")
"}; obj;", &v);
EVAL("({[" STD_ITERATOR "]: 5})", &v);
JS::ForOfIterator iter(cx);
bool ok = iter.init(v);
CHECK(!ok);
@ -35,9 +33,7 @@ BEGIN_TEST(testForOfIterator_bug515273_part1)
// Hack to make it simple to produce an object that has a property
// named Symbol.iterator.
EVAL("var obj = {'@@iterator': 5"
IF_JS_HAS_SYMBOLS(", [Symbol.iterator]: Array.prototype[Symbol.iterator]")
"}; obj;", &v);
EVAL("({[" STD_ITERATOR "]: 5})", &v);
JS::ForOfIterator iter(cx);
bool ok = iter.init(v, JS::ForOfIterator::AllowNonIterable);

View File

@ -5592,7 +5592,7 @@ JS::GetSymbolCode(Handle<Symbol*> symbol)
JS_PUBLIC_API(JS::Symbol *)
JS::GetWellKnownSymbol(JSContext *cx, JS::SymbolCode which)
{
return cx->runtime()->wellKnownSymbols->get(uint32_t(which));
return cx->wellKnownSymbols().get(uint32_t(which));
}
static bool

View File

@ -2561,7 +2561,8 @@ struct JSFunctionSpec {
*
* The _SYM variants allow defining a function with a symbol key rather than a
* string key. For example, use JS_SYM_FN(iterator, ...) to define an
* @@iterator method.
* @@iterator method. (In builds without ES6 symbols, it defines a method with
* the string id "@@iterator".)
*/
#define JS_FS(name,call,nargs,flags) \
JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
@ -2575,10 +2576,17 @@ struct JSFunctionSpec {
JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName)
#define JS_SELF_HOSTED_SYM_FN(symbol, selfHostedName, nargs, flags) \
JS_SYM_FNSPEC(symbol, nullptr, nullptr, nargs, flags, selfHostedName)
#ifdef JS_HAS_SYMBOLS
#define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \
JS_FNSPEC(reinterpret_cast<const char *>( \
uint32_t(::JS::SymbolCode::symbol) + 1), \
call, info, nargs, flags, selfHostedName)
#else
#define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \
JS_FNSPEC("@@" #symbol, call, info, nargs, flags, selfHostedName)
#endif
#define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \
{name, {call, info}, nargs, flags, selfHostedName}

View File

@ -3174,7 +3174,7 @@ static const JSFunctionSpec array_methods[] = {
JS_SELF_HOSTED_FN("fill", "ArrayFill", 3,0),
JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0),
JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0,0),
JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0),
JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0),
JS_FS_END

View File

@ -156,7 +156,7 @@ JSRuntime::initializeAtoms(JSContext *cx)
if (!wellKnownSymbols)
return false;
ImmutablePropertyNamePtr *descriptions = &commonNames->Symbol_iterator;
ImmutablePropertyNamePtr *descriptions = commonNames->wellKnownSymbolDescriptions();
ImmutableSymbolPtr *symbols = reinterpret_cast<ImmutableSymbolPtr *>(wellKnownSymbols);
for (size_t i = 0; i < JS::WellKnownSymbolLimit; i++) {
JS::Symbol *symbol = JS::Symbol::new_(cx, JS::SymbolCode(i), descriptions[i]);

View File

@ -886,7 +886,7 @@ iterator_next(JSContext *cx, unsigned argc, Value *vp)
}
static const JSFunctionSpec iterator_methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "LegacyIteratorShim", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "LegacyIteratorShim", 0, 0),
JS_FN("next", iterator_next, 0, 0),
JS_FS_END
};
@ -965,7 +965,7 @@ const Class ArrayIteratorObject::class_ = {
};
static const JSFunctionSpec array_iterator_methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "ArrayIteratorIdentity", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "ArrayIteratorIdentity", 0, 0),
JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0),
JS_FS_END
};
@ -1004,7 +1004,7 @@ const Class StringIteratorObject::class_ = {
};
static const JSFunctionSpec string_iterator_methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "StringIteratorIdentity", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "StringIteratorIdentity", 0, 0),
JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
JS_FS_END
};
@ -1369,8 +1369,14 @@ ForOfIterator::init(HandleValue iterable, NonIterableBehavior nonIterableBehavio
args.setThis(ObjectValue(*iterableObj));
RootedValue callee(cx);
#ifdef JS_HAS_SYMBOLS
RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator));
if (!JSObject::getGeneric(cx, iterableObj, iterableObj, iteratorId, &callee))
return false;
#else
if (!JSObject::getProperty(cx, iterableObj, iterableObj, cx->names().std_iterator, &callee))
return false;
#endif
// If obj[@@iterator] is undefined and we were asked to allow non-iterables,
// bail out now without setting iterator. This will make valueIsIterable(),

View File

@ -1592,6 +1592,13 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc)
return sprinter.printf("%d", GetBytecodeInteger(pc)) >= 0;
case JSOP_STRING:
return quote(loadAtom(pc), '"');
case JSOP_SYMBOL: {
unsigned i = uint8_t(pc[1]);
MOZ_ASSERT(i < JS::WellKnownSymbolLimit);
if (i < JS::WellKnownSymbolLimit)
return write(cx->names().wellKnownSymbolDescriptions()[i]);
break;
}
case JSOP_UNDEFINED:
return write(js_undefined_str);
case JSOP_THIS:

View File

@ -4204,7 +4204,7 @@ static const JSFunctionSpec string_methods[] = {
JS_SELF_HOSTED_FN("fontcolor","String_fontcolor", 1,0),
JS_SELF_HOSTED_FN("fontsize", "String_fontsize", 1,0),
JS_SELF_HOSTED_FN("@@iterator", "String_iterator", 0,0),
JS_SELF_HOSTED_SYM_FN(iterator, "String_iterator", 0,0),
JS_FS_END
};

View File

@ -25,7 +25,7 @@ function TestChangeArrayIteratorNext() {
return M2;
}
var iter = ([])['@@iterator']();
var iter = ([])[std_iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {

View File

@ -27,7 +27,7 @@ function TestIncreaseArrayLength() {
return M2;
}
var iter = ([])['@@iterator']();
var iter = ([])[std_iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {

View File

@ -26,7 +26,7 @@ function TestDecreaseArrayLength() {
return M2;
}
var iter = ([])['@@iterator']();
var iter = ([])[std_iterator]();
var iterProto = Object.getPrototypeOf(iter);
var OldNext = iterProto.next;
var NewNext = function () {

View File

@ -134,8 +134,8 @@ assertEq(obj instanceof C, true);
for (var primitive of [undefined, null, 17]) {
assertThrowsInstanceOf(
() => Array.from({
"@@iterator": () => {
next: () => primitive
[std_iterator]() {
return {next() { return primitive; }};
}
}),
TypeError);

View File

@ -8,7 +8,7 @@
// If an object has both .length and [@@iterator] properties, [@@iterator] is used.
var a = ['a', 'e', 'i', 'o', 'u'];
a["@@iterator"] = function* () {
a[std_iterator] = function* () {
for (var i = 5; i--; )
yield this[i];
};

View File

@ -6,19 +6,19 @@ var log = [];
function LoggingProxy(target) {
var h = {
defineProperty: function (t, id) {
log.push("define " + id);
log.push("define", id);
return undefined;
},
has: function (t, id) {
log.push("has " + id);
log.push("has", id);
return id in t;
},
get: function (t, id) {
log.push("get " + id);
log.push("get", id);
return t[id];
},
set: function (t, id, v) {
log.push("set " + id);
log.push("set", id);
t[id] = v;
}
};
@ -30,23 +30,25 @@ function LoggingProxy(target) {
// but handler.set to set the length.
LoggingProxy.from = Array.from;
LoggingProxy.from([3, 4, 5]);
assertDeepEq(log, ["define 0", "define 1", "define 2", "set length"]);
assertDeepEq(log, ["define", "0", "define", "1", "define", "2", "set", "length"]);
// When the argument passed to Array.from is a Proxy, Array.from
// calls handler.get on it.
log = [];
assertDeepEq(Array.from(new LoggingProxy([3, 4, 5])), [3, 4, 5]);
assertDeepEq(log, ["get @@iterator",
"get length", "get 0", "get length", "get 1", "get length", "get 2",
"get length"]);
assertDeepEq(log, ["get", std_iterator,
"get", "length", "get", "0",
"get", "length", "get", "1",
"get", "length", "get", "2",
"get", "length"]);
// Array-like iteration only gets the length once.
log = [];
var arr = [5, 6, 7];
arr["@@iterator"] = undefined;
arr[std_iterator] = undefined;
assertDeepEq(Array.from(new LoggingProxy(arr)), [5, 6, 7]);
assertDeepEq(log, ["get @@iterator",
"get length", "get 0", "get 1", "get 2"]);
assertDeepEq(log, ["get", std_iterator,
"get", "length", "get", "0", "get", "1", "get", "2"]);
if (typeof reportCompare === 'function')
reportCompare(0, 0);

View File

@ -11,11 +11,11 @@ assertDeepEq(Array.from(gclef), [gclef]);
assertDeepEq(Array.from(gclef + " G"), [gclef, " ", "G"]);
// Array.from on a string calls the @@iterator method.
String.prototype["@@iterator"] = function* () { yield 1; yield 2; };
String.prototype[std_iterator] = function* () { yield 1; yield 2; };
assertDeepEq(Array.from("anything"), [1, 2]);
// If the iterator method is deleted, Strings are still arraylike.
delete String.prototype["@@iterator"];
delete String.prototype[std_iterator];
assertDeepEq(Array.from("works"), ['w', 'o', 'r', 'k', 's']);
assertDeepEq(Array.from(gclef), ['\uD834', '\uDD1E']);

View File

@ -17,8 +17,6 @@ function* g() { yield 1; }
var GeneratorFunctionPrototype = Object.getPrototypeOf(g);
var GeneratorFunction = GeneratorFunctionPrototype.constructor;
var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;
// FIXME: This should be a symbol.
var std_iterator = "@@iterator";
// A generator function should have the same set of properties as any
@ -66,7 +64,9 @@ function TestGeneratorObjectPrototype() {
assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype),
GeneratorObjectPrototype);
var expected_property_names = ["next", "throw", "constructor", std_iterator];
var expected_property_names = ["next", "throw", "constructor"];
if (!JS_HAS_SYMBOLS)
expected_property_names.push(std_iterator);
var found_property_names =
Object.getOwnPropertyNames(GeneratorObjectPrototype);

View File

@ -66,10 +66,8 @@ if (typeof Symbol === "function") {
assertEq(descs.hasOwnProperty(s1), true);
assertEq(descs.hasOwnProperty(s2), true);
assertEq(descs.hasOwnProperty(s3), false);
assertEq([].hasOwnProperty(Symbol.iterator), false);
if (!("@@iterator" in []))
throw new Error("Congratulations on implementing Symbol.iterator! Please update this test.");
assertEq(Array.prototype.hasOwnProperty(Symbol.iterator), false); // should be true
assertEq([].hasOwnProperty(std_iterator), false);
assertEq(Array.prototype.hasOwnProperty(std_iterator), true);
// Object.prototype.propertyIsEnumerable
assertEq(n.propertyIsEnumerable(s1), true);

View File

@ -26,7 +26,8 @@ function test()
var [a, b, [c0, c1]] = [x, x, x];
}
expect = 'TypeError: (intermediate value)[\'@@iterator\'](...).next(...).value is null';
var ITERATOR = JS_HAS_SYMBOLS ? "Symbol.iterator" : "'@@iterator'";
expect = `TypeError: (intermediate value)[${ITERATOR}](...).next(...).value is null`;
actual = 'No Error';
try
{

View File

@ -0,0 +1,28 @@
// The decompiler can handle the implicit call to @@iterator in a for-of loop.
var x;
function check(code) {
var s = "no exception thrown";
try {
eval(code);
} catch (exc) {
s = exc.message;
}
var ITERATOR = JS_HAS_SYMBOLS ? "Symbol.iterator" : "'@@iterator'";
assertEq(s, `x[${ITERATOR}] is not a function`);
}
x = {};
check("for (var v of x) throw fit;");
check("[...x]");
check("Math.hypot(...x)");
x[std_iterator] = "potato";
check("for (var v of x) throw fit;");
x[std_iterator] = {};
check("for (var v of x) throw fit;");
if (typeof reportCompare === "function")
reportCompare(0, 0, "ok");

View File

@ -876,3 +876,6 @@ function OptLevel( i ) {
cx.setOptimizationLevel(i);
}
/* end of Rhino functions */
var JS_HAS_SYMBOLS = typeof Symbol === "function";
var std_iterator = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";

View File

@ -247,7 +247,7 @@ const Class StarGeneratorObject::class_ = {
};
static const JSFunctionSpec star_generator_methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0),
JS_SELF_HOSTED_FN("next", "StarGeneratorNext", 1, 0),
JS_SELF_HOSTED_FN("throw", "StarGeneratorThrow", 1, 0),
JS_FS_END
@ -256,7 +256,7 @@ static const JSFunctionSpec star_generator_methods[] = {
#define JSPROP_ROPERM (JSPROP_READONLY | JSPROP_PERMANENT)
static const JSFunctionSpec legacy_generator_methods[] = {
JS_SELF_HOSTED_FN("@@iterator", "LegacyGeneratorIteratorShim", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "LegacyGeneratorIteratorShim", 0, 0),
// "send" is an alias for "next".
JS_SELF_HOSTED_FN("next", "LegacyGeneratorNext", 1, JSPROP_ROPERM),
JS_SELF_HOSTED_FN("send", "LegacyGeneratorNext", 1, JSPROP_ROPERM),

View File

@ -324,7 +324,7 @@ InitBareBuiltinCtor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey prot
GlobalObject::initSelfHostingBuiltins(JSContext *cx, Handle<GlobalObject*> global,
const JSFunctionSpec *builtins)
{
/* Define a top-level property 'undefined' with the undefined value. */
// Define a top-level property 'undefined' with the undefined value.
if (!JSObject::defineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY))
@ -332,6 +332,20 @@ GlobalObject::initSelfHostingBuiltins(JSContext *cx, Handle<GlobalObject*> globa
return false;
}
// Define a top-level property 'std_iterator' with the name of the method
// used by for-of loops to create an iterator.
RootedValue std_iterator(cx);
#ifdef JS_HAS_SYMBOLS
std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator));
#else
std_iterator.setString(cx->names().std_iterator);
#endif
if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator,
JSPROP_PERMANENT | JSPROP_READONLY))
{
return false;
}
return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&

View File

@ -1124,6 +1124,7 @@ HandleError(JSContext *cx, InterpreterRegs &regs)
#define PUSH_BOOLEAN(b) REGS.sp++->setBoolean(b)
#define PUSH_DOUBLE(d) REGS.sp++->setDouble(d)
#define PUSH_INT32(i) REGS.sp++->setInt32(i)
#define PUSH_SYMBOL(s) REGS.sp++->setSymbol(s)
#define PUSH_STRING(s) do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
#define PUSH_OBJECT(obj) do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
#define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
@ -1601,7 +1602,6 @@ CASE(EnableInterruptsPseudoOpcode)
/* Various 1-byte no-ops. */
CASE(JSOP_NOP)
CASE(JSOP_UNUSED2)
CASE(JSOP_UNUSED45)
CASE(JSOP_UNUSED46)
CASE(JSOP_UNUSED47)
CASE(JSOP_UNUSED48)
@ -2706,6 +2706,10 @@ CASE(JSOP_TOSTRING)
}
END_CASE(JSOP_TOSTRING)
CASE(JSOP_SYMBOL)
PUSH_SYMBOL(cx->wellKnownSymbols().get(GET_UINT8(REGS.pc)));
END_CASE(JSOP_SYMBOL)
CASE(JSOP_OBJECT)
{
RootedNativeObject &ref = rootNativeObject0;

View File

@ -416,7 +416,15 @@
*/ \
macro(JSOP_DUPAT, 44, "dupat", NULL, 4, 0, 1, JOF_UINT24) \
\
macro(JSOP_UNUSED45, 45, "unused45", NULL, 1, 0, 0, JOF_BYTE) \
/*
* Push a well-known symbol onto the operand stack.
* Category: Literals
* Type: Constants
* Operands: uint8_t n, the JS::SymbolCode of the symbol to use
* Stack: => symbol
*/ \
macro(JSOP_SYMBOL, 45, "symbol", NULL, 2, 0, 1, JOF_UINT8) \
\
macro(JSOP_UNUSED46, 46, "unused46", NULL, 1, 0, 0, JOF_BYTE) \
macro(JSOP_UNUSED47, 47, "unused47", NULL, 1, 0, 0, JOF_BYTE) \
macro(JSOP_UNUSED48, 48, "unused48", NULL, 1, 0, 0, JOF_BYTE) \

View File

@ -18,6 +18,12 @@
using namespace js;
using namespace js::gc;
#ifdef JS_HAS_SYMBOLS
#define STD_ITERATOR_ID SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)
#else
#define STD_ITERATOR_ID ::js::NameToId(cx->names().std_iterator)
#endif
bool
js::ForOfPIC::Chain::initialize(JSContext *cx)
{
@ -44,8 +50,8 @@ js::ForOfPIC::Chain::initialize(JSContext *cx)
// do set disabled_ now, and clear it later when we succeed.
disabled_ = true;
// Look up '@@iterator' on Array.prototype, ensure it's a slotful shape.
Shape *iterShape = arrayProto->lookup(cx, cx->names().std_iterator);
// Look up Array.prototype[@@iterator], ensure it's a slotful shape.
Shape *iterShape = arrayProto->lookup(cx, STD_ITERATOR_ID);
if (!iterShape || !iterShape->hasSlot() || !iterShape->hasDefaultGetter())
return true;
@ -143,8 +149,8 @@ js::ForOfPIC::Chain::tryOptimizeArray(JSContext *cx, HandleArrayObject array, bo
if (!isOptimizableArray(array))
return true;
// Ensure array doesn't define '@@iterator' directly.
if (array->lookup(cx, cx->names().std_iterator))
// Ensure array doesn't define @@iterator directly.
if (array->lookup(cx, STD_ITERATOR_ID))
return true;
// Good to optimize now, create stub to add.
@ -197,7 +203,7 @@ js::ForOfPIC::Chain::isArrayStateStillSane()
if (arrayProto_->lastProperty() != arrayProtoShape_)
return false;
// Ensure that Array.prototype['@@iterator'] contains the
// Ensure that Array.prototype[@@iterator] contains the
// canonical iterator function.
if (arrayProto_->getSlot(arrayProtoIteratorSlot_) != canonicalIteratorFunc_)
return false;

View File

@ -130,7 +130,7 @@ struct ForOfPIC
/*
* A ForOfPIC has only one kind of stub for now: one that holds the shape
* of an array object that does not override its '@@iterator' property.
* of an array object that does not override its @@iterator property.
*/
class Stub : public BaseStub
{
@ -164,8 +164,8 @@ struct ForOfPIC
* ArrayIterator.prototype's shape (arrayIteratorProtoShape_)
* To ensure that an ArrayIterator.prototype has not been modified.
*
* Array.prototype's slot number for '@@iterator' (arrayProtoIteratorSlot_)
* Array.prototype's canonical value for '@@iterator' (canonicalIteratorFunc_)
* Array.prototype's slot number for @@iterator (arrayProtoIteratorSlot_)
* Array.prototype's canonical value for @@iterator (canonicalIteratorFunc_)
* To quickly retreive and ensure that the iterator constructor
* stored in the slot has not changed.
*
@ -182,7 +182,7 @@ struct ForOfPIC
HeapPtrNativeObject arrayIteratorProto_;
// Shape of matching Array.prototype object, and slot containing
// the '@@iterator' for it, and the canonical value.
// the @@iterator for it, and the canonical value.
HeapPtrShape arrayProtoShape_;
uint32_t arrayProtoIteratorSlot_;
HeapValue canonicalIteratorFunc_;

View File

@ -406,6 +406,10 @@ struct JSAtomState
#define PROPERTYNAME_FIELD(name, code, init, clasp) js::ImmutablePropertyNamePtr name;
JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
#undef PROPERTYNAME_FIELD
js::ImmutablePropertyNamePtr *wellKnownSymbolDescriptions() {
return &Symbol_iterator;
}
};
namespace js {

View File

@ -1501,6 +1501,12 @@ CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp)
if (!clone)
return false;
vp.setString(clone);
} else if (selfHostedValue.isSymbol()) {
// Well-known symbols are shared.
JS::Symbol *sym = selfHostedValue.toSymbol();
MOZ_ASSERT(sym->isWellKnownSymbol());
MOZ_ASSERT(cx->wellKnownSymbols().get(size_t(sym->code())) == sym);
vp.set(selfHostedValue);
} else {
MOZ_CRASH("Self-hosting CloneValue can't clone given value.");
}

View File

@ -760,7 +760,7 @@ TypedArrayObject::subarray(JSContext *cx, unsigned argc, Value *vp)
/* static */ const JSFunctionSpec
TypedArrayObject::protoFunctions[] = {
JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0, 0),
JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0, 0), \
JS_FN("subarray", TypedArrayObject::subarray, 2, 0),
JS_FN("set", TypedArrayObject::set, 2, 0),
JS_FN("copyWithin", TypedArrayObject::copyWithin, 2, 0),

View File

@ -27,8 +27,21 @@ namespace js {
* this wiki page:
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*
* === GREETINGS, FELLOW SUBTRAHEND INCREMENTER! ===
* For the time being, please increment the subtrahend by 2 each time it
* changes, because we have two flavors of bytecode: with JSOP_SYMBOL (in
* Nightly) and without (all others). FIXME: Bug 1066322 - Enable ES6 symbols
* in all builds.
*/
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 188);
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 190;
static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND
#ifdef JS_HAS_SYMBOLS
+ 1
#endif
));
class XDRBuffer {
public:

View File

@ -146,6 +146,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
var isNightlyBuild = version.endsWith("a1");
var isReleaseBuild = !version.contains("a");
const jsHasSymbols = typeof Symbol === "function";
const kIteratorSymbol = jsHasSymbols ? Symbol.iterator : "@@iterator";
var gPrototypeProperties = {};
gPrototypeProperties['Date'] =
["getTime", "getTimezoneOffset", "getYear", "getFullYear", "getUTCFullYear",
@ -168,7 +169,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
["length", "toSource", "toString", "toLocaleString", "join", "reverse", "sort", "push",
"pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf",
"forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find",
"findIndex", "copyWithin", "fill", "@@iterator", "entries", "keys", "constructor"];
"findIndex", "copyWithin", "fill", kIteratorSymbol, "entries", "keys", "constructor"];
if (isNightlyBuild) {
let pjsMethods = ['mapPar', 'reducePar', 'scanPar', 'scatterPar', 'filterPar'];
gPrototypeProperties['Array'] = gPrototypeProperties['Array'].concat(pjsMethods);
@ -177,7 +178,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
gPrototypeProperties[c] = ["constructor", "BYTES_PER_ELEMENT"];
}
gPrototypeProperties['TypedArray'] =
["length", "buffer", "byteLength", "byteOffset", "@@iterator", "subarray",
["length", "buffer", "byteLength", "byteOffset", kIteratorSymbol, "subarray",
"set", "copyWithin"];
for (var c of errorObjectClasses) {
@ -500,10 +501,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
var typedArrayProto = Object.getPrototypeOf(Int8Array.prototype);
gPrototypeProperties['TypedArray'] =
["length", "buffer", "byteLength", "byteOffset", "@@iterator", "subarray",
"set", "copyWithin"];
var desiredInheritedProps = Object.getOwnPropertyNames(typedArrayProto).sort();
var inheritedProps =
filterOut(desiredInheritedProps, ["BYTES_PER_ELEMENT", "constructor"]);

View File

@ -252,24 +252,14 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
PR_INIT_CLIST(&mDOMMediaQueryLists);
}
nsPresContext::~nsPresContext()
void
nsPresContext::Destroy()
{
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
SetShell(nullptr);
NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
"must not have media query lists left");
// Disconnect the refresh driver *after* the transition manager, which
// needs it.
if (mRefreshDriver && mRefreshDriver->PresContext() == this) {
mRefreshDriver->Disconnect();
}
if (mEventManager) {
// unclear if these are needed, but can't hurt
mEventManager->NotifyDestroyPresContext(this);
mEventManager->SetPresContext(nullptr);
mEventManager = nullptr;
}
if (mPrefChangedTimer)
@ -321,6 +311,24 @@ nsPresContext::~nsPresContext()
Preferences::UnregisterCallback(nsPresContext::PrefChangedCallback,
"nglayout.debug.paint_flashing_chrome",
this);
// Disconnect the refresh driver *after* the transition manager, which
// needs it.
if (mRefreshDriver && mRefreshDriver->PresContext() == this) {
mRefreshDriver->Disconnect();
mRefreshDriver = nullptr;
}
}
nsPresContext::~nsPresContext()
{
NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
SetShell(nullptr);
NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
"must not have media query lists left");
Destroy();
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext)
@ -368,13 +376,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeviceContext); // worth bothering?
if (tmp->mEventManager) {
// unclear if these are needed, but can't hurt
tmp->mEventManager->NotifyDestroyPresContext(tmp);
tmp->mEventManager->SetPresContext(nullptr);
tmp->mEventManager = nullptr;
}
// We own only the items in mDOMMediaQueryLists that have listeners;
// this reference is managed by their AddListener and RemoveListener
// methods.
@ -387,15 +388,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
}
// NS_RELEASE(tmp->mLanguage); // an atom
// NS_IMPL_CYCLE_COLLECTION_UNLINK(mTheme); // a service
// NS_IMPL_CYCLE_COLLECTION_UNLINK(mLangService); // a service
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrintSettings);
if (tmp->mPrefChangedTimer)
{
tmp->mPrefChangedTimer->Cancel();
tmp->mPrefChangedTimer = nullptr;
}
tmp->Destroy();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

View File

@ -1172,6 +1172,9 @@ public:
#endif
protected:
// May be called multiple times (unlink, destructor)
void Destroy();
void InvalidatePaintedLayers();
void AppUnitsPerDevPixelChanged();

View File

@ -2956,11 +2956,11 @@ PropertyProvider::ComputeJustifiableCharacters(int32_t aOffset, int32_t aLength)
run(mStart, nsSkipCharsRunIterator::LENGTH_INCLUDES_SKIPPED, aLength);
run.SetOriginalOffset(aOffset);
uint32_t justifiableChars = 0;
bool isCJK = IsChineseOrJapanese(mFrame);
bool isCJ = IsChineseOrJapanese(mFrame);
while (run.NextRun()) {
for (int32_t i = 0; i < run.GetRunLength(); ++i) {
justifiableChars +=
IsJustifiableCharacter(mFrag, run.GetOriginalOffset() + i, isCJK);
IsJustifiableCharacter(mFrag, run.GetOriginalOffset() + i, isCJ);
}
}
return justifiableChars;
@ -3083,7 +3083,7 @@ PropertyProvider::GetSpacingInternal(uint32_t aStart, uint32_t aLength,
gfxFloat halfJustificationSpace = mJustificationSpacing/2;
// Scan non-skipped characters and adjust justifiable chars, adding
// justification space on either side of the cluster
bool isCJK = IsChineseOrJapanese(mFrame);
bool isCJ = IsChineseOrJapanese(mFrame);
gfxSkipCharsIterator justificationStart(mStart), justificationEnd(mStart);
FindJustificationRange(&justificationStart, &justificationEnd);
@ -3094,7 +3094,7 @@ PropertyProvider::GetSpacingInternal(uint32_t aStart, uint32_t aLength,
int32_t runOriginalOffset = run.GetOriginalOffset();
for (int32_t i = 0; i < run.GetRunLength(); ++i) {
int32_t iterOriginalOffset = runOriginalOffset + i;
if (IsJustifiableCharacter(mFrag, iterOriginalOffset, isCJK)) {
if (IsJustifiableCharacter(mFrag, iterOriginalOffset, isCJ)) {
iter.SetOriginalOffset(iterOriginalOffset);
FindClusterStart(mTextRun, runOriginalOffset, &iter);
uint32_t clusterFirstChar = iter.GetSkippedOffset();
@ -8478,13 +8478,13 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC)
// Check if any character in the last cluster is justifiable
PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength,
nullptr, 0, nsTextFrame::eInflated);
bool isCJK = IsChineseOrJapanese(this);
bool isCJ = IsChineseOrJapanese(this);
gfxSkipCharsIterator justificationStart(start), justificationEnd(trimmedEndIter);
provider.FindJustificationRange(&justificationStart, &justificationEnd);
for (int32_t i = justificationEnd.GetOriginalOffset();
i < trimmed.GetEnd(); ++i) {
if (IsJustifiableCharacter(frag, i, isCJK)) {
if (IsJustifiableCharacter(frag, i, isCJ)) {
result.mLastCharIsJustifiable = true;
}
}

View File

@ -148,5 +148,5 @@ fuzzy-if(d2d,47,400) == linear-onestopposition-1.html linear-onestopposition-1-r
== bug-916535-background-repeat-linear.html bug-916535-background-repeat-linear-ref.html
fuzzy(1,800000) == large-gradient-1.html large-gradient-1-ref.html
== large-gradient-2.html large-gradient-2-ref.html
fuzzy(1,800000) == large-gradient-3.html large-gradient-3-ref.html
== large-gradient-4.html large-gradient-4-ref.html
fails-if(browserIsRemote&&!B2G) fuzzy(1,800000) == large-gradient-3.html large-gradient-3-ref.html
fails-if(browserIsRemote&&!B2G) == large-gradient-4.html large-gradient-4-ref.html

View File

@ -248,10 +248,10 @@ include outline/reftest.list
include object/reftest.list
# ogg-video/
include ogg-video/reftest.list
skip-if(!B2G&&browserIsRemote) include ogg-video/reftest.list
# webm-video/
include webm-video/reftest.list
skip-if(!B2G&&browserIsRemote) include webm-video/reftest.list
# parser/
include ../../parser/htmlparser/tests/reftest/reftest.list

View File

@ -37,6 +37,7 @@ generated-files = css_properties.js
[test_animations.html]
skip-if = toolkit == 'android'
[test_animations_omta.html]
skip-if = buildapp == 'mulet'
[test_animations_omta_start.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1041017
[test_animations_pausing.html]

View File

@ -27,7 +27,7 @@ namespace net {
* @see nsICookiePermission
*/
sync protocol PCookieService
prio(normal upto urgent) sync protocol PCookieService
{
manager PNecko;
@ -60,10 +60,10 @@ parent:
*
* @return the resulting cookie string.
*/
sync GetCookieString(URIParams host,
bool isForeign,
bool fromHttp,
SerializedLoadContext loadContext)
prio(urgent) sync GetCookieString(URIParams host,
bool isForeign,
bool fromHttp,
SerializedLoadContext loadContext)
returns (nsCString result);
/*
@ -95,12 +95,12 @@ parent:
* @see nsICookieService.setCookieStringFromHttp
* @see mozIThirdPartyUtil.isThirdPartyChannel
*/
SetCookieString(URIParams host,
bool isForeign,
nsCString cookieString,
nsCString serverTime,
bool fromHttp,
SerializedLoadContext loadContext);
prio(urgent) async SetCookieString(URIParams host,
bool isForeign,
nsCString cookieString,
nsCString serverTime,
bool fromHttp,
SerializedLoadContext loadContext);
__delete__();
};

View File

@ -35,7 +35,7 @@ namespace mozilla {
namespace net {
//-------------------------------------------------------------------
sync protocol PNecko
prio(normal upto urgent) sync protocol PNecko
{
manager PContent;
manages PHttpChannel;
@ -55,7 +55,7 @@ sync protocol PNecko
parent:
__delete__();
PCookieService();
prio(urgent) async PCookieService();
PHttpChannel(PBrowserOrId browser,
SerializedLoadContext loadContext,
HttpChannelCreationArgs args);

View File

@ -18,7 +18,7 @@ interface nsIX509Cert;
* {host:port, cert-fingerprint, allowed-overrides}
* that the user wants to accept without further warnings.
*/
[scriptable, uuid(31738d2a-77d3-4359-84c9-4be2f38fb8c5)]
[scriptable, uuid(be019e47-22fc-4355-9f16-9ab047d6742d)]
interface nsICertOverrideService : nsISupports {
/**
@ -108,15 +108,6 @@ interface nsICertOverrideService : nsISupports {
void clearValidityOverride(in ACString aHostName,
in int32_t aPort);
/**
* Obtain the full list of hostname:port for which overrides are known.
*
* @param aCount The number of host:port entries returned
* @param aHostsWithPortsArray The array of host:port entries returned
*/
void getAllOverrideHostsWithPorts(out uint32_t aCount,
[array, size_is(aCount)] out wstring aHostsWithPortsArray);
/**
* Is the given cert used in rules?
*

View File

@ -6,29 +6,24 @@
#include "nsCertOverrideService.h"
#include "pkix/pkixtypes.h"
#include "nsIX509Cert.h"
#include "NSSCertDBTrustDomain.h"
#include "nsNSSCertificate.h"
#include "nsNSSCertHelper.h"
#include "nsCRT.h"
#include "ScopedNSSTypes.h"
#include "SharedSSLState.h"
#include "mozilla/Telemetry.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsStreamUtils.h"
#include "nsNetUtil.h"
#include "nsCRT.h"
#include "nsILineInputStream.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsIX509Cert.h"
#include "nsNSSCertHelper.h"
#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsNetUtil.h"
#include "nsPromiseFlatString.h"
#include "nsThreadUtils.h"
#include "nsStreamUtils.h"
#include "nsStringBuffer.h"
#include "ScopedNSSTypes.h"
#include "SharedSSLState.h"
#include "nspr.h"
#include "pk11pub.h"
#include "certdb.h"
#include "sechash.h"
#include "nsThreadUtils.h"
#include "ssl.h" // For SSL_ClearSessionCache
using namespace mozilla;
@ -106,18 +101,11 @@ nsCertOverrideService::Init()
return NS_ERROR_NOT_SAME_THREAD;
}
// Note that the names of these variables would seem to indicate that at one
// point another hash algorithm was used and is still supported for backwards
// compatibility. This is not the case. It has always been SHA256.
mOidTagForStoringNewHashes = SEC_OID_SHA256;
SECOidData *od = SECOID_FindOIDByTag(mOidTagForStoringNewHashes);
if (!od)
return NS_ERROR_FAILURE;
char *dotted_oid = CERT_GetOidString(&od->oid);
if (!dotted_oid)
return NS_ERROR_FAILURE;
mDottedOidForStoringNewHashes = dotted_oid;
PR_smprintf_free(dotted_oid);
mDottedOidForStoringNewHashes.Assign("OID.2.16.840.1.101.3.4.2.1");
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
@ -172,7 +160,7 @@ nsCertOverrideService::Observe(nsISupports *,
mSettingsFile = nullptr;
}
Read();
CountPermanentOverrideTelemetry();
}
return NS_OK;
@ -398,42 +386,6 @@ GetCertFingerprintByOidTag(nsIX509Cert *aCert,
return GetCertFingerprintByOidTag(nsscert.get(), aOidTag, fp);
}
static nsresult
GetCertFingerprintByDottedOidString(CERTCertificate* nsscert,
const nsCString &dottedOid,
nsCString &fp)
{
SECItem oid;
oid.data = nullptr;
oid.len = 0;
SECStatus srv = SEC_StringToOID(nullptr, &oid,
dottedOid.get(), dottedOid.Length());
if (srv != SECSuccess)
return NS_ERROR_FAILURE;
SECOidTag oid_tag = SECOID_FindOIDTag(&oid);
SECITEM_FreeItem(&oid, false);
if (oid_tag == SEC_OID_UNKNOWN)
return NS_ERROR_FAILURE;
return GetCertFingerprintByOidTag(nsscert, oid_tag, fp);
}
static nsresult
GetCertFingerprintByDottedOidString(nsIX509Cert *aCert,
const nsCString &dottedOid,
nsCString &fp)
{
ScopedCERTCertificate nsscert(aCert->GetCert());
if (!nsscert) {
return NS_ERROR_FAILURE;
}
return GetCertFingerprintByDottedOidString(nsscert.get(), dottedOid, fp);
}
NS_IMETHODIMP
nsCertOverrideService::RememberValidityOverride(const nsACString& aHostName,
int32_t aPort,
@ -546,14 +498,17 @@ nsCertOverrideService::HasMatchingOverride(const nsACString & aHostName, int32_t
nsAutoCString fpStr;
nsresult rv;
// This code was originally written in a way that suggested that other hash
// algorithms are supported for backwards compatibility. However, this was
// always unnecessary, because only SHA256 has ever been used here.
if (settings.mFingerprintAlgOID.Equals(mDottedOidForStoringNewHashes)) {
rv = GetCertFingerprintByOidTag(aCert, mOidTagForStoringNewHashes, fpStr);
if (NS_FAILED(rv)) {
return rv;
}
} else {
return NS_ERROR_UNEXPECTED;
}
else {
rv = GetCertFingerprintByDottedOidString(aCert, settings.mFingerprintAlgOID, fpStr);
}
if (NS_FAILED(rv))
return rv;
*_retval = settings.mFingerprint.Equals(fpStr);
return NS_OK;
@ -649,15 +604,37 @@ nsCertOverrideService::ClearValidityOverride(const nsACString & aHostName, int32
mSettingsTable.RemoveEntry(hostPort.get());
Write();
}
SSL_ClearSessionCache();
if (EnsureNSSInitialized(nssEnsure)) {
SSL_ClearSessionCache();
} else {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
NS_IMETHODIMP
nsCertOverrideService::GetAllOverrideHostsWithPorts(uint32_t *aCount,
char16_t ***aHostsWithPortsArray)
static PLDHashOperator
CountPermanentEntriesCallback(nsCertOverrideEntry* aEntry, void* aArg)
{
return NS_ERROR_NOT_IMPLEMENTED;
uint32_t* overrideCount = reinterpret_cast<uint32_t*>(aArg);
if (aEntry && !aEntry->mSettings.mIsTemporary) {
*overrideCount = *overrideCount + 1;
return PL_DHASH_NEXT;
}
return PL_DHASH_NEXT;
}
void
nsCertOverrideService::CountPermanentOverrideTelemetry()
{
ReentrantMonitorAutoEnter lock(monitor);
uint32_t overrideCount = 0;
mSettingsTable.EnumerateEntries(CountPermanentEntriesCallback,
&overrideCount);
Telemetry::Accumulate(Telemetry::SSL_PERMANENT_CERT_ERROR_OVERRIDES,
overrideCount);
}
static bool
@ -738,15 +715,11 @@ FindMatchingCertCallback(nsCertOverrideEntry *aEntry,
if (still_ok && matchesDBKey(cai->cert, settings.mDBKey.get())) {
nsAutoCString cert_fingerprint;
nsresult rv;
nsresult rv = NS_ERROR_UNEXPECTED;
if (settings.mFingerprintAlgOID.Equals(cai->mDottedOidForStoringNewHashes)) {
rv = GetCertFingerprintByOidTag(cai->cert,
cai->mOidTagForStoringNewHashes, cert_fingerprint);
}
else {
rv = GetCertFingerprintByDottedOidString(cai->cert,
settings.mFingerprintAlgOID, cert_fingerprint);
}
if (NS_SUCCEEDED(rv) &&
settings.mFingerprint.Equals(cert_fingerprint)) {
cai->counter++;
@ -808,15 +781,11 @@ EnumerateCertOverridesCallback(nsCertOverrideEntry *aEntry,
else {
if (matchesDBKey(capac->cert, settings.mDBKey.get())) {
nsAutoCString cert_fingerprint;
nsresult rv;
nsresult rv = NS_ERROR_UNEXPECTED;
if (settings.mFingerprintAlgOID.Equals(capac->mDottedOidForStoringNewHashes)) {
rv = GetCertFingerprintByOidTag(capac->cert,
capac->mOidTagForStoringNewHashes, cert_fingerprint);
}
else {
rv = GetCertFingerprintByDottedOidString(capac->cert,
settings.mFingerprintAlgOID, cert_fingerprint);
}
if (NS_SUCCEEDED(rv) &&
settings.mFingerprint.Equals(cert_fingerprint)) {
(*capac->enumerator)(settings, capac->userdata);
@ -860,4 +829,3 @@ nsCertOverrideService::GetHostWithPort(const nsACString & aHostName, int32_t aPo
}
_retval.Assign(hostPort);
}

View File

@ -165,6 +165,8 @@ protected:
SECOidTag mOidTagForStoringNewHashes;
nsCString mDottedOidForStoringNewHashes;
void CountPermanentOverrideTelemetry();
void RemoveAllFromMemory();
nsresult Read();
nsresult Write();

View File

@ -199,7 +199,6 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsStreamCipher)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObject)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsKeyObjectFactory)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsDataSignatureVerifier)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nssEnsure, nsCertOverrideService, Init)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsure, nsRandomGenerator)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, nsSSLStatus)
NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, TransportSecurityInfo)
@ -207,6 +206,7 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(nssEnsureOnChromeOnly, TransportSecurityInfo)
typedef mozilla::psm::NSSErrorsService NSSErrorsService;
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NSSErrorsService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNSSVersion)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCertOverrideService, Init)
NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);

View File

@ -189,14 +189,6 @@
"VeriSign Universal Root Certification Authority",
"XRamp Global CA Root"
]
},
{
"name": "facebook",
"sha256_hashes": [
"Verisign Class 3 Public Primary Certification Authority - G3",
"DigiCert High Assurance EV Root CA",
"DigiCert ECC Secure Server CA"
]
}
],
@ -234,10 +226,7 @@
// twitterCDN. More specific rules take precedence because we search for
// exact domain name first.
{ "name": "twitter.com", "include_subdomains": true,
"pins": "twitterCDN", "test_mode": false },
// Facebook (not pinned by Chrome)
{ "name": "facebook.com", "include_subdomains": true,
"pins": "facebook", "test_mode": true }
"pins": "twitterCDN", "test_mode": false }
],
"extra_certificates": [

View File

@ -11,6 +11,7 @@
enum MacSandboxType {
MacSandboxType_Default = 0,
MacSandboxType_Plugin,
MacSandboxType_Content,
MacSandboxType_Invalid
};

Some files were not shown because too many files have changed in this diff Show More