merge mozilla-inbound to mozilla-central. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-11-09 00:00:16 +02:00
commit a353221537
166 changed files with 1510 additions and 1556 deletions

View file

@ -4,7 +4,28 @@ const TEST_URL = "data:text/html,a test page";
const DRAG_URL = "http://www.example.com/";
const DRAG_FORBIDDEN_URL = "chrome://browser/content/aboutDialog.xul";
const DRAG_TEXT = "Firefox is awesome";
const DRAG_TEXT_URL = "http://example.com/?q=Firefox+is+awesome";
const DRAG_WORD = "Firefox";
const DRAG_WORD_URL = "http://example.com/?q=Firefox";
registerCleanupFunction(async function cleanup() {
while (gBrowser.tabs.length > 1) {
await BrowserTestUtils.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
}
Services.search.currentEngine = originalEngine;
let engine = Services.search.getEngineByName("MozSearch");
Services.search.removeEngine(engine);
});
let originalEngine;
add_task(async function test_setup() {
// Stop search-engine loads from hitting the network
Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET",
"http://example.com/?q={searchTerms}");
let engine = Services.search.getEngineByName("MozSearch");
originalEngine = Services.search.currentEngine;
Services.search.currentEngine = engine;
});
add_task(async function checkDragURL() {
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
@ -26,13 +47,15 @@ add_task(async function checkDragForbiddenURL() {
});
add_task(async function checkDragText() {
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
let promiseLoad = BrowserTestUtils.browserLoaded(browser, false, DRAG_TEXT_URL);
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
[[{type: "text/plain", data: DRAG_TEXT}]], "copy", window);
is(gURLBar.value, DRAG_TEXT, "Dragging normal text should replace the URL bar value");
await promiseLoad;
promiseLoad = BrowserTestUtils.browserLoaded(browser, false, DRAG_WORD_URL);
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
[[{type: "text/plain", data: DRAG_WORD}]], "copy", window);
is(gURLBar.value, DRAG_WORD, "Dragging a single word should replace the URL bar value");
await promiseLoad;
});
});

View file

@ -951,12 +951,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
this.value = droppedItem instanceof URL ? droppedItem.href : droppedItem;
SetPageProxyState("invalid");
this.focus();
if (droppedItem instanceof URL) {
this.handleCommand();
// Force not showing the dropped URI immediately.
gBrowser.userTypedValue = null;
URLBarSetURI();
}
this.handleCommand();
// Force not showing the dropped URI immediately.
gBrowser.userTypedValue = null;
URLBarSetURI();
}
]]></body>
</method>

View file

@ -315,7 +315,6 @@
@RESPATH@/components/txtsvc.xpt
@RESPATH@/components/txmgr.xpt
@RESPATH@/components/uconv.xpt
@RESPATH@/components/unicharutil.xpt
@RESPATH@/components/update.xpt
@RESPATH@/components/uriloader.xpt
@RESPATH@/components/urlformatter.xpt

View file

@ -69,6 +69,7 @@ included_inclnames_to_ignore = set([
'jscustomallocator.h', # provided by embedders; allowed to be missing
'js-config.h', # generated in $OBJDIR
'fdlibm.h', # fdlibm
'mozmemory.h', # included without a path
'pratom.h', # NSPR
'prcvar.h', # NSPR
'prerror.h', # NSPR

View file

@ -13,6 +13,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "nsCOMPtr.h"
#include "nsIURI.h"
class nsPresContext;
class nsIPresShell;
namespace mozilla {

View file

@ -5,6 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AbortSignal.h"
#include "AbortController.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/AbortSignalBinding.h"

View file

@ -6,6 +6,8 @@
#include "mozilla/dom/AnimationEffectReadOnly.h"
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h"
#include "mozilla/dom/Animation.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/FloatingPoint.h"

View file

@ -7,6 +7,7 @@
#include "mozilla/dom/CSSPseudoElement.h"
#include "mozilla/dom/CSSPseudoElementBinding.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeEffectBinding.h"
#include "mozilla/AnimationComparator.h"
namespace mozilla {

View file

@ -13,6 +13,7 @@
#include "mozilla/BasePrincipal.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/IdleDeadline.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
#include "nsThreadUtils.h"

View file

@ -9,6 +9,7 @@
#include "mozilla/CycleCollectedJSContext.h"
#include "mozilla/dom/CustomElementRegistryBinding.h"
#include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WebComponentsBinding.h"
#include "mozilla/dom/DocGroup.h"
#include "nsHTMLTags.h"

View file

@ -8,6 +8,7 @@
#include "mozilla/dom/DOMErrorBinding.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/UseCounter.h"
#include "nsIDocument.h"
#include "nsPIDOMWindow.h"
namespace mozilla {

View file

@ -7736,6 +7736,31 @@ nsIDocument::SetDir(const nsAString& aDirection)
}
}
/* static */
bool
nsIDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData)
{
NS_PRECONDITION(aElement, "Must have element to work with!");
if (!aElement->HasName()) {
return false;
}
nsString* elementName = static_cast<nsString*>(aData);
return
aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
*elementName, eCaseMatters);
}
/* static */
void*
nsIDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
{
return const_cast<nsString*>(aName);
}
NS_IMETHODIMP
nsDocument::GetInputEncoding(nsAString& aInputEncoding)
{

View file

@ -57,6 +57,7 @@ class ElementCreationOptionsOrString;
class gfxUserFontSet;
class imgIRequest;
class nsBindingManager;
class nsCachableElementsByNameNodeList;
class nsIDocShell;
class nsDocShell;
class nsDOMNavigationTiming;
@ -2941,6 +2942,14 @@ public:
virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) = 0;
void GetDir(nsAString& aDirection) const;
void SetDir(const nsAString& aDirection);
already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName)
{
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
MatchNameAttribute,
nullptr,
UseExistingNameString,
aName);
}
nsPIDOMWindowOuter* GetDefaultView() const
{
return GetWindow();
@ -3321,6 +3330,12 @@ protected:
// Helper for GetScrollingElement/IsScrollingElement.
bool IsPotentiallyScrollable(mozilla::dom::HTMLBodyElement* aBody);
// Helpers for GetElementsByName.
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
int32_t aNamespaceID,
nsAtom* aAtom, void* aData);
static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
nsCString mReferrer;
nsString mLastModified;

View file

@ -6,14 +6,18 @@
#include "WebIDLGlobalNameHash.h"
#include "js/GCAPI.h"
#include "jswrapper.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/DOMJSProxyHandler.h"
#include "mozilla/dom/PrototypeList.h"
#include "mozilla/dom/RegisterBindings.h"
#include "nsGlobalWindow.h"
#include "nsIMemoryReporter.h"
#include "nsTHashtable.h"
#include "WrapperFactory.h"
namespace mozilla {
namespace dom {

View file

@ -12,6 +12,7 @@
#include "jsprf.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"

View file

@ -14,6 +14,8 @@
#include "jsapi.h"
#include "js/RootingAPI.h"
#include "nsCOMArray.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIScriptError.h"
#include "nsString.h"

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var canvas = document.createElement("canvas");
canvas.setAttribute("width", "7623");
canvas.setAttribute("height", "14064");
canvas.getContext("experimental-webgl");
}
</script>
</head>
<body onload="boom();"></body>
</html>

View file

@ -16,6 +16,7 @@ skip-if(Android) load 780392-1.html
skip-if(Android) skip-if(gtkWidget&&isDebugBuild) load 789933-1.html # bug 1155252 for linux
load 794463-1.html
load 802926-1.html
skip-if(winWidget&&isDebugBuild&&/^Windows\x20NT\x206\.1/.test(http.oscpu)) load 844280.html # intermittent OOMs on Win7 debug
load 896047-1.html
load 916128-1.html
load 934939-1.html

View file

@ -6,6 +6,8 @@
#include "ClientState.h"
#include "mozilla/dom/ClientIPCTypes.h"
namespace mozilla {
namespace dom {

View file

@ -7,6 +7,9 @@
#ifndef _mozilla_dom_ClientState_h
#define _mozilla_dom_ClientState_h
#include "mozilla/dom/DocumentBinding.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {

View file

@ -6,9 +6,11 @@
#include "mozilla/dom/WebCryptoThreadPool.h"
#include "MainThreadUtils.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsNSSComponent.h"
#include "nsXPCOMCIDInternal.h"
#include "nsXPCOMPrivate.h"
#include "nsIObserverService.h"

View file

@ -7,6 +7,8 @@
#ifndef mozilla_dom_WebCryptoThreadPool_h
#define mozilla_dom_WebCryptoThreadPool_h
#include "mozilla/Mutex.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIThreadPool.h"

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
function f() {
document.removeEventListener("DOMSubtreeModified", f, true);
document.documentElement.setAttributeNS(null, "contenteditable", "false");
}
document.addEventListener("DOMSubtreeModified", f, true);
document.documentElement.contentEditable = "true";
}
</script>
</head>
<body onload="boom();"></body>
</html>

View file

@ -53,6 +53,7 @@ load 682460.html
load 738744.xhtml
load 741218.json
load 741250.xhtml
load 768344.html
load 795221-1.html
load 795221-2.html
load 795221-3.html

View file

@ -2063,38 +2063,6 @@ nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
WriteCommon(cx, aText, true, rv);
}
bool
nsHTMLDocument::MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData)
{
NS_PRECONDITION(aElement, "Must have element to work with!");
if (!aElement->HasName()) {
return false;
}
nsString* elementName = static_cast<nsString*>(aData);
return
aElement->GetNameSpaceID() == kNameSpaceID_XHTML &&
aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
*elementName, eCaseMatters);
}
/* static */
void*
nsHTMLDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
{
return const_cast<nsString*>(aName);
}
NS_IMETHODIMP
nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
nsIDOMNodeList** aReturn)
{
*aReturn = GetElementsByName(aElementName).take();
return NS_OK;
}
void
nsHTMLDocument::AddedForm()
{

View file

@ -193,14 +193,6 @@ public:
return nsHTMLDocument::GetForms();
}
nsIHTMLCollection* Scripts();
already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
{
return GetFuncStringContentList<nsCachableElementsByNameNodeList>(this,
MatchNameAttribute,
nullptr,
UseExistingNameString,
aName);
}
already_AddRefed<nsIDocument> Open(JSContext* cx,
const nsAString& aType,
const nsAString& aReplace,
@ -280,10 +272,6 @@ protected:
nsAtom* aAtom, void* aData);
static bool MatchAnchors(mozilla::dom::Element* aElement, int32_t aNamespaceID,
nsAtom* aAtom, void* aData);
static bool MatchNameAttribute(mozilla::dom::Element* aElement,
int32_t aNamespaceID,
nsAtom* aAtom, void* aData);
static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
static void DocumentWriteTerminationFunc(nsISupports *aRef);

