forked from mirrors/gecko-dev
merge mozilla-inbound to mozilla-central. r=merge a=merge
This commit is contained in:
commit
a353221537
166 changed files with 1510 additions and 1556 deletions
|
|
@ -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;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIURI.h"
|
||||
class nsPresContext;
|
||||
class nsIPresShell;
|
||||
namespace mozilla {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include "jsapi.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsString.h"
|
||||
|
||||
|
|
|
|||
18
dom/canvas/crashtests/844280.html
Normal file
18
dom/canvas/crashtests/844280.html
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "ClientState.h"
|
||||
|
||||
#include "mozilla/dom/ClientIPCTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
22
dom/html/crashtests/768344.html
Normal file
22
dom/html/crashtests/768344.html
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
19
dom/media/test/crashtests/1267263.html
Normal file
19
dom/media/test/crashtests/1267263.html
Normal 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>
|
||||
32
dom/media/test/crashtests/1389304.html
Normal file
32
dom/media/test/crashtests/1389304.html
Normal 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>
|
||||
BIN
dom/media/test/crashtests/1389304.mp4
Normal file
BIN
dom/media/test/crashtests/1389304.mp4
Normal file
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
6
gfx/tests/crashtests/766422-1.html
Normal file
6
gfx/tests/crashtests/766422-1.html
Normal 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>
|
||||
17
gfx/tests/crashtests/766422-2.html
Normal file
17
gfx/tests/crashtests/766422-2.html
Normal 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>
|
||||
7
gfx/tests/crashtests/951893.xhtml
Normal file
7
gfx/tests/crashtests/951893.xhtml
Normal 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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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__
|
||||
|
||||
|
|
@ -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];
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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'
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[DEFAULT]
|
||||
head =
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
37
js/src/jit-test/tests/ion/rinstructions-no-sse4.js
Normal file
37
js/src/jit-test/tests/ion/rinstructions-no-sse4.js
Normal 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);
|
||||
}
|
||||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -7017,6 +7017,7 @@ class MMathFunction
|
|||
switch(function_) {
|
||||
case Sin:
|
||||
case Log:
|
||||
case Floor:
|
||||
case Round:
|
||||
return true;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ void JSAPITest::uninit()
|
|||
destroyContext();
|
||||
cx = nullptr;
|
||||
}
|
||||
msgs.clear();
|
||||
}
|
||||
|
||||
bool JSAPITest::exec(const char* bytes, const char* filename, int lineno)
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ UNSUPPORTED_FEATURES = set([
|
|||
"tail-call-optimization",
|
||||
"BigInt",
|
||||
"class-fields",
|
||||
"Promise.prototype.finally",
|
||||
"optional-catch-binding",
|
||||
"regexp-dotall",
|
||||
"regexp-lookbehind",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
/*---
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ RegisterCodeSegment(const CodeSegment* cs);
|
|||
void
|
||||
UnregisterCodeSegment(const CodeSegment* cs);
|
||||
|
||||
void
|
||||
ShutDownProcessStaticData();
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
9
layout/generic/crashtests/849987.html
Normal file
9
layout/generic/crashtests/849987.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div style="unicode-bidi: bidi-override;">û̂</div>
|
||||
</body>
|
||||
</html>
|
||||
37
layout/generic/crashtests/963878.html
Normal file
37
layout/generic/crashtests/963878.html
Normal 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
Loading…
Reference in a new issue