View file

@ -29,7 +29,6 @@ interface nsIDOMHTMLDocument : nsIDOMDocument
readonly attribute nsIDOMHTMLCollection links;
readonly attribute nsIDOMHTMLCollection forms;
readonly attribute nsIDOMHTMLCollection scripts;
nsIDOMNodeList getElementsByName(in DOMString elementName);
// If aContentType is not something supported by nsHTMLDocument and
// the HTML content sink, trying to write to the document will

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function boom()
{
vid.setMediaKeys(null);
vid.fastSeek(111);
}
</script>
</head>
<body onload="boom();">
<video id="vid" src="../../../../layout/reftests/webm-video/frames.webm"></video>
</body>
</html>

View file

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Media test: Negative duration.</title>
</head>
<body>
<video id="v" controls src="1389304.mp4">
</video>
<p id="msg"></p>
<script type="text/javascript">
function log(x) {
msg.innerHTML = x + "<br>";
}
v.play();
v.onended = function() {
log("endded!");
let seekable = v.seekable;
for (let i = 0; i < seekable.length; ++i) {
let start = seekable.start(i);
let end = seekable.end(i);
log(`[${i}]: start=${start} end=${end}`);
}
}
</script>
</body>
</html>

Binary file not shown.

View file

@ -86,6 +86,7 @@ load 1158427.html
load 1185176.html
load 1185192.html
load 1257700.html
load 1267263.html
load 1270303.html
load 1304948.html
load 1319486.html
@ -93,6 +94,7 @@ load 1368490.html
load 1291702.html
load 1378826.html
load 1384248.html
load 1389304.html
load 1393272.webm
load disconnect-wrong-destination.html
load analyser-channels-1.html

View file

@ -123,7 +123,8 @@ partial interface Document {
//(HTML only)readonly attribute HTMLCollection links;
//(HTML only)readonly attribute HTMLCollection forms;
//(HTML only)readonly attribute HTMLCollection scripts;
//(HTML only)NodeList getElementsByName(DOMString elementName);
[Pure]
NodeList getElementsByName(DOMString elementName);
//(Not implemented)readonly attribute DOMElementMap cssElementMap;
// dynamic markup insertion

View file

@ -29,7 +29,6 @@ interface HTMLDocument : Document {
readonly attribute HTMLCollection forms;
[Pure]
readonly attribute HTMLCollection scripts;
NodeList getElementsByName(DOMString elementName);
// dynamic markup insertion
[CEReactions, Throws]

View file

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html style="-moz-perspective: 1000px; -moz-transform: skewY(277deg); overflow: -moz-hidden-unscrollable;">
<body style="-moz-transform: skewY(127deg);">
<div style="height: 20px; background: lightgreen;"></div>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<script>
function boom()
{
var ctx = document.getElementById("c").getContext('2d');
ctx.stroke();
}
</script>
</head>
<body onload="boom();">
<canvas id="c" width="800" style="overflow: -moz-hidden-unscrollable; transform: skewY(30rad);"></canvas>
</body>
</html>

View file

@ -0,0 +1,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<body style="display: flex; position: absolute; transform: matrix3d(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); overflow-y: hidden;">
<video></video><video></video><video></video><track style="transform: rotate(45deg) scale(2, 1); position: absolute;"><video></video></track>
</body>
</html>

View file

@ -114,6 +114,8 @@ load 746849.html
load 746866.html
load 747132.html
load 747302.html
load 766422-1.html
load 766422-2.html
load 766452-1.html
load 766452-2.html
load 768079-1.html
@ -136,6 +138,7 @@ pref(layers.force-active,true) load 914457-1.html
load 944579.svg
load 944579.html
pref(security.fileuri.strict_origin_policy,false) load 950000.html
load 951893.xhtml
load 1011218.html
load 1034403-1.html
load 1056516.html

View file

@ -10,9 +10,6 @@
#include "nsJISx4051LineBreaker.h"
#include "nsSampleWordBreaker.h"
// unicharutil
#include "nsUnicodeNormalizer.h"
// string bundles (intl)
#include "nsStringBundleService.h"
#include "nsStringBundleTextOverride.h"
@ -28,13 +25,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSampleWordBreaker)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleService, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStringBundleTextOverride, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeNormalizer)
NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID);
NS_DEFINE_NAMED_CID(MOZ_OSPREFERENCES_CID);
NS_DEFINE_NAMED_CID(NS_LBRK_CID);
NS_DEFINE_NAMED_CID(NS_WBRK_CID);
NS_DEFINE_NAMED_CID(NS_UNICODE_NORMALIZER_CID);
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLESERVICE_CID);
NS_DEFINE_NAMED_CID(NS_STRINGBUNDLETEXTOVERRIDE_CID);
NS_DEFINE_NAMED_CID(NS_COLLATIONFACTORY_CID);
@ -46,7 +40,6 @@ static const mozilla::Module::CIDEntry kIntlCIDs[] = {
{ &kMOZ_OSPREFERENCES_CID, false, nullptr, mozilla::intl::OSPreferencesConstructor },
{ &kNS_LBRK_CID, false, nullptr, nsJISx4051LineBreakerConstructor },
{ &kNS_WBRK_CID, false, nullptr, nsSampleWordBreakerConstructor },
{ &kNS_UNICODE_NORMALIZER_CID, false, nullptr, nsUnicodeNormalizerConstructor },
{ &kNS_STRINGBUNDLESERVICE_CID, false, nullptr, nsStringBundleServiceConstructor },
{ &kNS_STRINGBUNDLETEXTOVERRIDE_CID, false, nullptr, nsStringBundleTextOverrideConstructor },
{ &kNS_COLLATIONFACTORY_CID, false, nullptr, nsCollationFactoryConstructor },
@ -60,7 +53,6 @@ static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
{ MOZ_OSPREFERENCES_CONTRACTID, &kMOZ_OSPREFERENCES_CID },
{ NS_LBRK_CONTRACTID, &kNS_LBRK_CID },
{ NS_WBRK_CONTRACTID, &kNS_WBRK_CID },
{ NS_UNICODE_NORMALIZER_CONTRACTID, &kNS_UNICODE_NORMALIZER_CID },
{ NS_STRINGBUNDLE_CONTRACTID, &kNS_STRINGBUNDLESERVICE_CID },
{ NS_STRINGBUNDLETEXTOVERRIDE_CONTRACTID, &kNS_STRINGBUNDLETEXTOVERRIDE_CID },
{ NS_COLLATIONFACTORY_CONTRACTID, &kNS_COLLATIONFACTORY_CID },

View file

@ -5,24 +5,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ['util']
TEST_DIRS += ['tests']
XPIDL_SOURCES += [
'nsIUnicodeNormalizer.idl',
]
XPIDL_MODULE = 'unicharutil'
EXPORTS += [
'nsUGenCategory.h',
'nsUnicodeNormalizer.h',
]
UNIFIED_SOURCES += [
'nsUnicodeNormalizer.cpp',
]
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']

View file

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
%{C++
#define NS_UNICODE_NORMALIZER_CID { 0xa665e49a, 0xf3e6, 0x4fed, { 0x9f, 0x31, 0xf7, 0xc5, 0x68, 0xa2, 0x98, 0x99 } }
#define NS_UNICODE_NORMALIZER_CONTRACTID "@mozilla.org/intl/unicodenormalizer;1"
%}
[scriptable, uuid(B43A461F-1BCF-4329-820B-66E48C979E14)]
interface nsIUnicodeNormalizer : nsISupports
{
/**
* Normalize Unicode (NFD, NFC, NFKD, NFKC).
*
* NFD: Canonical Decomposition
* NFC: Canonical Decomposition, followed by Canonical Composition
* NFKD: Compatibility Decomposition
* NFKC: Compatibility Decomposition, followed by Canonical Composition
* Reference: Unicode Standard, TR15, Unicode Normalization Forms
*
* @param aSrc [IN] nsAString which contains an input UTF-16 string.
* @param aDest [OUT] A pointer to an output buffer provided by a callee.
* @return NS_OK for success,
*/
void NormalizeUnicodeNFD(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFC(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFKD(in AString aSrc, out AString aDest);
void NormalizeUnicodeNFKC(in AString aSrc, out AString aDest);
};

View file

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsUnicodeNormalizer.h"
#include "ICUUtils.h"
#include "unicode/unorm2.h"
#include "unicode/utext.h"
NS_IMPL_ISUPPORTS(nsUnicodeNormalizer, nsIUnicodeNormalizer)
static nsresult
DoNormalization(const UNormalizer2* aNorm, const nsAString& aSrc,
nsAString& aDest)
{
UErrorCode errorCode = U_ZERO_ERROR;
const int32_t length = aSrc.Length();
const UChar* src = reinterpret_cast<const UChar*>(aSrc.BeginReading());
// Initial guess for a capacity that is likely to be enough for most cases.
int32_t capacity = length + (length >> 8) + 8;
while (true) {
aDest.SetLength(capacity);
UChar* dest = reinterpret_cast<UChar*>(aDest.BeginWriting());
int32_t len = unorm2_normalize(aNorm, src, aSrc.Length(), dest, capacity,
&errorCode);
if (U_SUCCESS(errorCode)) {
aDest.SetLength(len);
break;
}
if (errorCode != U_BUFFER_OVERFLOW_ERROR) {
// Some other error that we don't handle
break;
}
// Buffer wasn't big enough; adjust to the reported size and try again.
capacity = len;
errorCode = U_ZERO_ERROR;
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFD(const nsAString& aSrc,
nsAString& aDest)
{
// The unorm2_getNF*Instance functions return static singletons that should
// not be deleted, so we just get them once on first use.
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFC(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFCInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFKD(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFKDInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}
nsresult
nsUnicodeNormalizer::NormalizeUnicodeNFKC(const nsAString& aSrc,
nsAString& aDest)
{
static UErrorCode errorCode = U_ZERO_ERROR;
static const UNormalizer2* norm = unorm2_getNFKCInstance(&errorCode);
if (U_SUCCESS(errorCode)) {
return DoNormalization(norm, aSrc, aDest);
}
return ICUUtils::UErrorToNsResult(errorCode);
}

View file

@ -1,33 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsUnicodeNormalizer_h__
#define nsUnicodeNormalizer_h__
#include "nscore.h"
#include "nsISupports.h"
#include "nsIUnicodeNormalizer.h"
nsresult NS_NewUnicodeNormalizer(nsISupports** oResult);
class nsUnicodeNormalizer : public nsIUnicodeNormalizer {
public:
nsUnicodeNormalizer() { }
NS_DECL_ISUPPORTS
NS_IMETHOD NormalizeUnicodeNFD( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFC( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest) override;
NS_IMETHOD NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest) override;
private:
virtual ~nsUnicodeNormalizer() { }
};
#endif //nsUnicodeNormalizer_h__

View file

@ -1,12 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* dummy test data will be overwritten by generator */
static char versionText[] = "\0";
static testcaseLine Part0TestData[1];
static testcaseLine Part1TestData[1];
static testcaseLine Part2TestData[1];
static testcaseLine Part3TestData[1];

View file

@ -1,282 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include "gtest/gtest.h"
#include "nsXPCOM.h"
#include "nsIUnicodeNormalizer.h"
#include "nsString.h"
#include "nsCharTraits.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/Sprintf.h"
struct testcaseLine {
wchar_t* c1;
wchar_t* c2;
wchar_t* c3;
wchar_t* c4;
wchar_t* c5;
char* description;
};
#ifdef DEBUG_smontagu
#define DEBUG_NAMED_TESTCASE(t, s) \
printf(t ": "); \
for (uint32_t i = 0; i < s.Length(); ++i) \
printf("%x ", s.CharAt(i)); \
printf("\n")
#else
#define DEBUG_NAMED_TESTCASE(t, s)
#endif
#define DEBUG_TESTCASE(x) DEBUG_NAMED_TESTCASE(#x, x)
#define NORMALIZE_AND_COMPARE(base, comparison, form, description) \
normalized.Truncate();\
normalizer->NormalizeUnicode##form(comparison, normalized);\
DEBUG_NAMED_TESTCASE(#form "(" #comparison ")", normalized);\
if (!base.Equals(normalized)) {\
rv = false;\
showError(description, #base " != " #form "(" #comparison ")\n");\
}
NS_DEFINE_CID(kUnicodeNormalizerCID, NS_UNICODE_NORMALIZER_CID);
nsIUnicodeNormalizer *normalizer;
#include "NormalizationData.h"
void showError(const char* description, const char* errorText)
{
printf("%s failed: %s", description, errorText);
}
bool TestInvariants(testcaseLine* testLine)
{
nsAutoString c1, c2, c3, c4, c5, normalized;
c1 = nsDependentString((char16_t*)testLine->c1);
c2 = nsDependentString((char16_t*)testLine->c2);
c3 = nsDependentString((char16_t*)testLine->c3);
c4 = nsDependentString((char16_t*)testLine->c4);
c5 = nsDependentString((char16_t*)testLine->c5);
bool rv = true;
/*
1. The following invariants must be true for all conformant implementations
NFC
c2 == NFC(c1) == NFC(c2) == NFC(c3)
*/
DEBUG_TESTCASE(c2);
NORMALIZE_AND_COMPARE(c2, c1, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c2, c2, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c2, c3, NFC, testLine->description);
/*
c4 == NFC(c4) == NFC(c5)
*/
DEBUG_TESTCASE(c4);
NORMALIZE_AND_COMPARE(c4, c4, NFC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c5, NFC, testLine->description);
/*
NFD
c3 == NFD(c1) == NFD(c2) == NFD(c3)
*/
DEBUG_TESTCASE(c3);
NORMALIZE_AND_COMPARE(c3, c1, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c3, c2, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c3, c3, NFD, testLine->description);
/*
c5 == NFD(c4) == NFD(c5)
*/
DEBUG_TESTCASE(c5);
NORMALIZE_AND_COMPARE(c5, c4, NFD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c5, NFD, testLine->description);
/*
NFKC
c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
*/
DEBUG_TESTCASE(c4);
NORMALIZE_AND_COMPARE(c4, c1, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c2, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c3, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c4, NFKC, testLine->description);
NORMALIZE_AND_COMPARE(c4, c5, NFKC, testLine->description);
/*
NFKD
c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
*/
DEBUG_TESTCASE(c5);
NORMALIZE_AND_COMPARE(c5, c1, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c2, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c3, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c4, NFKD, testLine->description);
NORMALIZE_AND_COMPARE(c5, c5, NFKD, testLine->description);
return rv;
}
uint32_t UTF32CodepointFromTestcase(testcaseLine* testLine)
{
if (!IS_SURROGATE(testLine->c1[0]))
return testLine->c1[0];
NS_ASSERTION(NS_IS_HIGH_SURROGATE(testLine->c1[0]) &&
NS_IS_LOW_SURROGATE(testLine->c1[1]),
"Test data neither in BMP nor legal surrogate pair");
return SURROGATE_TO_UCS4(testLine->c1[0], testLine->c1[1]);
}
bool TestUnspecifiedCodepoint(uint32_t codepoint)
{
bool rv = true;
char16_t unicharArray[3];
nsAutoString X, normalized;
if (IS_IN_BMP(codepoint)) {
unicharArray[0] = codepoint;
unicharArray[1] = 0;
X = nsDependentString(unicharArray);
}
else {
unicharArray[0] = H_SURROGATE(codepoint);
unicharArray[1] = L_SURROGATE(codepoint);
unicharArray[2] = 0;
X = nsDependentString(unicharArray);
}
/*
2. For every code point X assigned in this version of Unicode that is not specifically
listed in Part 1, the following invariants must be true for all conformant
implementations:
X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
*/
static const size_t len = 9;
char description[len];
DEBUG_TESTCASE(X);
snprintf(description, len, "U+%04X", codepoint);
NORMALIZE_AND_COMPARE(X, X, NFC, description);
NORMALIZE_AND_COMPARE(X, X, NFD, description);
NORMALIZE_AND_COMPARE(X, X, NFKC, description);
NORMALIZE_AND_COMPARE(X, X, NFKD, description);
return rv;
}
void TestPart0()
{
printf("Test Part0: Specific cases\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part0TestData[i].c1[0] != 0) {
if (TestInvariants(&Part0TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart1()
{
printf("Test Part1: Character by character test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
uint32_t codepoint;
uint32_t testDataCodepoint = UTF32CodepointFromTestcase(&Part1TestData[i]);
for (codepoint = 1; codepoint < 0x110000; ++codepoint) {
if (testDataCodepoint == codepoint) {
if (TestInvariants(&Part1TestData[i]))
++numPassed;
else
++numFailed;
testDataCodepoint = UTF32CodepointFromTestcase(&Part1TestData[++i]);
} else {
if (TestUnspecifiedCodepoint(codepoint))
++numPassed;
else
++numFailed;
}
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart2()
{
printf("Test Part2: Canonical Order Test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part2TestData[i].c1[0] != 0) {
if (TestInvariants(&Part2TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
void TestPart3()
{
printf("Test Part3: PRI #29 Test\n");
uint32_t i = 0;
uint32_t numFailed = 0;
uint32_t numPassed = 0;
while (Part3TestData[i].c1[0] != 0) {
if (TestInvariants(&Part3TestData[i++]))
++numPassed;
else
++numFailed;
}
printf(" %d cases passed, %d failed\n\n", numPassed, numFailed);
EXPECT_EQ(0u, numFailed);
}
TEST(NormalizationTest, Main) {
if (sizeof(wchar_t) != 2) {
printf("This test can only be run where sizeof(wchar_t) == 2\n");
return;
}
if (strlen(versionText) == 0) {
printf("No testcases: to run the tests generate the header file using\n");
printf(" perl genNormalizationData.pl\n");
printf("in intl/unichar/tools and rebuild\n");
return;
}
printf("NormalizationTest: test nsIUnicodeNormalizer. UCD version: %s\n",
versionText);
normalizer = nullptr;
nsresult res;
res = CallGetService(kUnicodeNormalizerCID, &normalizer);
ASSERT_FALSE(NS_FAILED(res)) << "GetService failed";
ASSERT_NE(nullptr, normalizer);
TestPart0();
TestPart1();
TestPart2();
TestPart3();
NS_RELEASE(normalizer);
}

View file

@ -1,93 +0,0 @@
#!/usr/bin/perl
#
# 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/.
open ( TEXTFILE , "< NormalizationTest.txt")
|| die "Cannot find NormalizationTest.txt. The latest version should be available from\n http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt\n";
open ( OUT , "> NormalizationData.h")
#open ( OUT , "> test.txt")
|| die "Cannot create output file NormalizationData.h\n";
$mpl = <<END_OF_MPL;
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
DO NOT EDIT THIS DOCUMENT !!! THIS DOCUMENT IS GENERATED BY
mozilla/intl/unicharutil/tools/genNormalizationData.pl
*/
END_OF_MPL
print OUT $mpl;
# XXX This code assumes that wchar_t is 16-bit unsigned, which is currently
# true on Windows, Linux and Mac (with |g++ -fshort-wchar|).
# To make it work where that assumption doesn't hold, one could generate
# one huge array containing all the strings as 16-bit units (including
# the 0 terminator) and initialize the array of testcaseLine with pointers
# into the huge array.
while(<TEXTFILE>) {
chop;
if (/^# NormalizationTest-(.+)\.txt/) {
print OUT "static char versionText[] = \"$1\";\n";
} elsif (/^\@Part(.)/) {
if ($1 != "0") {
print OUT " {\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " \"\",\n";
print OUT " },\n";
print OUT "};\n";
}
print OUT "\n";
print OUT "static testcaseLine Part$1TestData[] = \n";
print OUT "{\n";
} else {
unless (/^\#/) {
@cases = split(/;/ , $_);
print OUT " {\n";
for ($case = 0; $case < 5; ++$case) {
$c = $cases[$case];
print OUT " L\"";
@codepoints = split(/ / , $c);
foreach (@codepoints) {
$cp = hex($_);
if ($cp < 0x10000) {
# BMP codepoint
printf OUT "\\x%04X", $cp;
} else {
# non-BMP codepoint, convert to surrogate pair
printf OUT "\\x%04X\\x%04X",
($cp >> 10) + 0xD7C0,
($cp & 0x03FF) | 0xDC00;
}
}
print OUT "\",\n";
}
$description = $cases[10];
$description =~ s/^ \) //;
print OUT " \"$description\"\n";
print OUT " },\n";
}
}
}
print OUT " {\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " L\"\",\n";
print OUT " \"\",\n";
print OUT " },\n";
print OUT "};\n";
close (OUT);
close (TEXTFILE);

View file

@ -1,11 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SOURCES += [
'NormalizationTest.cpp',
]
FINAL_LIBRARY = 'xul-gtest'

View file

@ -1,2 +0,0 @@
[DEFAULT]
head =

View file

@ -26,6 +26,8 @@
#include "jstypes.h"
#include "mozmemory.h"
/* The public JS engine namespace. */
namespace JS {}
@ -364,22 +366,33 @@ struct MOZ_RAII JS_PUBLIC_DATA(AutoEnterOOMUnsafeRegion)
} /* namespace js */
// Malloc allocation.
namespace js {
extern JS_PUBLIC_DATA(arena_id_t) MallocArena;
extern void InitMallocAllocator();
extern void ShutDownMallocAllocator();
} /* namespace js */
static inline void* js_malloc(size_t bytes)
{
JS_OOM_POSSIBLY_FAIL();
return malloc(bytes);
return moz_arena_malloc(js::MallocArena, bytes);
}
static inline void* js_calloc(size_t bytes)
{
JS_OOM_POSSIBLY_FAIL();
return calloc(bytes, 1);
return moz_arena_calloc(js::MallocArena, bytes, 1);
}
static inline void* js_calloc(size_t nmemb, size_t size)
{
JS_OOM_POSSIBLY_FAIL();
return calloc(nmemb, size);
return moz_arena_calloc(js::MallocArena, nmemb, size);
}
static inline void* js_realloc(void* p, size_t bytes)
@ -390,19 +403,18 @@ static inline void* js_realloc(void* p, size_t bytes)
MOZ_ASSERT(bytes != 0);
JS_OOM_POSSIBLY_FAIL();
return realloc(p, bytes);
return moz_arena_realloc(js::MallocArena, p, bytes);
}
static inline void js_free(void* p)
{
// TODO: This should call |moz_arena_free(js::MallocArena, p)| but we
// currently can't enforce that all memory freed here was allocated by
// js_malloc().
free(p);
}
static inline char* js_strdup(const char* s)
{
JS_OOM_POSSIBLY_FAIL();
return strdup(s);
}
JS_PUBLIC_API(char*) js_strdup(const char* s);
#endif/* JS_USE_CUSTOM_ALLOCATOR */
#include <new>

View file

@ -2272,6 +2272,7 @@ PerformPromiseRace(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
MOZ_ASSERT_UNREACHABLE("Shouldn't reach the end of PerformPromiseRace");
}
// ES2016, Sub-steps of 25.4.4.4 and 25.4.4.5.
static MOZ_MUST_USE JSObject*
CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue argVal,
@ -2332,6 +2333,13 @@ CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue ar
return promise;
}
MOZ_MUST_USE JSObject*
js::PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value)
{
RootedValue C(cx, ObjectValue(*constructor));
return CommonStaticResolveRejectImpl(cx, C, value, ResolveMode);
}
/**
* ES2016, 25.4.4.4, Promise.reject.
*/
@ -3680,6 +3688,7 @@ CreatePromisePrototype(JSContext* cx, JSProtoKey key)
static const JSFunctionSpec promise_methods[] = {
JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0),
JS_FN("then", Promise_then, 2, 0),
JS_SELF_HOSTED_FN("finally", "Promise_finally", 1, 0),
JS_FS_END
};

View file

@ -124,6 +124,15 @@ OriginalPromiseThen(JSContext* cx, Handle<PromiseObject*> promise,
HandleValue onFulfilled, HandleValue onRejected,
MutableHandleObject dependent, bool createDependent);
/**
* PromiseResolve ( C, x )
*
* The abstract operation PromiseResolve, given a constructor and a value,
* returns a new promise resolved with that value.
*/
MOZ_MUST_USE JSObject*
PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
MOZ_MUST_USE PromiseObject*
CreatePromiseObjectForAsync(JSContext* cx, HandleValue generatorVal);

View file

@ -7,3 +7,71 @@ function Promise_catch(onRejected) {
// Steps 1-2.
return callContentFunction(this.then, this, undefined, onRejected);
}
// Promise.prototype.finally proposal, stage 3.
// Promise.prototype.finally ( onFinally )
function Promise_finally(onFinally) {
// Step 1.
var promise = this;
// Step 2.
if (!IsObject(promise))
ThrowTypeError(JSMSG_INCOMPATIBLE_PROTO, "Promise", "finally", "value");
// Step 3.
var C = SpeciesConstructor(promise, GetBuiltinConstructor("Promise"));
// Step 4.
assert(IsConstructor(C), "SpeciesConstructor returns a constructor function");
// Steps 5-6.
var thenFinally, catchFinally;
if (!IsCallable(onFinally)) {
thenFinally = onFinally;
catchFinally = onFinally;
} else {
// ThenFinally Function.
// The parentheses prevent the infering of a function name.
(thenFinally) = function(value) {
// Steps 1-2 (implicit).
// Step 3.
var result = onFinally();
// Steps 4-5 (implicit).
// Step 6.
var promise = PromiseResolve(C, result);
// Step 7.
// FIXME: spec issue - "be equivalent to a function that" is not a defined spec term.
// https://github.com/tc39/ecma262/issues/933
// Step 8.
return callContentFunction(promise.then, promise, function() { return value; });
};
// CatchFinally Function.
(catchFinally) = function(reason) {
// Steps 1-2 (implicit).
// Step 3.
var result = onFinally();
// Steps 4-5 (implicit).
// Step 6.
var promise = PromiseResolve(C, result);
// Step 7.
// FIXME: spec issue - "be equivalent to a function that" is not a defined spec term.
// https://github.com/tc39/ecma262/issues/933
// Step 8.
return callContentFunction(promise.then, promise, function() { throw reason; });
};
}
// Step 7.
return callContentFunction(promise.then, promise, thenFinally, catchFinally);
}

View file

@ -0,0 +1,37 @@
// |jit-test| --no-sse4;
// This test is a fork of dce-with-rinstructions.js. It tests recover
// instructions which are only executed on pre-SSE4 processors.
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
const max = 200;
// Check that we are able to remove the operation inside recover test
// functions (denoted by "rop..."), when we inline the first version
// of uceFault, and ensure that the bailout is correct when uceFault
// is replaced (which cause an invalidation bailout)
let uceFault = function (i) {
if (i > 98)
uceFault = function (i) { return true; };
return false;
};
let uceFault_floor_double = eval(
uneval(uceFault)
.replace('uceFault', 'uceFault_floor_double')
);
function rfloor_double(i) {
const x = Math.floor(i + (-1 >>> 0));
if (uceFault_floor_double(i) || uceFault_floor_double(i))
assertEq(x, 99 + (-1 >>> 0)); /* = i + 2 ^ 32 - 1 */
assertRecoveredOnBailout(x, true);
return i;
}
for (let j = 100 - max; j < 100; j++) {
with({}){} // Do not Ion-compile this loop.
const i = j < 2 ? (Math.abs(j) % 50) + 2 : j;
rfloor_double(i);
}

View file

@ -4080,7 +4080,7 @@ AnalyzePoppedThis(JSContext* cx, ObjectGroup* group,
// Add the property to the object, being careful not to update type information.
DebugOnly<unsigned> slotSpan = baseobj->slotSpan();
MOZ_ASSERT(!baseobj->containsPure(id));
if (!NativeObject::addDataProperty(cx, baseobj, id, baseobj->slotSpan(), JSPROP_ENUMERATE))
if (!NativeObject::addDataProperty(cx, baseobj, id, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE))
return false;
MOZ_ASSERT(baseobj->slotSpan() != slotSpan);
MOZ_ASSERT(!baseobj->inDictionaryMode());

View file

@ -858,8 +858,13 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
value = valueDouble;
}
if (needsPostBarrier(value))
current->add(MPostWriteBarrier::New(alloc(), obj, value));
if (needsPostBarrier(value)) {
MInstruction* elements = MElements::New(alloc(), obj);
current->add(elements);
MInstruction* initLength = MInitializedLength::New(alloc(), elements);
current->add(initLength);
current->add(MPostWriteElementBarrier::New(alloc(), obj, value, initLength));
}
ins = MArrayPush::New(alloc(), obj, value);
current->add(ins);

View file

@ -7017,6 +7017,7 @@ class MMathFunction
switch(function_) {
case Sin:
case Log:
case Floor:
case Round:
return true;
default:

View file

@ -962,6 +962,9 @@ MMathFunction::writeRecoverData(CompactBufferWriter& writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
switch (function_) {
case Floor:
writer.writeUnsigned(uint32_t(RInstruction::Recover_Floor));
return true;
case Round:
writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
return true;

View file

@ -691,9 +691,7 @@ PostWriteElementBarrier(JSRuntime* rt, JSObject* obj, int32_t index)
if (InBounds == IndexInBounds::Yes) {
MOZ_ASSERT(uint32_t(index) < obj->as<NativeObject>().getDenseInitializedLength());
} else {
if (MOZ_UNLIKELY(!obj->is<NativeObject>()) ||
uint32_t(index) >= obj->as<NativeObject>().getDenseInitializedLength())
{
if (MOZ_UNLIKELY(!obj->is<NativeObject>() || index < 0)) {
rt->gc.storeBuffer().putWholeCell(obj);
return;
}

View file

@ -394,12 +394,13 @@ END_TEST(testHashMapLookupWithDefaultOOM)
BEGIN_TEST(testHashTableMovableEnum)
{
IntSet set;
CHECK(set.init());
// Exercise returning a hash table Enum object from a function.
CHECK(set.put(1));
for (auto e = enumerateSet(); !e.empty(); e.popFront())
for (auto e = enumerateSet(set); !e.empty(); e.popFront())
e.removeFront();
CHECK(set.count() == 0);
@ -425,9 +426,7 @@ BEGIN_TEST(testHashTableMovableEnum)
return true;
}
IntSet set;
IntSet::Enum enumerateSet()
IntSet::Enum enumerateSet(IntSet& set)
{
return IntSet::Enum(set);
}

View file

@ -45,6 +45,7 @@ void JSAPITest::uninit()
destroyContext();
cx = nullptr;
}
msgs.clear();
}
bool JSAPITest::exec(const char* bytes, const char* filename, int lineno)

View file

@ -33,6 +33,7 @@ class JSAPITestString {
const char* begin() const { return chars.begin(); }
const char* end() const { return chars.end(); }
size_t length() const { return chars.length(); }
void clear() { chars.clearAndFree(); }
JSAPITestString& operator +=(const char* s) {
if (!chars.append(s, strlen(s)))

View file

@ -3868,7 +3868,12 @@ js::DuplicateString(JSContext* cx, const char16_t* s)
UniqueChars
js::DuplicateString(const char* s)
{
return UniqueChars(js_strdup(s));
size_t n = strlen(s) + 1;
UniqueChars ret(js_pod_malloc<char>(n));
if (!ret)
return ret;
PodCopy(ret.get(), s, n);
return ret;
}
UniqueChars
@ -3899,6 +3904,12 @@ js::DuplicateString(const char16_t* s, size_t n)
return ret;
}
JS_PUBLIC_API(char*)
js_strdup(const char* s)
{
return DuplicateString(s).release();
}
template <typename CharT>
const CharT*
js_strchr_limit(const CharT* s, char16_t c, const CharT* limit)

View file

@ -170,6 +170,20 @@ ResetSimulatedInterrupt()
} // namespace js
#endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
JS_PUBLIC_DATA(arena_id_t) js::MallocArena;
void
js::InitMallocAllocator()
{
MallocArena = moz_create_arena();
}
void
js::ShutDownMallocAllocator()
{
moz_dispose_arena(MallocArena);
}
JS_PUBLIC_API(void)
JS_Assert(const char* s, const char* file, int ln)
{

View file

@ -3993,6 +3993,8 @@ KillWorkerThreads(JSContext* cx)
thread->join();
}
workerThreads.clearAndFree();
js_delete(workerThreadsLock);
workerThreadsLock = nullptr;
@ -4929,12 +4931,12 @@ NestedShell(JSContext* cx, unsigned argc, Value* vp)
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
return false;
}
if (!argv.append(strdup(sArgv[0])))
if (!argv.append(js_strdup(sArgv[0])))
return false;
// Propagate selected flags from the current shell
for (unsigned i = 0; i < sPropagatedFlags.length(); i++) {
char* cstr = strdup(sPropagatedFlags[i]);
char* cstr = js_strdup(sPropagatedFlags[i]);
if (!cstr || !argv.append(cstr))
return false;
}
@ -8631,6 +8633,7 @@ main(int argc, char** argv, char** envp)
state->shutdown = true;
while (!state->jobs.empty())
state.wait(/* jobs empty */);
state->jobs.clearAndFree();
});
sArgc = argc;
@ -8652,6 +8655,12 @@ main(int argc, char** argv, char** envp)
SetOutputFile("JS_STDOUT", &rcStdout, &gOutFile);
SetOutputFile("JS_STDERR", &rcStderr, &gErrFile);
// Start the engine.
if (!JS_Init())
return 1;
auto shutdownEngine = MakeScopeExit([]() { JS_ShutDown(); });
OptionParser op("Usage: {progname} [options] [[script] scriptArgs*]");
op.setDescription("The SpiderMonkey shell provides a command line interface to the "
@ -8875,10 +8884,6 @@ main(int argc, char** argv, char** envp)
if (op.getBoolOption("no-threads"))
js::DisableExtraThreads();
// Start the engine.
if (!JS_Init())
return 1;
if (!InitSharedArrayBufferMailbox())
return 1;
@ -8978,6 +8983,5 @@ main(int argc, char** argv, char** envp)
DestructSharedArrayBufferMailbox();
JS_DestroyContext(cx);
JS_ShutDown();
return result;
}

View file

@ -22,7 +22,6 @@ UNSUPPORTED_FEATURES = set([
"tail-call-optimization",
"BigInt",
"class-fields",
"Promise.prototype.finally",
"optional-catch-binding",
"regexp-dotall",
"regexp-lookbehind",

View file

@ -1,4 +1,5 @@
commit a456b0a390bb0f70b4cb8d38cb5ab0ecb557a851
Merge: db05f2f 297502b
Author: Rick Waldron <waldron.rick@gmail.com>
Date: Mon Oct 23 11:02:44 2017 -0400

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,4 +1,3 @@
// |reftest| skip -- Promise.prototype.finally is not supported
// Copyright (C) 2017 Jordan Harband. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---

View file

@ -1,34 +1,3 @@
// file: timer.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Used in website/scripts/sth.js
---*/
//setTimeout is not available, hence this script was loaded
if (Promise === undefined && this.setTimeout === undefined) {
if(/\$DONE()/.test(code))
$ERROR("Async test capability is not supported in your test environment");
}
if (Promise !== undefined && this.setTimeout === undefined) {
(function(that) {
that.setTimeout = function(callback, delay) {
var p = Promise.resolve();
var start = Date.now();
var end = start + delay;
function check(){
var timeLeft = end - Date.now();
if(timeLeft > 0)
p.then(check);
else
callback();
}
p.then(check);
}
})(this);
}
// file: fnGlobalObject.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
@ -570,6 +539,20 @@ var byteConversionValues = {
}
};
// file: nans.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
A collection of NaN values produced from expressions that have been observed
to create distinct bit representations on various platforms. These provide a
weak basis for assertions regarding the consistent canonicalization of NaN
values in Array buffers.
---*/
var distinctNaNs = [
0/0, Infinity/Infinity, -(0/0), Math.pow(-1, 0.5), -Math.pow(-1, 0.5)
];
// file: testBuiltInObject.js
// Copyright 2012 Mozilla Corporation. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
@ -699,26 +682,35 @@ function testBuiltInObject(obj, isFunction, isConstructor, properties, length) {
return true;
}
// file: promiseHelper.js
// file: timer.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
Check that an array contains a numeric sequence starting at 1
and incrementing by 1 for each entry in the array. Used by
Promise tests to assert the order of execution in deep Promise
resolution pipelines.
Used in website/scripts/sth.js
---*/
//setTimeout is not available, hence this script was loaded
if (Promise === undefined && this.setTimeout === undefined) {
if(/\$DONE()/.test(code))
$ERROR("Async test capability is not supported in your test environment");
}
function checkSequence(arr, message) {
arr.forEach(function(e, i) {
if (e !== (i+1)) {
$ERROR((message ? message : "Steps in unexpected sequence:") +
" '" + arr.join(',') + "'");
if (Promise !== undefined && this.setTimeout === undefined) {
(function(that) {
that.setTimeout = function(callback, delay) {
var p = Promise.resolve();
var start = Date.now();
var end = start + delay;
function check(){
var timeLeft = end - Date.now();
if(timeLeft > 0)
p.then(check);
else
callback();
}
p.then(check);
}
});
return true;
})(this);
}
// file: proxyTrapsHelper.js
@ -851,19 +843,27 @@ description: |
var $MAX_ITERATIONS = 100000;
// file: nans.js
// file: promiseHelper.js
// Copyright (C) 2017 Ecma International. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: |
A collection of NaN values produced from expressions that have been observed
to create distinct bit representations on various platforms. These provide a
weak basis for assertions regarding the consistent canonicalization of NaN
values in Array buffers.
Check that an array contains a numeric sequence starting at 1
and incrementing by 1 for each entry in the array. Used by
Promise tests to assert the order of execution in deep Promise
resolution pipelines.
---*/
var distinctNaNs = [
0/0, Infinity/Infinity, -(0/0), Math.pow(-1, 0.5), -Math.pow(-1, 0.5)
];
function checkSequence(arr, message) {
arr.forEach(function(e, i) {
if (e !== (i+1)) {
$ERROR((message ? message : "Steps in unexpected sequence:") +
" '" + arr.join(',') + "'");
}
});
return true;
}
// file: detachArrayBuffer.js
// Copyright (C) 2017 Ecma International. All rights reserved.

View file

@ -6,6 +6,7 @@
#include "threading/Mutex.h"
#include "js/Initialization.h"
#include "js/Utility.h"
using namespace js;
@ -44,6 +45,11 @@ js::Mutex::heldMutexStack()
void
js::Mutex::lock()
{
if (!JS_IsInitialized()) {
MutexImpl::lock();
return;
}
auto& stack = heldMutexStack();
if (!stack.empty()) {
const Mutex& prev = *stack.back();
@ -65,6 +71,11 @@ js::Mutex::lock()
void
js::Mutex::unlock()
{
if (!JS_IsInitialized()) {
MutexImpl::unlock();
return;
}
auto& stack = heldMutexStack();
MOZ_ASSERT(stack.back() == this);
MutexImpl::unlock();

View file

@ -812,7 +812,7 @@ GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
RootedId id(cx, NameToId(name));
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0));
Shape* shape = cx->zone()->propertyTree().getChild(cx, last, child);
if (!shape)
return false;

View file

@ -100,6 +100,8 @@ JS::detail::InitWithFailureDiagnostic(bool isDebugBuild)
RETURN_IF_FAIL(js::oom::InitThreadType());
#endif
js::InitMallocAllocator();
RETURN_IF_FAIL(js::Mutex::Init());
RETURN_IF_FAIL(js::wasm::InitInstanceStaticData());
@ -170,6 +172,7 @@ JS_ShutDown(void)
js::MemoryProtectionExceptionHandler::uninstall();
js::wasm::ShutDownInstanceStaticData();
js::wasm::ShutDownProcessStaticData();
js::Mutex::ShutDown();
@ -199,6 +202,8 @@ JS_ShutDown(void)
js::jit::ReleaseProcessExecutableMemory();
}
js::ShutDownMallocAllocator();
libraryInitState = InitState::ShutDown;
}

View file

@ -481,8 +481,6 @@ NativeObject::sparsifyDenseElement(JSContext* cx, HandleNativeObject obj, uint32
removeDenseElementForSparseIndex(cx, obj, index);
uint32_t slot = obj->slotSpan();
RootedId id(cx, INT_TO_JSID(index));
AutoKeepShapeTables keep(cx);
@ -496,15 +494,15 @@ NativeObject::sparsifyDenseElement(JSContext* cx, HandleNativeObject obj, uint32
// NOTE: We don't use addDataProperty because we don't want the
// extensibility check if we're, for example, sparsifying frozen objects..
if (!addDataPropertyInternal(cx, obj, id, slot,
obj->getElementsHeader()->elementAttributes(),
entry, keep)) {
Shape* shape = addDataPropertyInternal(cx, obj, id, SHAPE_INVALID_SLOT,
obj->getElementsHeader()->elementAttributes(),
entry, keep);
if (!shape) {
obj->setDenseElementUnchecked(index, value);
return false;
}
MOZ_ASSERT(slot == obj->slotSpan() - 1);
obj->initSlot(slot, value);
obj->initSlot(shape->slot(), value);
return true;
}

View file

@ -847,9 +847,12 @@ class NativeObject : public ShapedObject
void freeSlot(JSContext* cx, uint32_t slot);
private:
static MOZ_ALWAYS_INLINE Shape* getChildProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent,
MutableHandle<StackShape> child);
static MOZ_ALWAYS_INLINE Shape* getChildDataProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent,
MutableHandle<StackShape> child);
static MOZ_ALWAYS_INLINE Shape* getChildAccessorProperty(JSContext* cx, HandleNativeObject obj,
HandleShape parent,
MutableHandle<StackShape> child);
public:
/* Add a property whose id is not yet in this scope. */

View file

@ -115,7 +115,7 @@ NextEnvironmentShape(JSContext* cx, HandleAtom name, BindingKind bindKind, uint3
}
jsid id = NameToId(name->asPropertyName());
Rooted<StackShape> child(cx, StackShape(base, id, slot, attrs, 0));
Rooted<StackShape> child(cx, StackShape(base, id, slot, attrs));
return cx->zone()->propertyTree().getChild(cx, shape, child);
}

View file

@ -2093,100 +2093,17 @@ intrinsic_ModuleNamespaceExports(JSContext* cx, unsigned argc, Value* vp)
}
static bool
intrinsic_CreatePendingPromise(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
JSObject* promise = PromiseObject::createSkippingExecutor(cx);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_CreatePromiseResolvedWith(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
JSObject* promise = PromiseObject::unforgeableResolve(cx, args[0]);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_CreatePromiseRejectedWith(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
JSObject* promise = PromiseObject::unforgeableReject(cx, args[0]);
if (!promise)
return false;
args.rval().setObject(*promise);
return true;
}
static bool
intrinsic_ResolvePromise(JSContext* cx, unsigned argc, Value* vp)
intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
if (!PromiseObject::resolve(cx, promise, args[1]))
RootedObject constructor(cx, &args[0].toObject());
JSObject* promise = js::PromiseResolve(cx, constructor, args[1]);
if (!promise)
return false;
args.rval().setUndefined();
return true;
}
static bool
intrinsic_RejectPromise(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
if (!PromiseObject::reject(cx, promise, args[1]))
return false;
args.rval().setUndefined();
return true;
}
static bool
intrinsic_CallOriginalPromiseThen(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() >= 2);
RootedObject promise(cx, &args[0].toObject());
Value val = args[1];
RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
val = args.get(2);
RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
JSObject* resultPromise = JS::CallOriginalPromiseThen(cx, promise, onResolvedObj,
onRejectedObj);
if (!resultPromise)
return false;
args.rval().setObject(*resultPromise);
return true;
}
static bool
intrinsic_AddPromiseReactions(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() >= 2);
RootedObject promise(cx, &args[0].toObject());
Value val = args[1];
RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
val = args.get(2);
RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
if (!JS::AddPromiseReactions(cx, promise, onResolvedObj, onRejectedObj))
return false;
args.rval().setUndefined();
args.rval().setObject(*promise);
return true;
}
@ -2609,13 +2526,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0),
JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0),
JS_FN("CreatePendingPromise", intrinsic_CreatePendingPromise, 0, 0),
JS_FN("CreatePromiseResolvedWith", intrinsic_CreatePromiseResolvedWith, 1, 0),
JS_FN("CreatePromiseRejectedWith", intrinsic_CreatePromiseRejectedWith, 1, 0),
JS_FN("ResolvePromise", intrinsic_ResolvePromise, 2, 0),
JS_FN("RejectPromise", intrinsic_RejectPromise, 2, 0),
JS_FN("AddPromiseReactions", intrinsic_AddPromiseReactions, 3, 0),
JS_FN("CallOriginalPromiseThen", intrinsic_CallOriginalPromiseThen, 3, 0),
JS_FN("IsPromiseObject", intrinsic_IsInstanceOfBuiltin<PromiseObject>, 1, 0),
JS_FN("CallPromiseMethodIfWrapped", CallNonGenericSelfhostedMethod<Is<PromiseObject>>, 2, 0),
JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0),
JS_FS_END
};

View file

@ -292,56 +292,49 @@ Shape::replaceLastProperty(JSContext* cx, StackBaseShape& base,
* one of lastProperty() or lastProperty()->parent.
*/
/* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::getChildProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child)
NativeObject::getChildDataProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child)
{
/*
* Shared properties have no slot, but slot_ will reflect that of parent.
* Unshared properties allocate a slot here but may lose it due to a
* JS_ClearScope call.
*/
if (!child.isDataProperty()) {
child.setSlot(parent->maybeSlot());
} else {
if (child.hasMissingSlot()) {
uint32_t slot;
if (obj->inDictionaryMode()) {
if (!allocDictionarySlot(cx, obj, &slot))
return nullptr;
} else {
slot = obj->slotSpan();
MOZ_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
// Objects with many properties are converted to dictionary
// mode, so we can't overflow SHAPE_MAXIMUM_SLOT here.
MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
}
child.setSlot(slot);
MOZ_ASSERT(child.isDataProperty());
if (child.hasMissingSlot()) {
uint32_t slot;
if (obj->inDictionaryMode()) {
if (!allocDictionarySlot(cx, obj, &slot))
return nullptr;
} else {
/*
* Slots can only be allocated out of order on objects in
* dictionary mode. Otherwise the child's slot must be after the
* parent's slot (if it has one), because slot number determines
* slot span for objects with that shape. Usually child slot
* *immediately* follows parent slot, but there may be a slot gap
* when the object uses some -- but not all -- of its reserved
* slots to store properties.
*/
MOZ_ASSERT(obj->inDictionaryMode() ||
parent->hasMissingSlot() ||
child.slot() == parent->maybeSlot() + 1 ||
(parent->maybeSlot() + 1 < JSSLOT_FREE(obj->getClass()) &&
child.slot() == JSSLOT_FREE(obj->getClass())));
slot = obj->slotSpan();
MOZ_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
// Objects with many properties are converted to dictionary
// mode, so we can't overflow SHAPE_MAXIMUM_SLOT here.
MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
}
child.setSlot(slot);
} else {
/*
* Slots can only be allocated out of order on objects in
* dictionary mode. Otherwise the child's slot must be after the
* parent's slot (if it has one), because slot number determines
* slot span for objects with that shape. Usually child slot
* *immediately* follows parent slot, but there may be a slot gap
* when the object uses some -- but not all -- of its reserved
* slots to store properties.
*/
MOZ_ASSERT(obj->inDictionaryMode() ||
parent->hasMissingSlot() ||
child.slot() == parent->maybeSlot() + 1 ||
(parent->maybeSlot() + 1 < JSSLOT_FREE(obj->getClass()) &&
child.slot() == JSSLOT_FREE(obj->getClass())));
}
if (obj->inDictionaryMode()) {
MOZ_ASSERT(parent == obj->lastProperty());
Shape* shape = child.isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx);
Shape* shape = Allocate<Shape>(cx);
if (!shape)
return nullptr;
if (child.isDataProperty() && child.slot() >= obj->lastProperty()->base()->slotSpan()) {
if (child.slot() >= obj->lastProperty()->base()->slotSpan()) {
if (!obj->setSlotSpan(cx, child.slot() + 1)) {
new (shape) Shape(obj->lastProperty()->base()->unowned(), 0);
return nullptr;
@ -363,6 +356,37 @@ NativeObject::getChildProperty(JSContext* cx,
return shape;
}
/* static */ MOZ_ALWAYS_INLINE Shape*
NativeObject::getChildAccessorProperty(JSContext* cx,
HandleNativeObject obj, HandleShape parent,
MutableHandle<StackShape> child)
{
MOZ_ASSERT(!child.isDataProperty());
// Accessor properties have no slot, but slot_ will reflect that of parent.
child.setSlot(parent->maybeSlot());
if (obj->inDictionaryMode()) {
MOZ_ASSERT(parent == obj->lastProperty());
Shape* shape = Allocate<AccessorShape>(cx);
if (!shape)
return nullptr;
shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
return shape;
}
Shape* shape = cx->zone()->propertyTree().inlinedGetChild(cx, parent, child);
if (!shape)
return nullptr;
MOZ_ASSERT(shape->parent == parent);
MOZ_ASSERT_IF(parent != obj->lastProperty(), parent == obj->lastProperty()->parent);
if (!obj->setLastProperty(cx, shape))
return nullptr;
return shape;
}
/* static */ bool
js::NativeObject::toDictionaryMode(JSContext* cx, HandleNativeObject obj)
{
@ -485,10 +509,8 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
AutoCheckShapeConsistency check(obj);
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
/*
* The code below deals with either converting obj to dictionary mode or
* growing an object that's already in dictionary mode.
*/
// The code below deals with either converting obj to dictionary mode or
// growing an object that's already in dictionary mode.
ShapeTable* table = nullptr;
if (!obj->inDictionaryMode()) {
if (ShouldConvertToDictionary(obj)) {
@ -511,7 +533,7 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
MOZ_ASSERT(!!table == !!entry);
/* Find or create a property tree node labeled by our arguments. */
// Find or create a property tree node labeled by our arguments.
RootedShape shape(cx);
{
RootedShape last(cx, obj->lastProperty());
@ -519,9 +541,9 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
if (!nbase)
return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs, 0));
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs));
child.updateGetterSetter(getter, setter);
shape = getChildProperty(cx, obj, last, &child);
shape = getChildAccessorProperty(cx, obj, last, &child);
if (!shape)
return nullptr;
}
@ -529,11 +551,11 @@ NativeObject::addAccessorPropertyInternal(JSContext* cx,
MOZ_ASSERT(shape == obj->lastProperty());
if (table) {
/* Store the tree node pointer in the table entry for id. */
// Store the tree node pointer in the table entry for id.
entry->setPreservingCollision(shape);
table->incEntryCount();
/* Pass the table along to the new last property, namely shape. */
// Pass the table along to the new last property, namely shape.
MOZ_ASSERT(shape->parent->maybeTable(keep) == table);
shape->parent->handoffTableTo(shape);
}
@ -549,17 +571,15 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
{
AutoCheckShapeConsistency check(obj);
/*
* The code below deals with either converting obj to dictionary mode or
* growing an object that's already in dictionary mode.
*/
// The slot, if any, must be a reserved slot.
MOZ_ASSERT(slot == SHAPE_INVALID_SLOT ||
slot < JSCLASS_RESERVED_SLOTS(obj->getClass()));
// The code below deals with either converting obj to dictionary mode or
// growing an object that's already in dictionary mode.
ShapeTable* table = nullptr;
if (!obj->inDictionaryMode()) {
bool stableSlot =
(slot == SHAPE_INVALID_SLOT) ||
obj->lastProperty()->hasMissingSlot() ||
(slot == obj->lastProperty()->maybeSlot() + 1);
if (!stableSlot || ShouldConvertToDictionary(obj)) {
if (ShouldConvertToDictionary(obj)) {
if (!toDictionaryMode(cx, obj))
return nullptr;
table = obj->lastProperty()->maybeTable(keep);
@ -579,7 +599,7 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
MOZ_ASSERT(!!table == !!entry);
/* Find or create a property tree node labeled by our arguments. */
// Find or create a property tree node labeled by our arguments.
RootedShape shape(cx);
{
RootedShape last(cx, obj->lastProperty());
@ -587,8 +607,8 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
if (!nbase)
return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs, 0));
shape = getChildProperty(cx, obj, last, &child);
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs));
shape = getChildDataProperty(cx, obj, last, &child);
if (!shape)
return nullptr;
}
@ -596,11 +616,11 @@ NativeObject::addDataPropertyInternal(JSContext* cx,
MOZ_ASSERT(shape == obj->lastProperty());
if (table) {
/* Store the tree node pointer in the table entry for id. */
// Store the tree node pointer in the table entry for id.
entry->setPreservingCollision(shape);
table->incEntryCount();
/* Pass the table along to the new last property, namely shape. */
// Pass the table along to the new last property, namely shape.
MOZ_ASSERT(shape->parent->maybeTable(keep) == table);
shape->parent->handoffTableTo(shape);
}
@ -653,7 +673,7 @@ NativeObject::addEnumerableDataProperty(JSContext* cx, HandleNativeObject obj, H
if (!allocDictionarySlot(cx, obj, &slot))
return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE, 0));
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE));
MOZ_ASSERT(last == obj->lastProperty());
shape = Allocate<Shape>(cx);
@ -674,7 +694,7 @@ NativeObject::addEnumerableDataProperty(JSContext* cx, HandleNativeObject obj, H
MOZ_ASSERT(slot < JSSLOT_FREE(obj->getClass()) + PropertyTree::MAX_HEIGHT);
MOZ_ASSERT(slot < SHAPE_MAXIMUM_SLOT);
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE, 0));
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, JSPROP_ENUMERATE));
shape = cx->zone()->propertyTree().inlinedGetChild(cx, last, child);
if (!shape)
return nullptr;
@ -732,7 +752,7 @@ js::ReshapeForAllocKind(JSContext* cx, Shape* shape, TaggedProto proto,
if (!nbase)
return nullptr;
Rooted<StackShape> child(cx, StackShape(nbase, id, i, JSPROP_ENUMERATE, 0));
Rooted<StackShape> child(cx, StackShape(nbase, id, i, JSPROP_ENUMERATE));
newShape = cx->zone()->propertyTree().getChild(cx, newShape, child);
if (!newShape)
return nullptr;
@ -783,16 +803,7 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
AutoCheckShapeConsistency check(obj);
AssertValidArrayIndex(obj, id);
/*
* Search for id in order to claim its entry if table has been allocated.
*
* Note that we can only try to claim an entry in a table that is thread
* local. An object may be thread local *without* its shape being thread
* local. The only thread local objects that *also* have thread local
* shapes are dictionaries that were allocated/converted thread
* locally. Only for those objects we can try to claim an entry in its
* shape table.
*/
// Search for id in order to claim its entry if table has been allocated.
AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry;
RootedShape shape(cx);
@ -803,25 +814,19 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
}
if (!shape) {
/*
* You can't add properties to a non-extensible object, but you can change
* attributes of properties in such objects.
*/
MOZ_ASSERT(obj->nonProxyIsExtensible());
MOZ_ASSERT(obj->nonProxyIsExtensible(),
"Can't add new property to non-extensible object");
return addDataPropertyInternal(cx, obj, id, SHAPE_INVALID_SLOT, attrs, entry, keep);
}
/* Property exists: search must have returned a valid entry. */
// Property exists: search must have returned a valid entry.
MOZ_ASSERT_IF(entry, !entry->isRemoved());
AssertCanChangeAttrs(shape, attrs);
/*
* If the caller wants to allocate a slot, but doesn't care which slot,
* copy the existing shape's slot into slot so we can match shape, if all
* other members match.
*/
// If the caller wants to allocate a slot, but doesn't care which slot,
// copy the existing shape's slot into slot so we can match shape, if all
// other members match.
bool hadSlot = shape->isDataProperty();
uint32_t oldSlot = shape->maybeSlot();
uint32_t slot = hadSlot ? oldSlot : SHAPE_INVALID_SLOT;
@ -834,18 +839,14 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
return nullptr;
}
/*
* Now that we've possibly preserved slot, check whether all members match.
* If so, this is a redundant "put" and we can return without more work.
*/
if (shape->matchesParamsAfterId(nbase, slot, attrs, 0, nullptr, nullptr))
// Now that we've possibly preserved slot, check whether all members match.
// If so, this is a redundant "put" and we can return without more work.
if (shape->matchesParamsAfterId(nbase, slot, attrs, nullptr, nullptr))
return shape;
/*
* Overwriting a non-last property requires switching to dictionary mode.
* The shape tree is shared immutable, and we can't removeProperty and then
* addPropertyInternal because a failure under add would lose data.
*/
// Overwriting a non-last property requires switching to dictionary mode.
// The shape tree is shared immutable, and we can't removeProperty and then
// addDataPropertyInternal because a failure under add would lose data.
if (shape != obj->lastProperty() && !obj->inDictionaryMode()) {
if (!toDictionaryMode(cx, obj))
return nullptr;
@ -858,12 +859,10 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
MOZ_ASSERT_IF(shape->isDataProperty(), shape->slot() == slot);
if (obj->inDictionaryMode()) {
/*
* Updating some property in a dictionary-mode object. Create a new
* shape for the existing property, and also generate a new shape for
* the last property of the dictionary (unless the modified property
* is also the last property).
*/
// Updating some property in a dictionary-mode object. Create a new
// shape for the existing property, and also generate a new shape for
// the last property of the dictionary (unless the modified property
// is also the last property).
bool updateLast = (shape == obj->lastProperty());
shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr,
/* accessorShape = */ false);
@ -872,10 +871,6 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
if (!updateLast && !NativeObject::generateOwnShape(cx, obj))
return nullptr;
/*
* FIXME bug 593129 -- slot allocation and NativeObject *this must move
* out of here!
*/
if (slot == SHAPE_INVALID_SLOT) {
if (!allocDictionarySlot(cx, obj, &slot))
return nullptr;
@ -890,10 +885,8 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
shape->attrs = uint8_t(attrs);
shape->flags = Shape::IN_DICTIONARY;
} else {
/*
* Updating the last property in a non-dictionary-mode object. Find an
* alternate shared child of the last property's previous shape.
*/
// Updating the last property in a non-dictionary-mode object. Find an
// alternate shared child of the last property's previous shape.
StackBaseShape base(obj->lastProperty()->base());
UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base);
@ -902,10 +895,10 @@ NativeObject::putDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id
MOZ_ASSERT(shape == obj->lastProperty());
/* Find or create a property tree node labeled by our arguments. */
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs, 0));
// Find or create a property tree node labeled by our arguments.
Rooted<StackShape> child(cx, StackShape(nbase, id, slot, attrs));
RootedShape parent(cx, shape->parent);
shape = getChildProperty(cx, obj, parent, &child);
shape = getChildDataProperty(cx, obj, parent, &child);
if (!shape)
return nullptr;
}
@ -925,16 +918,7 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
/*
* Search for id in order to claim its entry if table has been allocated.
*
* Note that we can only try to claim an entry in a table that is thread
* local. An object may be thread local *without* its shape being thread
* local. The only thread local objects that *also* have thread local
* shapes are dictionaries that were allocated/converted thread
* locally. Only for those objects we can try to claim an entry in its
* shape table.
*/
// Search for id in order to claim its entry if table has been allocated.
AutoKeepShapeTables keep(cx);
ShapeTable::Entry* entry;
RootedShape shape(cx);
@ -945,16 +929,12 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
}
if (!shape) {
/*
* You can't add properties to a non-extensible object, but you can change
* attributes of properties in such objects.
*/
MOZ_ASSERT(obj->nonProxyIsExtensible());
MOZ_ASSERT(obj->nonProxyIsExtensible(),
"Can't add new property to non-extensible object");
return addAccessorPropertyInternal(cx, obj, id, getter, setter, attrs, entry, keep);
}
/* Property exists: search must have returned a valid entry. */
// Property exists: search must have returned a valid entry.
MOZ_ASSERT_IF(entry, !entry->isRemoved());
AssertCanChangeAttrs(shape, attrs);
@ -970,18 +950,14 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
return nullptr;
}
/*
* Now that we've possibly preserved slot, check whether all members match.
* If so, this is a redundant "put" and we can return without more work.
*/
if (shape->matchesParamsAfterId(nbase, SHAPE_INVALID_SLOT, attrs, 0, getter, setter))
// Check whether all members match. If so, this is a redundant "put" and we can
// return without more work.
if (shape->matchesParamsAfterId(nbase, SHAPE_INVALID_SLOT, attrs, getter, setter))
return shape;
/*
* Overwriting a non-last property requires switching to dictionary mode.
* The shape tree is shared immutable, and we can't removeProperty and then
* addPropertyInternal because a failure under add would lose data.
*/
// Overwriting a non-last property requires switching to dictionary mode.
// The shape tree is shared immutable, and we can't removeProperty and then
// addAccessorPropertyInternal because a failure under add would lose data.
if (shape != obj->lastProperty() && !obj->inDictionaryMode()) {
if (!toDictionaryMode(cx, obj))
return nullptr;
@ -992,12 +968,10 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
}
if (obj->inDictionaryMode()) {
/*
* Updating some property in a dictionary-mode object. Create a new
* shape for the existing property, and also generate a new shape for
* the last property of the dictionary (unless the modified property
* is also the last property).
*/
// Updating some property in a dictionary-mode object. Create a new
// shape for the existing property, and also generate a new shape for
// the last property of the dictionary (unless the modified property
// is also the last property).
bool updateLast = (shape == obj->lastProperty());
shape = NativeObject::replaceWithNewEquivalentShape(cx, obj, shape, nullptr,
/* accessorShape = */ true);
@ -1020,10 +994,8 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
accShape.rawSetter = setter;
GetterSetterWriteBarrierPost(&accShape);
} else {
/*
* Updating the last property in a non-dictionary-mode object. Find an
* alternate shared child of the last property's previous shape.
*/
// Updating the last property in a non-dictionary-mode object. Find an
// alternate shared child of the last property's previous shape.
StackBaseShape base(obj->lastProperty()->base());
UnownedBaseShape* nbase = BaseShape::getUnowned(cx, base);
@ -1032,21 +1004,19 @@ NativeObject::putAccessorProperty(JSContext* cx, HandleNativeObject obj, HandleI
MOZ_ASSERT(shape == obj->lastProperty());
/* Find or create a property tree node labeled by our arguments. */
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs, 0));
// Find or create a property tree node labeled by our arguments.
Rooted<StackShape> child(cx, StackShape(nbase, id, SHAPE_INVALID_SLOT, attrs));
child.updateGetterSetter(getter, setter);
RootedShape parent(cx, shape->parent);
shape = getChildProperty(cx, obj, parent, &child);
shape = getChildAccessorProperty(cx, obj, parent, &child);
if (!shape)
return nullptr;
}
/*
* Can't fail now, so free the previous incarnation's slot. But we do not
* need to free oldSlot (and must not, as trying to will botch an assertion
* in JSObject::freeSlot) if the new last property (shape here) has a
* slotSpan that does not cover it.
*/
// Can't fail now, so free the previous incarnation's slot. But we do not
// need to free oldSlot (and must not, as trying to will botch an assertion
// in NativeObject::freeSlot) if the new last property (shape here) has a
// slotSpan that does not cover it.
if (hadSlot && oldSlot < obj->slotSpan())
obj->freeSlot(cx, oldSlot);
@ -1858,8 +1828,7 @@ Shape::fixupShapeTreeAfterMovingGC()
StackShape lookup(unowned,
const_cast<Shape*>(key)->propidRef(),
key->slotInfo & Shape::SLOT_MASK,
key->attrs,
key->flags);
key->attrs);
lookup.updateGetterSetter(getter, setter);
e.rekeyFront(lookup, key);
}

View file

@ -994,13 +994,13 @@ class Shape : public gc::TenuredCell
bool matches(const Shape* other) const {
return propid_.get() == other->propid_.get() &&
matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs, other->flags,
matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
other->getter(), other->setter());
}
inline bool matches(const StackShape& other) const;
bool matchesParamsAfterId(BaseShape* base, uint32_t aslot, unsigned aattrs, unsigned aflags,
bool matchesParamsAfterId(BaseShape* base, uint32_t aslot, unsigned aattrs,
GetterOp rawGetter, SetterOp rawSetter) const
{
return base->unowned() == this->base()->unowned() &&
@ -1443,14 +1443,14 @@ struct StackShape
uint8_t flags;
explicit StackShape(UnownedBaseShape* base, jsid propid, uint32_t slot,
unsigned attrs, unsigned flags)
unsigned attrs)
: base(base),
propid(propid),
rawGetter(nullptr),
rawSetter(nullptr),
slot_(slot),
attrs(uint8_t(attrs)),
flags(uint8_t(flags))
flags(0)
{
MOZ_ASSERT(base);
MOZ_ASSERT(!JSID_IS_VOID(propid));
@ -1623,7 +1623,7 @@ inline bool
Shape::matches(const StackShape& other) const
{
return propid_.get() == other.propid &&
matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags,
matchesParamsAfterId(other.base, other.slot_, other.attrs,
other.rawGetter, other.rawSetter);
}

View file

@ -398,8 +398,10 @@ MakeReplacementTemplateObject(JSContext* cx, HandleObjectGroup group, const Unbo
for (size_t i = 0; i < layout.properties().length(); i++) {
const UnboxedLayout::Property& property = layout.properties()[i];
id = NameToId(property.name);
if (!NativeObject::addDataProperty(cx, obj, id, i, JSPROP_ENUMERATE))
Shape* shape = NativeObject::addDataProperty(cx, obj, id, SHAPE_INVALID_SLOT, JSPROP_ENUMERATE);
if (!shape)
return nullptr;
MOZ_ASSERT(shape->slot() == i);
MOZ_ASSERT(obj->slotSpan() == i + 1);
MOZ_ASSERT(!obj->inDictionaryMode());
}
@ -485,7 +487,7 @@ UnboxedLayout::makeNativeGroup(JSContext* cx, ObjectGroup* group)
const UnboxedLayout::Property& property = layout.properties()[i];
Rooted<StackShape> child(cx, StackShape(shape->base()->unowned(), NameToId(property.name),
i, JSPROP_ENUMERATE, 0));
i, JSPROP_ENUMERATE));
shape = cx->zone()->propertyTree().getChild(cx, shape, child);
if (!shape)
return false;

View file

@ -126,6 +126,13 @@ class ProcessCodeSegmentMap
MOZ_ASSERT(segments2_.empty());
}
void freeAll() {
MOZ_ASSERT(segments1_.empty());
MOZ_ASSERT(segments2_.empty());
segments1_.clearAndFree();
segments2_.clearAndFree();
}
bool insert(const CodeSegment* cs) {
LockGuard<Mutex> lock(mutatorsMutex_);
@ -230,3 +237,9 @@ wasm::LookupCode(const void* pc)
const CodeSegment* found = LookupCodeSegment(pc);
return found ? found->code() : nullptr;
}
void
wasm::ShutDownProcessStaticData()
{
processCodeSegmentMap.freeAll();
}

View file

@ -51,6 +51,9 @@ RegisterCodeSegment(const CodeSegment* cs);
void
UnregisterCodeSegment(const CodeSegment* cs);
void
ShutDownProcessStaticData();
} // namespace wasm
} // namespace js

View file

@ -249,7 +249,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
"$`", "$'", Symbol.species])
gPrototypeProperties['Promise'] =
["constructor", "catch", "then", Symbol.toStringTag];
["constructor", "catch", "then", "finally", Symbol.toStringTag];
gConstructorProperties['Promise'] =
constructorProps(["resolve", "reject", "all", "race", Symbol.species]);

View file

@ -742,6 +742,7 @@ nsIPresShell::nsIPresShell()
, mAutoWeakFrames(nullptr)
, mCanvasBackgroundColor(NS_RGBA(0,0,0,0))
, mSelectionFlags(0)
, mChangeNestCount(0)
, mRenderFlags(0)
, mDidInitialize(false)
, mIsDestroying(false)
@ -787,7 +788,6 @@ PresShell::PresShell()
, mLastReflowStart(0.0)
, mLastAnchorScrollPositionY(0)
, mAPZFocusSequenceNumber(0)
, mChangeNestCount(0)
, mDocumentLoading(false)
, mIgnoreFrameDestruction(false)
, mHaveShutDown(false)
@ -3075,10 +3075,9 @@ PresShell::GoToAnchor(const nsAString& aAnchorName, bool aScroll,
// Search for an anchor element with a matching "name" attribute
if (!content && htmlDoc) {
nsCOMPtr<nsIDOMNodeList> list;
// Find a matching list of named nodes
rv = htmlDoc->GetElementsByName(aAnchorName, getter_AddRefs(list));
if (NS_SUCCEEDED(rv) && list) {
nsCOMPtr<nsIDOMNodeList> list = mDocument->GetElementsByName(aAnchorName);
if (list) {
uint32_t i;
// Loop through the named nodes looking for the first anchor
for (i = 0; true; i++) {
@ -4038,25 +4037,23 @@ PresShell::HandlePostedReflowCallbacks(bool aInterruptible)
}
bool
PresShell::IsSafeToFlush() const
nsIPresShell::IsSafeToFlush() const
{
// Not safe if we are reflowing or in the middle of frame construction
bool isSafeToFlush = !mIsReflowing &&
!mChangeNestCount;
if (mIsReflowing || mChangeNestCount) {
return false;
}
if (isSafeToFlush) {
// Not safe if we are painting
nsViewManager* viewManager = GetViewManager();
if (viewManager) {
bool isPainting = false;
viewManager->IsPainting(isPainting);
if (isPainting) {
isSafeToFlush = false;
}
if (nsViewManager* viewManager = GetViewManager()) {
bool isPainting = false;
viewManager->IsPainting(isPainting);
if (isPainting) {
return false;
}
}
return isSafeToFlush;
return true;
}

View file

@ -128,7 +128,6 @@ public:
eInferFromBitToAdd) override;
virtual void FrameNeedsToContinueReflow(nsIFrame *aFrame) override;
virtual void CancelAllPendingReflows() override;
virtual bool IsSafeToFlush() const override;
virtual void DoFlushPendingNotifications(mozilla::FlushType aType) override;
virtual void DoFlushPendingNotifications(mozilla::ChangesToFlush aType) override;
virtual void DestroyFramesForAndRestyle(mozilla::dom::Element* aElement) override;
@ -857,11 +856,6 @@ protected:
// The focus information needed for async keyboard scrolling
FocusTarget mAPZFocusTarget;
// This is used to protect ourselves from triggering reflow while in the
// middle of frame construction and the like... it really shouldn't be
// needed, one hopes, but it is for now.
uint16_t mChangeNestCount;
bool mDocumentLoading : 1;
bool mIgnoreFrameDestruction : 1;
bool mHaveShutDown : 1;

View file

@ -541,11 +541,9 @@ public:
virtual void RecordShadowStyleChange(mozilla::dom::ShadowRoot* aShadowRoot) = 0;
/**
* Determine if it is safe to flush all pending notifications
* @param aIsSafeToFlush true if it is safe, false otherwise.
*
* Determine if it is safe to flush all pending notifications.
*/
virtual bool IsSafeToFlush() const = 0;
bool IsSafeToFlush() const;
/**
* Flush pending notifications of the type specified. This method
@ -1708,6 +1706,11 @@ protected:
int16_t mSelectionFlags;
// This is used to protect ourselves from triggering reflow while in the
// middle of frame construction and the like... it really shouldn't be
// needed, one hopes, but it is for now.
uint16_t mChangeNestCount;
// Flags controlling how our document is rendered. These persist
// between paints and so are tied with retained layer pixels.
// PresShell flushes retained layers when the rendering state

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="UTF-8">
</head>
<body>
<div style="unicode-bidi: bidi-override;">u&#x0302;&#x0302;</div>
</body>
</html>

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function repeatManyTimes(s)
{
while (s.length < 0x8000)
s = s + s;
return s;
}
function boom()
{
var initialText =
"\u062A" + // ARABIC LETTER TEH
repeatManyTimes(
"\u2029" + // PARAGRAPH SEPARATOR
"\u202D" + // LEFT-TO-RIGHT OVERRIDE
" "
) +
"1"; // THE LONELIEST ASCII CHARACTER
var textNode = document.createTextNode(initialText);
document.getElementById("v").appendChild(textNode);
document.documentElement.offsetHeight;
textNode.data = "*" + textNode.data;
}
</script>
</head>
<body onload="boom();">
<div id="v" style="display: table-row; font-size: 500%;"></div>
</body>
</html>

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