mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound and m-c. IGNORE BAD COMMIT MESSAGES
This commit is contained in:
commit
a6fa56a5d3
@ -1150,3 +1150,7 @@ function closeBrowserWindow(window, callback) {
|
||||
}, false);
|
||||
window.close();
|
||||
}
|
||||
|
||||
// Test disabled on Linux because of bug 882867
|
||||
if (require("sdk/system/runtime").OS == "Linux")
|
||||
module.exports = {};
|
||||
|
@ -488,17 +488,22 @@
|
||||
<handlers>
|
||||
<handler event="command"><![CDATA[
|
||||
const target = event.originalTarget;
|
||||
if (target.classList.contains("addengine-item")) {
|
||||
if (target.engine) {
|
||||
this.currentEngine = target.engine;
|
||||
} else if (target.classList.contains("addengine-item")) {
|
||||
var searchService =
|
||||
Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
// We only detect OpenSearch files
|
||||
var type = Components.interfaces.nsISearchEngine.DATA_XML;
|
||||
// Select the installed engine if the installation succeeds
|
||||
var installCallback = {
|
||||
onSuccess: engine => this.currentEngine = engine
|
||||
}
|
||||
searchService.addEngine(target.getAttribute("uri"), type,
|
||||
target.getAttribute("src"), false);
|
||||
target.getAttribute("src"), false,
|
||||
installCallback);
|
||||
}
|
||||
else if (target.engine)
|
||||
this.currentEngine = target.engine;
|
||||
else
|
||||
return;
|
||||
|
||||
|
@ -30,8 +30,7 @@ function test() {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName("Bug 426329");
|
||||
ok(engine, "Engine was added.");
|
||||
//XXX Bug 493051
|
||||
//ss.currentEngine = engine;
|
||||
ss.currentEngine = engine;
|
||||
break;
|
||||
case "engine-current":
|
||||
ok(ss.currentEngine.name == "Bug 426329", "currentEngine set");
|
||||
|
@ -16,8 +16,7 @@ function test() {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName(ENGINE_NAME);
|
||||
ok(engine, "Engine was added.");
|
||||
//XXX Bug 493051
|
||||
//ss.currentEngine = engine;
|
||||
ss.currentEngine = engine;
|
||||
break;
|
||||
case "engine-current":
|
||||
is(ss.currentEngine.name, ENGINE_NAME, "currentEngine set");
|
||||
|
@ -42,20 +42,18 @@ function test() {
|
||||
}
|
||||
|
||||
function addEngine(aCallback) {
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-current":
|
||||
ok(Services.search.currentEngine.name == "Bug 426329",
|
||||
"currentEngine set");
|
||||
aCallback();
|
||||
break;
|
||||
let installCallback = {
|
||||
onSuccess: function (engine) {
|
||||
Services.search.currentEngine = engine;
|
||||
aCallback();
|
||||
},
|
||||
onError: function (errorCode) {
|
||||
ok(false, "failed to install engine: " + errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
Services.search.addEngine(
|
||||
engineURL + "426329.xml", Ci.nsISearchEngine.DATA_XML,
|
||||
"data:image/x-icon,%00", false);
|
||||
};
|
||||
Services.search.addEngine(engineURL + "426329.xml",
|
||||
Ci.nsISearchEngine.DATA_XML,
|
||||
"data:image/x-icon,%00", false, installCallback);
|
||||
}
|
||||
|
||||
function testOnWindow(aIsPrivate, aCallback) {
|
||||
|
@ -832,16 +832,7 @@ var SelectionHelperUI = {
|
||||
return;
|
||||
}
|
||||
|
||||
let selectionTap = this._hitTestSelection(aEvent);
|
||||
|
||||
// If the tap is in the selection, just ignore it. We disallow this
|
||||
// since we always get a single tap before a double, and double tap
|
||||
// copies selected text.
|
||||
if (selectionTap) {
|
||||
if (!this._targetIsEditable) {
|
||||
this.closeEditSession(false);
|
||||
return;
|
||||
}
|
||||
if (this._hitTestSelection(aEvent) && this._targetIsEditable) {
|
||||
// Attach to the newly placed caret position
|
||||
this._sendAsyncMessage("Browser:CaretAttach", {
|
||||
xPos: aEvent.clientX,
|
||||
@ -855,12 +846,11 @@ var SelectionHelperUI = {
|
||||
if (this.startMark.visible && pointInTargetElement &&
|
||||
this._targetIsEditable) {
|
||||
this._transitionFromSelectionToCaret(clientCoords.x, clientCoords.y);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have active selection in anything else don't let the event get
|
||||
// to content. Prevents random taps from killing active selection.
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
// Close when we get a single tap in content.
|
||||
this.closeEditSession(false);
|
||||
},
|
||||
|
||||
_onKeypress: function _onKeypress() {
|
||||
|
@ -306,11 +306,9 @@ gTests.push({
|
||||
},
|
||||
});
|
||||
|
||||
/*
|
||||
disable until bug 860248 is addressed.
|
||||
gTests.push({
|
||||
desc: "double-tap copy text in content",
|
||||
setUp: setUpHelper,
|
||||
desc: "tap on selection clears selection in content",
|
||||
setUp: setUpAndTearDown,
|
||||
run: function test() {
|
||||
|
||||
sendContextMenuClick(30, 20);
|
||||
@ -319,102 +317,35 @@ gTests.push({
|
||||
return SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
|
||||
sendDoubleTap(gWindow, 30, 20);
|
||||
sendTap(gWindow, 30, 20);
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return !SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
|
||||
// check copy text results
|
||||
let text = SpecialPowers.getClipboardData("text/unicode").trim();
|
||||
is(text, "There", "copy text test");
|
||||
|
||||
// check for active selection
|
||||
is(getTrimmedSelection(gWindow).toString(), "", "selection test");
|
||||
},
|
||||
tearDown: tearDownHelper,
|
||||
tearDown: setUpAndTearDown,
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "double-tap copy text in scrolled content",
|
||||
setUp: setUpHelper,
|
||||
desc: "tap off selection clears selection in content",
|
||||
setUp: setUpAndTearDown,
|
||||
run: function test() {
|
||||
let scrollPromise = waitForEvent(gWindow, "scroll");
|
||||
gWindow.scrollBy(0, 200);
|
||||
yield scrollPromise;
|
||||
ok(scrollPromise && !(scrollPromise instanceof Error), "scrollPromise error");
|
||||
|
||||
sendContextMenuClick(30, 100);
|
||||
sendContextMenuClick(30, 20);
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
|
||||
sendDoubleTap(gWindow, 42, 100);
|
||||
sendTap(gWindow, 30, 100);
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return !SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
|
||||
// check copy text results
|
||||
let text = SpecialPowers.getClipboardData("text/unicode");
|
||||
is(text, "suddenly", "copy text test");
|
||||
|
||||
// check for active selection
|
||||
is(getTrimmedSelection(gWindow).toString(), "", "selection test");
|
||||
},
|
||||
tearDown: function tearDown() {
|
||||
emptyClipboard();
|
||||
clearSelection(gWindow);
|
||||
let scrollPromise = waitForEvent(gWindow, "scroll");
|
||||
gWindow.scrollBy(0, -200);
|
||||
yield scrollPromise;
|
||||
yield waitForCondition(function () {
|
||||
return !SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
},
|
||||
tearDown: setUpAndTearDown,
|
||||
});
|
||||
|
||||
gTests.push({
|
||||
desc: "single clicks on selection in non-editable content",
|
||||
setUp: setUpHelper,
|
||||
run: function test() {
|
||||
sendContextMenuClick(100, 20);
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return SelectionHelperUI.isSelectionUIVisible;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
|
||||
// active state
|
||||
is(SelectionHelperUI.isActive, true, "selection active");
|
||||
|
||||
let ypos = SelectionHelperUI.endMark.yPos + kMarkerOffsetY;
|
||||
let touchdrag = new TouchDragAndHold();
|
||||
yield touchdrag.start(gWindow, SelectionHelperUI.endMark.xPos, ypos, 190, ypos);
|
||||
touchdrag.end();
|
||||
|
||||
yield waitForCondition(function () {
|
||||
return !SelectionHelperUI.hasActiveDrag;
|
||||
}, kCommonWaitMs, kCommonPollMs);
|
||||
yield SelectionHelperUI.pingSelectionHandler();
|
||||
|
||||
// active state
|
||||
is(SelectionHelperUI.isActive, true, "selection active");
|
||||
|
||||
// click on selected text - nothing should change
|
||||
sendTap(gWindow, 240, 20);
|
||||
|
||||
is(SelectionHelperUI.isActive, true, "selection active");
|
||||
|
||||
// click outside the text - nothing should change
|
||||
sendTap(gWindow, 197, 119);
|
||||
|
||||
is(SelectionHelperUI.isActive, true, "selection active");
|
||||
},
|
||||
tearDown: tearDownHelper,
|
||||
});
|
||||
*/
|
||||
|
||||
function test() {
|
||||
if (!isLandscapeMode()) {
|
||||
todo(false, "browser_selection_tests need landscape mode to run.");
|
||||
|
@ -40,6 +40,14 @@ CString sFirefoxPath;
|
||||
// startup command line paramters.
|
||||
#define kMetroTestFile "tests.ini"
|
||||
|
||||
// Process exit codes for buildbotcustom logic. These are currently ignored, but
|
||||
// at some point releng expects to use these.
|
||||
#define SUCCESS 0
|
||||
#define WARNINGS 1
|
||||
#define FAILURE 2
|
||||
#define EXCEPTION 3
|
||||
#define RETRY 4
|
||||
|
||||
static void Log(const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list a = NULL;
|
||||
@ -56,7 +64,7 @@ static void Log(const wchar_t *fmt, ...)
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void Fail(const wchar_t *fmt, ...)
|
||||
static void Fail(bool aRequestRetry, const wchar_t *fmt, ...)
|
||||
{
|
||||
va_list a = NULL;
|
||||
wchar_t szDebugString[1024];
|
||||
@ -67,8 +75,11 @@ static void Fail(const wchar_t *fmt, ...)
|
||||
va_end(a);
|
||||
if(!lstrlenW(szDebugString))
|
||||
return;
|
||||
|
||||
wprintf(L"TEST-UNEXPECTED-FAIL | metrotestharness.exe | %s\n", szDebugString);
|
||||
if (aRequestRetry) {
|
||||
wprintf(L"FAIL-SHOULD-RETRY | metrotestharness.exe | %s\n", szDebugString);
|
||||
} else {
|
||||
wprintf(L"TEST-UNEXPECTED-FAIL | metrotestharness.exe | %s\n", szDebugString);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
@ -83,7 +94,7 @@ static bool GetModulePath(CStringW& aPathBuffer)
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
if (!GetModuleFileName(NULL, buffer, MAX_PATH)) {
|
||||
Fail(L"GetModuleFileName failed.");
|
||||
Fail(false, L"GetModuleFileName failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -190,13 +201,6 @@ static void ReadPipe()
|
||||
}
|
||||
}
|
||||
|
||||
// From buildbotcustom logic:
|
||||
#define SUCCESS 0
|
||||
#define WARNINGS 1
|
||||
#define FAILURE 2
|
||||
#define EXCEPTION 3
|
||||
#define RETRY 4 /* will retry endlessly on new slaves, be careful with this! */
|
||||
|
||||
static int Launch()
|
||||
{
|
||||
Log(L"Launching browser...");
|
||||
@ -209,7 +213,7 @@ static int Launch()
|
||||
CLSCTX_LOCAL_SERVER,
|
||||
IID_IApplicationActivationManager,
|
||||
(void**)&activateMgr))) {
|
||||
Fail(L"CoCreateInstance CLSID_ApplicationActivationManager failed.");
|
||||
Fail(false, L"CoCreateInstance CLSID_ApplicationActivationManager failed.");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -217,7 +221,7 @@ static int Launch()
|
||||
WCHAR appModelID[256];
|
||||
// Activation is based on the browser's registered app model id
|
||||
if (!GetDefaultBrowserAppModelID(appModelID, (sizeof(appModelID)/sizeof(WCHAR)))) {
|
||||
Fail(L"GetDefaultBrowserAppModelID failed.");
|
||||
Fail(false, L"GetDefaultBrowserAppModelID failed.");
|
||||
return FAILURE;
|
||||
}
|
||||
Log(L"App model id='%s'", appModelID);
|
||||
@ -251,7 +255,7 @@ static int Launch()
|
||||
// Use the firefoxpath passed to us by the test harness
|
||||
int index = sFirefoxPath.ReverseFind('\\');
|
||||
if (index == -1) {
|
||||
Fail(L"Bad firefoxpath path");
|
||||
Fail(false, L"Bad firefoxpath path");
|
||||
return FAILURE;
|
||||
}
|
||||
testFilePath = sFirefoxPath.Mid(0, index);
|
||||
@ -261,7 +265,7 @@ static int Launch()
|
||||
// Use the module path
|
||||
char path[MAX_PATH];
|
||||
if (!GetModuleFileNameA(NULL, path, MAX_PATH)) {
|
||||
Fail(L"GetModuleFileNameA errorno=%d", GetLastError());
|
||||
Fail(false, L"GetModuleFileNameA errorno=%d", GetLastError());
|
||||
return FAILURE;
|
||||
}
|
||||
char* slash = strrchr(path, '\\');
|
||||
@ -277,7 +281,7 @@ static int Launch()
|
||||
|
||||
// Make sure the firefox bin exists
|
||||
if (GetFileAttributesW(sFirefoxPath) == INVALID_FILE_ATTRIBUTES) {
|
||||
Fail(L"Invalid bin path: '%s'", sFirefoxPath);
|
||||
Fail(false, L"Invalid bin path: '%s'", sFirefoxPath);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -289,7 +293,7 @@ static int Launch()
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hTestFile == INVALID_HANDLE_VALUE) {
|
||||
Fail(L"CreateFileA errorno=%d", GetLastError());
|
||||
Fail(false, L"CreateFileA errorno=%d", GetLastError());
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@ -304,7 +308,7 @@ static int Launch()
|
||||
Log(L"Browser command line args: '%s'", CString(asciiParams));
|
||||
if (!WriteFile(hTestFile, asciiParams, asciiParams.GetLength(), NULL, 0)) {
|
||||
CloseHandle(hTestFile);
|
||||
Fail(L"WriteFile errorno=%d", GetLastError());
|
||||
Fail(false, L"WriteFile errorno=%d", GetLastError());
|
||||
return FAILURE;
|
||||
}
|
||||
FlushFileBuffers(hTestFile);
|
||||
@ -312,14 +316,14 @@ static int Launch()
|
||||
|
||||
// Create a named stdout pipe for the browser
|
||||
if (!SetupTestOutputPipe()) {
|
||||
Fail(L"SetupTestOutputPipe failed (errno=%d)", GetLastError());
|
||||
Fail(false, L"SetupTestOutputPipe failed (errno=%d)", GetLastError());
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// Launch firefox
|
||||
hr = activateMgr->ActivateApplication(appModelID, L"", AO_NOERRORUI, &processID);
|
||||
if (FAILED(hr)) {
|
||||
Fail(L"ActivateApplication result %X", hr);
|
||||
Fail(true, L"ActivateApplication result %X", hr);
|
||||
return RETRY;
|
||||
}
|
||||
|
||||
@ -327,7 +331,7 @@ static int Launch()
|
||||
|
||||
HANDLE child = OpenProcess(SYNCHRONIZE, FALSE, processID);
|
||||
if (!child) {
|
||||
Fail(L"Couldn't find child process. (%d)", GetLastError());
|
||||
Fail(false, L"Couldn't find child process. (%d)", GetLastError());
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
@ -305,6 +305,19 @@ case "$target" in
|
||||
if test ! -d "$android_platform_tools" ; then
|
||||
android_platform_tools="$android_sdk"/tools # SDK Tools < r8
|
||||
fi
|
||||
# The build tools got moved around to different directories in
|
||||
# SDK Tools r22. Try to locate them.
|
||||
android_build_tools=""
|
||||
for suffix in 17.0.0 android-4.2.2; do
|
||||
tools_directory="$android_sdk/../../build-tools/$suffix"
|
||||
if test -d "$tools_directory" ; then
|
||||
android_build_tools="$tools_directory"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$android_build_tools" ; then
|
||||
android_build_tools="$android_platform_tools" # SDK Tools < r22
|
||||
fi
|
||||
ANDROID_SDK="${android_sdk}"
|
||||
if test -e "${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar" ; then
|
||||
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar"
|
||||
@ -312,12 +325,14 @@ case "$target" in
|
||||
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/support/v4/android-support-v4.jar";
|
||||
fi
|
||||
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
|
||||
ANDROID_BUILD_TOOLS="${android_build_tools}"
|
||||
AC_SUBST(ANDROID_SDK)
|
||||
AC_SUBST(ANDROID_COMPAT_LIB)
|
||||
if ! test -e $ANDROID_COMPAT_LIB ; then
|
||||
AC_MSG_ERROR([You must download the Android support library when targeting Android. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_COMPAT_LIB)])
|
||||
fi
|
||||
AC_SUBST(ANDROID_PLATFORM_TOOLS)
|
||||
AC_SUBST(ANDROID_BUILD_TOOLS)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -13,6 +13,8 @@ dir-tests := $(DEPTH)/$(mobile-tests)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := robocop-debug
|
||||
|
||||
ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.6.jar
|
||||
|
||||
JAVAFILES = \
|
||||
@ -81,9 +83,10 @@ GARBAGE += \
|
||||
$(java-tests-dep) \
|
||||
$(_JAVA_HARNESS) \
|
||||
classes.dex \
|
||||
robocop.ap_ \
|
||||
robocop-debug-signed.apk \
|
||||
robocop-debug-signed-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(robocop-deps) \
|
||||
$(NULL)
|
||||
|
||||
@ -100,23 +103,28 @@ include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
GENERATED_DIRS_tools = classes $(dir-tests)
|
||||
|
||||
libs:: robocop-debug-signed.apk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
classes.dex: robocop.ap_
|
||||
classes.dex: $(ANDROID_APK_NAME).ap_
|
||||
classes.dex: $(robocop-deps)
|
||||
classes.dex: $(java-harness-dep)
|
||||
classes.dex: $(java-tests-dep)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(java-tests-dep)
|
||||
$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH) $(ANDROID_COMPT_LIB)
|
||||
|
||||
robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
|
||||
$(ANDROID_APK_NAME).ap_: AndroidManifest.xml $(TESTPATH)/assets/*
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
|
||||
|
||||
robocop-debug-signed-unaligned.apk: robocop.ap_ classes.dex
|
||||
$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z robocop.ap_ -f classes.dex
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
$(ZIP) -v0 $@ classes.dex
|
||||
|
||||
robocop-debug-signed.apk: robocop-debug-signed-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $^ $@
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $< $@
|
||||
|
||||
# PP_java-tests not fully usable here
|
||||
# Intermediate step toward a library rule.
|
||||
|
@ -9,6 +9,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := sutAgentAndroid
|
||||
|
||||
JAVAFILES = \
|
||||
AlertLooperThread.java \
|
||||
ASMozStub.java \
|
||||
@ -39,10 +41,10 @@ RES_FILES = \
|
||||
GARBAGE += \
|
||||
AndroidManifest.xml \
|
||||
classes.dex \
|
||||
sutAgentAndroid.apk \
|
||||
sutAgentAndroid.ap_ \
|
||||
sutAgentAndroid-unsigned-unaligned.apk \
|
||||
sutAgentAndroid-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE_DIRS += network-libs
|
||||
@ -56,23 +58,22 @@ include $(topsrcdir)/config/rules.mk
|
||||
# include Android specific java flags - using these instead of what's in rules.mk
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
tools:: sutAgentAndroid.apk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
classes.dex: $(JAVAFILES)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES))
|
||||
$(DX) --dex --output=$@ classes $(subst :, ,$(EXTRA_JARS))
|
||||
|
||||
sutAgentAndroid.ap_: $(srcdir)/AndroidManifest.xml
|
||||
$(ANDROID_APK_NAME).ap_: AndroidManifest.xml
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
|
||||
sutAgentAndroid-unsigned-unaligned.apk: sutAgentAndroid.ap_ classes.dex
|
||||
$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z sutAgentAndroid.ap_ -f classes.dex
|
||||
|
||||
sutAgentAndroid-unaligned.apk: sutAgentAndroid-unsigned-unaligned.apk
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
ifdef JARSIGNER
|
||||
$(JARSIGNER) $@
|
||||
endif
|
||||
$(ZIP) -v0 $@ classes.dex
|
||||
|
||||
sutAgentAndroid.apk: sutAgentAndroid-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 sutAgentAndroid-unaligned.apk $@
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $< $@
|
||||
|
@ -9,6 +9,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := FenCP
|
||||
|
||||
JAVAFILES = \
|
||||
DirCursor.java \
|
||||
FenCP.java \
|
||||
@ -28,7 +30,10 @@ RES_FILES = \
|
||||
GARBAGE += \
|
||||
AndroidManifest.xml \
|
||||
classes.dex \
|
||||
FenCP.apk \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE_DIRS += network-libs
|
||||
@ -40,23 +45,22 @@ include $(topsrcdir)/config/rules.mk
|
||||
# include Android specific java flags - using these instead of what's in rules.mk
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
tools:: FenCP.apk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
classes.dex: $(JAVAFILES)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES))
|
||||
$(DX) --dex --output=$@ classes
|
||||
|
||||
FenCP.ap_: $(srcdir)/AndroidManifest.xml
|
||||
$(AAPT) package -f -M $(srcdir)/AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
$(ANDROID_APK_NAME).ap_: AndroidManifest.xml
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
|
||||
FenCP-unsigned-unaligned.apk: FenCP.ap_ classes.dex
|
||||
$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z FenCP.ap_ -f classes.dex
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
$(ZIP) -v0 $@ classes.dex
|
||||
|
||||
FenCP-unaligned.apk: FenCP-unsigned-unaligned.apk
|
||||
cp FenCP-unsigned-unaligned.apk $@
|
||||
ifdef JARSIGNER
|
||||
$(JARSIGNER) $@
|
||||
endif
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
FenCP.apk: FenCP-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 FenCP-unaligned.apk $@
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $< $@
|
||||
|
@ -9,6 +9,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := FfxCP
|
||||
|
||||
JAVAFILES = \
|
||||
DirCursor.java \
|
||||
ffxcp.java \
|
||||
@ -28,7 +30,10 @@ RES_FILES = \
|
||||
GARBAGE += \
|
||||
AndroidManifest.xml \
|
||||
classes.dex \
|
||||
FfxCP.apk \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE_DIRS += network-libs
|
||||
@ -40,23 +45,22 @@ include $(topsrcdir)/config/rules.mk
|
||||
# include Android specific java flags - using these instead of what's in rules.mk
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
tools:: FfxCP.apk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
classes.dex: $(JAVAFILES)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES))
|
||||
$(DX) --dex --output=$@ classes
|
||||
|
||||
FfxCP.ap_: $(srcdir)/AndroidManifest.xml
|
||||
$(AAPT) package -f -M $(srcdir)/AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
$(ANDROID_APK_NAME).ap_: AndroidManifest.xml
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
|
||||
FfxCP-unsigned-unaligned.apk: FfxCP.ap_ classes.dex
|
||||
$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z FfxCP.ap_ -f classes.dex
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
$(ZIP) -v0 $@ classes.dex
|
||||
|
||||
FfxCP-unaligned.apk: FfxCP-unsigned-unaligned.apk
|
||||
cp FfxCP-unsigned-unaligned.apk $@
|
||||
ifdef JARSIGNER
|
||||
$(JARSIGNER) $@
|
||||
endif
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
FfxCP.apk: FfxCP-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 FfxCP-unaligned.apk $@
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $< $@
|
||||
|
@ -9,6 +9,8 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ANDROID_APK_NAME := Watcher
|
||||
|
||||
JAVAFILES = \
|
||||
IWatcherService.java \
|
||||
RedirOutputThread.java \
|
||||
@ -32,7 +34,10 @@ RES_FILES = \
|
||||
GARBAGE += \
|
||||
AndroidManifest.xml \
|
||||
classes.dex \
|
||||
Watcher.apk \
|
||||
$(ANDROID_APK_NAME).ap_ \
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk \
|
||||
$(ANDROID_APK_NAME)-unaligned.apk \
|
||||
$(ANDROID_APK_NAME).apk \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE_DIRS += res classes network-libs
|
||||
@ -44,29 +49,23 @@ include $(topsrcdir)/config/rules.mk
|
||||
# include Android specific java flags - using these instead of what's in rules.mk
|
||||
include $(topsrcdir)/config/android-common.mk
|
||||
|
||||
tools:: Watcher.apk
|
||||
tools:: $(ANDROID_APK_NAME).apk
|
||||
|
||||
classes.dex: $(JAVAFILES)
|
||||
$(NSINSTALL) -D classes
|
||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES))
|
||||
$(DX) --dex --output=$@ classes
|
||||
|
||||
Watcher.ap_: $(srcdir)/AndroidManifest.xml
|
||||
$(AAPT) package -f -M $(srcdir)/AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
$(ANDROID_APK_NAME).ap_: AndroidManifest.xml
|
||||
$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||
|
||||
Watcher-unsigned-unaligned.apk: Watcher.ap_ classes.dex
|
||||
$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z Watcher.ap_ -f classes.dex
|
||||
$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
|
||||
cp $< $@
|
||||
$(ZIP) -v0 $@ classes.dex
|
||||
|
||||
Watcher-unaligned.apk: Watcher-unsigned-unaligned.apk
|
||||
cp Watcher-unsigned-unaligned.apk $@
|
||||
ifdef JARSIGNER
|
||||
$(JARSIGNER) $@
|
||||
endif
|
||||
|
||||
Watcher.apk: Watcher-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 Watcher-unaligned.apk $@
|
||||
|
||||
export::
|
||||
$(NSINSTALL) -D res
|
||||
@(cd $(srcdir)/res && tar $(TAR_CREATE_FLAGS) - *) | (cd $(DEPTH)/build/mobile/sutagent/android/watcher/res && tar -xf -)
|
||||
$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
|
||||
cp $< $@
|
||||
$(DEBUG_JARSIGNER) $@
|
||||
|
||||
$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
|
||||
$(ZIPALIGN) -f -v 4 $< $@
|
||||
|
@ -21,7 +21,6 @@ STDCXX_COMPAT =
|
||||
|
||||
ifneq (WINNT,$(HOST_OS_ARCH))
|
||||
HOST_PROGRAM = nsinstall_real$(HOST_BIN_SUFFIX)
|
||||
DISABLED_HOST_CSRCS = nsinstall.c pathsub.c
|
||||
endif
|
||||
|
||||
ifndef CROSS_COMPILE
|
||||
|
@ -12,14 +12,11 @@ ifndef JAVA_CLASSPATH
|
||||
$(error JAVA_CLASSPATH must be defined before including android-common.mk)
|
||||
endif
|
||||
|
||||
DX=$(ANDROID_PLATFORM_TOOLS)/dx
|
||||
AAPT=$(ANDROID_PLATFORM_TOOLS)/aapt
|
||||
APKBUILDER=$(ANDROID_SDK)/../../tools/apkbuilder
|
||||
DX=$(ANDROID_BUILD_TOOLS)/dx
|
||||
AAPT=$(ANDROID_BUILD_TOOLS)/aapt
|
||||
ZIPALIGN=$(ANDROID_SDK)/../../tools/zipalign
|
||||
|
||||
ifdef JARSIGNER
|
||||
APKBUILDER_FLAGS += -u
|
||||
endif
|
||||
# DEBUG_JARSIGNER always debug signs.
|
||||
DEBUG_JARSIGNER=$(PYTHON) $(call core_abspath,$(topsrcdir)/mobile/android/debug_sign_tool.py)
|
||||
|
||||
# For Android, this defaults to $(ANDROID_SDK)/android.jar
|
||||
ifndef JAVA_BOOTCLASSPATH
|
||||
|
@ -16,6 +16,7 @@ endif
|
||||
# responsibility between Makefile.in and mozbuild files.
|
||||
_MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
DIRS \
|
||||
HOST_CSRCS \
|
||||
MODULE \
|
||||
PARALLEL_DIRS \
|
||||
TEST_DIRS \
|
||||
|
@ -510,17 +510,6 @@ public:
|
||||
static nsresult GuessCharset(const char *aData, uint32_t aDataLen,
|
||||
nsACString &aCharset);
|
||||
|
||||
/**
|
||||
* Determine whether aContent is in some way associated with aForm. If the
|
||||
* form is a container the only elements that are considered to be associated
|
||||
* with a form are the elements that are contained within the form. If the
|
||||
* form is a leaf element then all elements will be accepted into this list,
|
||||
* since this can happen due to content fixup when a form spans table rows or
|
||||
* table cells.
|
||||
*/
|
||||
static bool BelongsInForm(nsIContent *aForm,
|
||||
nsIContent *aContent);
|
||||
|
||||
static nsresult CheckQName(const nsAString& aQualifiedName,
|
||||
bool aNamespaceAware = true,
|
||||
const PRUnichar** aColon = nullptr);
|
||||
|
@ -140,26 +140,6 @@ nsSimpleContentList::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope)
|
||||
return NodeListBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
// nsFormContentList
|
||||
|
||||
nsFormContentList::nsFormContentList(nsIContent *aForm,
|
||||
nsBaseContentList& aContentList)
|
||||
: nsSimpleContentList(aForm)
|
||||
{
|
||||
|
||||
// move elements that belong to mForm into this content list
|
||||
|
||||
uint32_t i, length = 0;
|
||||
aContentList.GetLength(&length);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
nsIContent *c = aContentList.Item(i);
|
||||
if (c && nsContentUtils::BelongsInForm(aForm, c)) {
|
||||
AppendElement(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hashtable for storing nsContentLists
|
||||
static PLDHashTable gContentListHashTable;
|
||||
|
||||
|
@ -124,16 +124,6 @@ private:
|
||||
nsCOMPtr<nsINode> mRoot;
|
||||
};
|
||||
|
||||
// This class is used only by form element code and this is a static
|
||||
// list of elements. NOTE! This list holds strong references to
|
||||
// the elements in the list.
|
||||
class nsFormContentList : public nsSimpleContentList
|
||||
{
|
||||
public:
|
||||
nsFormContentList(nsIContent *aForm,
|
||||
nsBaseContentList& aContentList);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class that's used as the key to hash nsContentList implementations
|
||||
* for fast retrieval
|
||||
|
@ -2365,62 +2365,6 @@ nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
|
||||
aBaseURI, sIOService);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::BelongsInForm(nsIContent *aForm,
|
||||
nsIContent *aContent)
|
||||
{
|
||||
NS_PRECONDITION(aForm, "Must have a form");
|
||||
NS_PRECONDITION(aContent, "Must have a content node");
|
||||
|
||||
if (aForm == aContent) {
|
||||
// A form does not belong inside itself, so we return false here
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIContent* content = aContent->GetParent();
|
||||
|
||||
while (content) {
|
||||
if (content == aForm) {
|
||||
// aContent is contained within the form so we return true.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (content->Tag() == nsGkAtoms::form &&
|
||||
content->IsHTML()) {
|
||||
// The child is contained within a form, but not the right form
|
||||
// so we ignore it.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
content = content->GetParent();
|
||||
}
|
||||
|
||||
if (aForm->GetChildCount() > 0) {
|
||||
// The form is a container but aContent wasn't inside the form,
|
||||
// return false
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The form is a leaf and aContent wasn't inside any other form so
|
||||
// we check whether the content comes after the form. If it does,
|
||||
// return true. If it does not, then it couldn't have been inside
|
||||
// the form in the HTML.
|
||||
if (PositionIsBefore(aForm, aContent)) {
|
||||
// We could be in this form!
|
||||
// In the future, we may want to get document.forms, look at the
|
||||
// form after aForm, and if aContent is after that form after
|
||||
// aForm return false here....
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsContentUtils::CheckQName(const nsAString& aQualifiedName,
|
||||
|
@ -145,7 +145,7 @@ protected:
|
||||
nsString mResult;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
JSObject* mResultArrayBuffer;
|
||||
JS::Heap<JSObject*> mResultArrayBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1786,7 +1786,7 @@ struct CustomPrototypeTraceArgs {
|
||||
|
||||
|
||||
static PLDHashOperator
|
||||
CustomPrototypeTrace(const nsAString& aName, JSObject*& aObject, void *aArg)
|
||||
CustomPrototypeTrace(const nsAString& aName, JS::Heap<JSObject*>& aObject, void *aArg)
|
||||
{
|
||||
CustomPrototypeTraceArgs* traceArgs = static_cast<CustomPrototypeTraceArgs*>(aArg);
|
||||
MOZ_ASSERT(aObject, "Protocol object value must not be null");
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsJSThingHashtable.h"
|
||||
#include "nsIBoxObject.h"
|
||||
#include "nsPIBoxObject.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
@ -1203,7 +1204,7 @@ protected:
|
||||
|
||||
// Hashtable for custom element prototypes in web components.
|
||||
// Custom prototypes are in the document's compartment.
|
||||
nsDataHashtable<nsStringHashKey, JSObject*> mCustomPrototypes;
|
||||
nsJSThingHashtable<nsStringHashKey, JSObject*> mCustomPrototypes;
|
||||
|
||||
nsRefPtr<nsEventListenerManager> mListenerManager;
|
||||
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#endif
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
@ -216,6 +217,11 @@ nsNodeUtils::LastRelease(nsINode* aNode)
|
||||
// notify, since we're being destroyed in any case.
|
||||
static_cast<nsGenericHTMLFormElement*>(aNode)->ClearForm(true);
|
||||
}
|
||||
|
||||
if (aNode->IsElement() && aNode->AsElement()->IsHTML(nsGkAtoms::img)) {
|
||||
HTMLImageElement* imageElem = static_cast<HTMLImageElement*>(aNode);
|
||||
imageElem->ClearForm(true);
|
||||
}
|
||||
}
|
||||
aNode->UnsetFlags(NODE_HAS_PROPERTIES);
|
||||
|
||||
|
@ -782,12 +782,14 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
|
||||
RootJSResultObjects();
|
||||
|
||||
// The Unicode converter has already zapped the BOM if there was one
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
if (!JS_ParseJSON(aCx,
|
||||
static_cast<const jschar*>(mResponseText.get()), mResponseText.Length(),
|
||||
JS::MutableHandle<JS::Value>::fromMarkedLocation(&mResultJSON))) {
|
||||
&value)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mResultJSON = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -657,14 +657,14 @@ protected:
|
||||
|
||||
bool mFirstStartRequestSeen;
|
||||
bool mInLoadProgressEvent;
|
||||
|
||||
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
nsCOMPtr<nsIChannel> mNewRedirectChannel;
|
||||
|
||||
JS::Value mResultJSON;
|
||||
|
||||
JS::Heap<JS::Value> mResultJSON;
|
||||
|
||||
js::ArrayBufferBuilder mArrayBufferBuilder;
|
||||
JSObject* mResultArrayBuffer;
|
||||
JS::Heap<JSObject*> mResultArrayBuffer;
|
||||
|
||||
void ResetResponse();
|
||||
|
||||
|
@ -69,7 +69,7 @@ private:
|
||||
ImageData() MOZ_DELETE;
|
||||
|
||||
uint32_t mWidth, mHeight;
|
||||
JSObject* mData;
|
||||
JS::Heap<JSObject*> mData;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
JS::Value mData;
|
||||
JS::Heap<JS::Value> mData;
|
||||
nsString mOrigin;
|
||||
nsString mLastEventId;
|
||||
nsCOMPtr<nsIDOMWindow> mSource;
|
||||
|
@ -70,7 +70,7 @@ private:
|
||||
nsAutoArrayPtr<float> mFrameBuffer;
|
||||
uint32_t mFrameBufferLength;
|
||||
float mTime;
|
||||
JSObject* mCachedArray;
|
||||
JS::Heap<JSObject*> mCachedArray;
|
||||
bool mAllowAudioData;
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsHTMLFormElement.h"
|
||||
|
||||
#include "imgIContainer.h"
|
||||
#include "imgILoader.h"
|
||||
@ -67,6 +68,7 @@ namespace dom {
|
||||
|
||||
HTMLImageElement::HTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
, mForm(nullptr)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
@ -84,7 +86,7 @@ NS_IMPL_RELEASE_INHERITED(HTMLImageElement, Element)
|
||||
|
||||
|
||||
// QueryInterface implementation for HTMLImageElement
|
||||
NS_INTERFACE_TABLE_HEAD(HTMLImageElement)
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLImageElement)
|
||||
NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
|
||||
NS_INTERFACE_TABLE_INHERITED4(HTMLImageElement,
|
||||
nsIDOMHTMLImageElement,
|
||||
@ -296,6 +298,47 @@ HTMLImageElement::GetAttributeMappingFunction() const
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
bool aNotify)
|
||||
{
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None && mForm &&
|
||||
(aName == nsGkAtoms::name || aName == nsGkAtoms::id)) {
|
||||
// remove the image from the hashtable as needed
|
||||
nsAutoString tmp;
|
||||
GetAttr(kNameSpaceID_None, aName, tmp);
|
||||
|
||||
if (!tmp.IsEmpty()) {
|
||||
mForm->RemoveImageElementFromTable(this, tmp,
|
||||
nsHTMLFormElement::AttributeUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_None && mForm &&
|
||||
(aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
|
||||
aValue && !aValue->IsEmptyString()) {
|
||||
// add the image to the hashtable as needed
|
||||
NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
|
||||
"Expected atom value for name/id");
|
||||
mForm->AddImageElementToTable(this,
|
||||
nsDependentAtomString(aValue->GetAtomValue()));
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
||||
{
|
||||
@ -414,6 +457,10 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
|
||||
if (aParent) {
|
||||
UpdateFormOwner();
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||
// FIXME: Bug 660963 it would be nice if we could just have
|
||||
// ClearBrokenState update our state and do it fast...
|
||||
@ -434,10 +481,45 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
void
|
||||
HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
if (mForm) {
|
||||
if (aNullParent || !FindAncestorForm(mForm)) {
|
||||
ClearForm(true);
|
||||
} else {
|
||||
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::UpdateFormOwner()
|
||||
{
|
||||
if (!mForm) {
|
||||
mForm = FindAncestorForm();
|
||||
}
|
||||
|
||||
if (mForm && !HasFlag(ADDED_TO_FORM)) {
|
||||
// Now we need to add ourselves to the form
|
||||
nsAutoString nameVal, idVal;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
|
||||
|
||||
SetFlags(ADDED_TO_FORM);
|
||||
|
||||
mForm->AddImageElement(this);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->AddImageElementToTable(this, nameVal);
|
||||
}
|
||||
|
||||
if (!idVal.IsEmpty()) {
|
||||
mForm->AddImageElementToTable(this, idVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::MaybeLoadImage()
|
||||
{
|
||||
@ -577,5 +659,55 @@ HTMLImageElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return HTMLImageElementBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIDOMHTMLFormElement*
|
||||
HTMLImageElement::GetForm() const
|
||||
{
|
||||
return mForm;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
HTMLImageElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
||||
{
|
||||
NS_PRECONDITION(aForm, "Don't pass null here");
|
||||
NS_ASSERTION(!mForm,
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
mForm = static_cast<nsHTMLFormElement*>(aForm);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::ClearForm(bool aRemoveFromForm)
|
||||
{
|
||||
NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
|
||||
"Form control should have had flag set correctly");
|
||||
|
||||
if (!mForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRemoveFromForm) {
|
||||
nsAutoString nameVal, idVal;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
|
||||
|
||||
mForm->RemoveImageElement(this);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->RemoveImageElementFromTable(this, nameVal,
|
||||
nsHTMLFormElement::ElementRemoved);
|
||||
}
|
||||
|
||||
if (!idVal.IsEmpty()) {
|
||||
mForm->RemoveImageElementFromTable(this, idVal,
|
||||
nsHTMLFormElement::ElementRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
UnsetFlags(ADDED_TO_FORM);
|
||||
mForm = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -174,12 +174,30 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::lowsrc, aLowsrc, aError);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIDOMHTMLFormElement* GetForm() const;
|
||||
#endif
|
||||
void SetForm(nsIDOMHTMLFormElement* aForm);
|
||||
void ClearForm(bool aRemoveFromForm);
|
||||
|
||||
protected:
|
||||
CSSIntPoint GetXY();
|
||||
virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
|
||||
virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
|
||||
virtual JSObject* WrapNode(JSContext *aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
void UpdateFormOwner();
|
||||
|
||||
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
bool aNotify) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
|
||||
|
||||
// This is a weak reference that this element and the HTMLFormElement
|
||||
// cooperate in maintaining.
|
||||
nsHTMLFormElement* mForm;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -2179,11 +2179,13 @@ nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm)
|
||||
mForm->RemoveElement(this, true);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, nameVal);
|
||||
mForm->RemoveElementFromTable(this, nameVal,
|
||||
nsHTMLFormElement::ElementRemoved);
|
||||
}
|
||||
|
||||
if (!idVal.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, idVal);
|
||||
mForm->RemoveElementFromTable(this, idVal,
|
||||
nsHTMLFormElement::ElementRemoved);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2314,7 +2316,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
GetAttr(kNameSpaceID_None, aName, tmp);
|
||||
|
||||
if (!tmp.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, tmp);
|
||||
mForm->RemoveElementFromTable(this, tmp,
|
||||
nsHTMLFormElement::AttributeUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2322,13 +2325,15 @@ nsGenericHTMLFormElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
|
||||
|
||||
if (!tmp.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, tmp);
|
||||
mForm->RemoveElementFromTable(this, tmp,
|
||||
nsHTMLFormElement::AttributeUpdated);
|
||||
}
|
||||
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
|
||||
|
||||
if (!tmp.IsEmpty()) {
|
||||
mForm->RemoveElementFromTable(this, tmp);
|
||||
mForm->RemoveElementFromTable(this, tmp,
|
||||
nsHTMLFormElement::AttributeUpdated);
|
||||
}
|
||||
|
||||
mForm->RemoveElement(this, false);
|
||||
|
@ -1047,15 +1047,16 @@ class HTMLFieldSetElement;
|
||||
|
||||
// Form element specific bits
|
||||
enum {
|
||||
// If this flag is set on an nsGenericHTMLFormElement, that means that we have
|
||||
// added ourselves to our mForm. It's possible to have a non-null mForm, but
|
||||
// not have this flag set. That happens when the form is set via the content
|
||||
// sink.
|
||||
// If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement,
|
||||
// that means that we have added ourselves to our mForm. It's possible to
|
||||
// have a non-null mForm, but not have this flag set. That happens when the
|
||||
// form is set via the content sink.
|
||||
ADDED_TO_FORM = FORM_ELEMENT_FLAG_BIT(0),
|
||||
|
||||
// If this flag is set on an nsGenericHTMLFormElement, that means that its form
|
||||
// is in the process of being unbound from the tree, and this form element
|
||||
// hasn't re-found its form in nsGenericHTMLFormElement::UnbindFromTree yet.
|
||||
// If this flag is set on an nsGenericHTMLFormElement or an HTMLImageElement,
|
||||
// that means that its form is in the process of being unbound from the tree,
|
||||
// and this form element hasn't re-found its form in
|
||||
// nsGenericHTMLFormElement::UnbindFromTree yet.
|
||||
MAYBE_ORPHAN_FORM_ELEMENT = FORM_ELEMENT_FLAG_BIT(1)
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,9 @@
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
// images
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
|
||||
@ -104,6 +107,8 @@ public:
|
||||
|
||||
nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult AddImageElementToTable(HTMLImageElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
nsresult IndexOfControl(nsIFormControl* aControl,
|
||||
@ -241,6 +246,8 @@ nsHTMLFormElement::nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
mInvalidElementsCount(0),
|
||||
mEverTriedInvalidSubmit(false)
|
||||
{
|
||||
mImageNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
|
||||
mPastNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
|
||||
}
|
||||
|
||||
nsHTMLFormElement::~nsHTMLFormElement()
|
||||
@ -248,6 +255,8 @@ nsHTMLFormElement::~nsHTMLFormElement()
|
||||
if (mControls) {
|
||||
mControls->DropFormReference();
|
||||
}
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -290,9 +299,16 @@ ElementTraverser(const nsAString& key, nsIDOMHTMLInputElement* element,
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControls)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageNameLookupTable)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPastNameLookupTable)
|
||||
tmp->mSelectedRadioButtons.EnumerateRead(ElementTraverser, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
tmp->Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsHTMLFormElement, Element)
|
||||
NS_IMPL_RELEASE_INHERITED(nsHTMLFormElement, Element)
|
||||
|
||||
@ -455,8 +471,9 @@ nsHTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
return rv;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
MarkOrphans(const nsTArray<nsGenericHTMLFormElement*>& aArray)
|
||||
MarkOrphans(const nsTArray<T*>& aArray)
|
||||
{
|
||||
uint32_t length = aArray.Length();
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
@ -483,8 +500,7 @@ CollectOrphans(nsINode* aRemovalRoot,
|
||||
// Now if MAYBE_ORPHAN_FORM_ELEMENT is not set, that would mean that the
|
||||
// node is in fact a descendant of the form and hence should stay in the
|
||||
// form. If it _is_ set, then we need to check whether the node is a
|
||||
// descendant of aRemovalRoot. If it is, we leave it in the form. See
|
||||
// also the code in nsGenericHTMLFormElement::FindForm.
|
||||
// descendant of aRemovalRoot. If it is, we leave it in the form.
|
||||
#ifdef DEBUG
|
||||
bool removed = false;
|
||||
#endif
|
||||
@ -511,6 +527,46 @@ CollectOrphans(nsINode* aRemovalRoot,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CollectOrphans(nsINode* aRemovalRoot,
|
||||
const nsTArray<HTMLImageElement*>& aArray
|
||||
#ifdef DEBUG
|
||||
, nsIDOMHTMLFormElement* aThisForm
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Walk backwards so that if we remove elements we can just keep iterating
|
||||
uint32_t length = aArray.Length();
|
||||
for (uint32_t i = length; i > 0; --i) {
|
||||
HTMLImageElement* node = aArray[i-1];
|
||||
|
||||
// Now if MAYBE_ORPHAN_FORM_ELEMENT is not set, that would mean that the
|
||||
// node is in fact a descendant of the form and hence should stay in the
|
||||
// form. If it _is_ set, then we need to check whether the node is a
|
||||
// descendant of aRemovalRoot. If it is, we leave it in the form.
|
||||
#ifdef DEBUG
|
||||
bool removed = false;
|
||||
#endif
|
||||
if (node->HasFlag(MAYBE_ORPHAN_FORM_ELEMENT)) {
|
||||
node->UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
|
||||
node->ClearForm(true);
|
||||
|
||||
#ifdef DEBUG
|
||||
removed = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!removed) {
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form = node->GetForm();
|
||||
NS_ASSERTION(form == aThisForm, "How did that happen?");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
@ -519,6 +575,7 @@ nsHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
// Mark all of our controls as maybe being orphans
|
||||
MarkOrphans(mControls->mElements);
|
||||
MarkOrphans(mControls->mNotInElements);
|
||||
MarkOrphans(mImageElements);
|
||||
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
@ -535,17 +592,22 @@ nsHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
CollectOrphans(ancestor, mControls->mElements
|
||||
#ifdef DEBUG
|
||||
, this
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
CollectOrphans(ancestor, mControls->mNotInElements
|
||||
#ifdef DEBUG
|
||||
, this
|
||||
#endif
|
||||
#endif
|
||||
);
|
||||
CollectOrphans(ancestor, mImageElements
|
||||
#ifdef DEBUG
|
||||
, this
|
||||
#endif
|
||||
);
|
||||
|
||||
if (oldDocument) {
|
||||
oldDocument->RemovedForm();
|
||||
}
|
||||
}
|
||||
ForgetCurrentSubmission();
|
||||
}
|
||||
|
||||
@ -1034,18 +1096,17 @@ nsHTMLFormElement::GetElementAt(int32_t aIndex) const
|
||||
* 0 otherwise
|
||||
*/
|
||||
static inline int32_t
|
||||
CompareFormControlPosition(nsGenericHTMLFormElement *aControl1,
|
||||
nsGenericHTMLFormElement *aControl2,
|
||||
CompareFormControlPosition(Element *aElement1, Element *aElement2,
|
||||
const nsIContent* aForm)
|
||||
{
|
||||
NS_ASSERTION(aControl1 != aControl2, "Comparing a form control to itself");
|
||||
NS_ASSERTION(aElement1 != aElement2, "Comparing a form control to itself");
|
||||
|
||||
// If an element has a @form, we can assume it *might* be able to not have
|
||||
// a parent and still be in the form.
|
||||
NS_ASSERTION((aControl1->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||
aControl1->GetParent()) &&
|
||||
(aControl2->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||
aControl2->GetParent()),
|
||||
NS_ASSERTION((aElement1->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||
aElement1->GetParent()) &&
|
||||
(aElement2->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
|
||||
aElement2->GetParent()),
|
||||
"Form controls should always have parents");
|
||||
|
||||
// If we pass aForm, we are assuming both controls are form descendants which
|
||||
@ -1054,15 +1115,15 @@ CompareFormControlPosition(nsGenericHTMLFormElement *aControl1,
|
||||
// TODO: remove the prevent asserts fix, see bug 598468.
|
||||
#ifdef DEBUG
|
||||
nsLayoutUtils::gPreventAssertInCompareTreePosition = true;
|
||||
int32_t rVal = nsLayoutUtils::CompareTreePosition(aControl1, aControl2, aForm);
|
||||
int32_t rVal = nsLayoutUtils::CompareTreePosition(aElement1, aElement2, aForm);
|
||||
nsLayoutUtils::gPreventAssertInCompareTreePosition = false;
|
||||
|
||||
return rVal;
|
||||
#else // DEBUG
|
||||
return nsLayoutUtils::CompareTreePosition(aControl1, aControl2, aForm);
|
||||
return nsLayoutUtils::CompareTreePosition(aElement1, aElement2, aForm);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Checks that all form elements are in document order. Asserts if any pair of
|
||||
@ -1106,6 +1167,57 @@ nsHTMLFormElement::PostPasswordEvent()
|
||||
event->PostDOMEvent();
|
||||
}
|
||||
|
||||
// This function return true if the element, once appended, is the last one in
|
||||
// the array.
|
||||
template<typename ElementType>
|
||||
static bool
|
||||
AddElementToList(nsTArray<ElementType*>& aList, ElementType* aChild,
|
||||
nsHTMLFormElement* aForm)
|
||||
{
|
||||
NS_ASSERTION(aList.IndexOf(aChild) == aList.NoIndex,
|
||||
"aChild already in aList");
|
||||
|
||||
uint32_t count = aList.Length();
|
||||
ElementType* element;
|
||||
bool lastElement = false;
|
||||
|
||||
// Optimize most common case where we insert at the end.
|
||||
int32_t position = -1;
|
||||
if (count > 0) {
|
||||
element = aList[count - 1];
|
||||
position = CompareFormControlPosition(aChild, element, aForm);
|
||||
}
|
||||
|
||||
// If this item comes after the last element, or the elements array is
|
||||
// empty, we append to the end. Otherwise, we do a binary search to
|
||||
// determine where the element should go.
|
||||
if (position >= 0 || count == 0) {
|
||||
// WEAK - don't addref
|
||||
aList.AppendElement(aChild);
|
||||
lastElement = true;
|
||||
}
|
||||
else {
|
||||
int32_t low = 0, mid, high;
|
||||
high = count - 1;
|
||||
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
|
||||
element = aList[mid];
|
||||
position = CompareFormControlPosition(aChild, element, aForm);
|
||||
if (position >= 0)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid - 1;
|
||||
}
|
||||
|
||||
// WEAK - don't addref
|
||||
aList.InsertElementAt(low, aChild);
|
||||
}
|
||||
|
||||
return lastElement;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
bool aUpdateValidity, bool aNotify)
|
||||
@ -1121,47 +1233,8 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
bool childInElements = ShouldBeInElements(aChild);
|
||||
nsTArray<nsGenericHTMLFormElement*>& controlList = childInElements ?
|
||||
mControls->mElements : mControls->mNotInElements;
|
||||
|
||||
NS_ASSERTION(controlList.IndexOf(aChild) == controlList.NoIndex,
|
||||
"Form control already in form");
|
||||
|
||||
uint32_t count = controlList.Length();
|
||||
nsGenericHTMLFormElement* element;
|
||||
|
||||
// Optimize most common case where we insert at the end.
|
||||
bool lastElement = false;
|
||||
int32_t position = -1;
|
||||
if (count > 0) {
|
||||
element = controlList[count - 1];
|
||||
position = CompareFormControlPosition(aChild, element, this);
|
||||
}
|
||||
|
||||
// If this item comes after the last element, or the elements array is
|
||||
// empty, we append to the end. Otherwise, we do a binary search to
|
||||
// determine where the element should go.
|
||||
if (position >= 0 || count == 0) {
|
||||
// WEAK - don't addref
|
||||
controlList.AppendElement(aChild);
|
||||
lastElement = true;
|
||||
}
|
||||
else {
|
||||
int32_t low = 0, mid, high;
|
||||
high = count - 1;
|
||||
|
||||
while (low <= high) {
|
||||
mid = (low + high) / 2;
|
||||
|
||||
element = controlList[mid];
|
||||
position = CompareFormControlPosition(aChild, element, this);
|
||||
if (position >= 0)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid - 1;
|
||||
}
|
||||
|
||||
// WEAK - don't addref
|
||||
controlList.InsertElementAt(low, aChild);
|
||||
}
|
||||
bool lastElement = AddElementToList(controlList, aChild, this);
|
||||
|
||||
#ifdef DEBUG
|
||||
AssertDocumentOrder(controlList, this);
|
||||
@ -1359,10 +1432,74 @@ nsHTMLFormElement::HandleDefaultSubmitRemoval()
|
||||
}
|
||||
}
|
||||
|
||||
static nsresult
|
||||
RemoveElementFromTableInternal(
|
||||
nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
|
||||
nsIContent* aChild, const nsAString& aName)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
|
||||
if (!aTable.Get(aName, getter_AddRefs(supports)))
|
||||
return NS_OK;
|
||||
|
||||
// Single element in the hash, just remove it if it's the one
|
||||
// we're trying to remove...
|
||||
if (supports == aChild) {
|
||||
aTable.Remove(aName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(supports));
|
||||
if (content) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList(do_QueryInterface(supports));
|
||||
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
|
||||
|
||||
// Upcast, uggly, but it works!
|
||||
nsBaseContentList *list = static_cast<nsBaseContentList*>(nodeList.get());
|
||||
|
||||
list->RemoveElement(aChild);
|
||||
|
||||
uint32_t length = 0;
|
||||
list->GetLength(&length);
|
||||
|
||||
if (!length) {
|
||||
// If the list is empty we remove if from our hash, this shouldn't
|
||||
// happen tho
|
||||
aTable.Remove(aName);
|
||||
} else if (length == 1) {
|
||||
// Only one element left, replace the list in the hash with the
|
||||
// single element.
|
||||
nsIContent* node = list->Item(0);
|
||||
if (node) {
|
||||
aTable.Put(aName, node);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
RemovePastNames(const nsAString& aName,
|
||||
nsCOMPtr<nsISupports>& aData,
|
||||
void* aClosure)
|
||||
{
|
||||
return aClosure == aData ? PL_DHASH_REMOVE : PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
|
||||
const nsAString& aName)
|
||||
const nsAString& aName,
|
||||
RemoveElementReason aRemoveReason)
|
||||
{
|
||||
// If the element is being removed from the form, we have to remove it from
|
||||
// the past names map.
|
||||
if (aRemoveReason == ElementRemoved) {
|
||||
mPastNameLookupTable.Enumerate(RemovePastNames, aElement);
|
||||
}
|
||||
|
||||
return mControls->RemoveElementFromTable(aElement, aName);
|
||||
}
|
||||
|
||||
@ -1374,16 +1511,24 @@ nsHTMLFormElement::FindNamedItem(const nsAString& aName,
|
||||
if (result) {
|
||||
// FIXME Get the wrapper cache from DoResolveName.
|
||||
*aCache = nullptr;
|
||||
AddToPastNamesMap(aName, result);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(GetCurrentDoc());
|
||||
if (!htmlDoc) {
|
||||
result = mImageNameLookupTable.GetWeak(aName);
|
||||
if (result) {
|
||||
*aCache = nullptr;
|
||||
return nullptr;
|
||||
AddToPastNamesMap(aName, result);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
return htmlDoc->ResolveName(aName, this, aCache);
|
||||
result = mPastNameLookupTable.GetWeak(aName);
|
||||
if (result) {
|
||||
*aCache = nullptr;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
@ -1910,7 +2055,7 @@ nsHTMLFormElement::OnSecurityChange(nsIWebProgress* aWebProgress,
|
||||
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP_(int32_t)
|
||||
nsHTMLFormElement::IndexOfControl(nsIFormControl* aControl)
|
||||
{
|
||||
@ -2141,6 +2286,17 @@ nsHTMLFormElement::IntrinsicState() const
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLFormElement::Clear()
|
||||
{
|
||||
for (int32_t i = mImageElements.Length() - 1; i >= 0; i--) {
|
||||
mImageElements[i]->ClearForm(false);
|
||||
}
|
||||
mImageElements.Clear();
|
||||
mImageNameLookupTable.Clear();
|
||||
mPastNameLookupTable.Clear();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsFormControlList implementation, this could go away if there were
|
||||
// a lightweight collection implementation somewhere
|
||||
@ -2229,7 +2385,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormControlList)
|
||||
|
||||
// nsIDOMHTMLCollection interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
nsFormControlList::GetLength(uint32_t* aLength)
|
||||
{
|
||||
FlushPendingNotifications();
|
||||
@ -2298,20 +2454,17 @@ nsFormControlList::NamedItemInternal(const nsAString& aName,
|
||||
return mNameLookupTable.GetWeak(aName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName)
|
||||
static nsresult
|
||||
AddElementToTableInternal(
|
||||
nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
|
||||
nsIContent* aChild, const nsAString& aName, nsHTMLFormElement* aForm)
|
||||
{
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
mNameLookupTable.Get(aName, getter_AddRefs(supports));
|
||||
aTable.Get(aName, getter_AddRefs(supports));
|
||||
|
||||
if (!supports) {
|
||||
// No entry found, add the form control
|
||||
mNameLookupTable.Put(aName, NS_ISUPPORTS_CAST(nsIContent*, aChild));
|
||||
// No entry found, add the element
|
||||
aTable.Put(aName, aChild);
|
||||
} else {
|
||||
// Found something in the hash, check its type
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(supports);
|
||||
@ -2327,7 +2480,7 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
|
||||
// Found an element, create a list, add the element to the list and put
|
||||
// the list in the hash
|
||||
nsSimpleContentList *list = new nsSimpleContentList(mForm);
|
||||
nsSimpleContentList *list = new nsSimpleContentList(aForm);
|
||||
|
||||
// If an element has a @form, we can assume it *might* be able to not have
|
||||
// a parent and still be in the form.
|
||||
@ -2337,14 +2490,14 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
// Determine the ordering between the new and old element.
|
||||
bool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
|
||||
|
||||
list->AppendElement(newFirst ? aChild : content);
|
||||
list->AppendElement(newFirst ? content : aChild);
|
||||
list->AppendElement(newFirst ? aChild : content.get());
|
||||
list->AppendElement(newFirst ? content.get() : aChild);
|
||||
|
||||
|
||||
nsCOMPtr<nsISupports> listSupports = do_QueryObject(list);
|
||||
|
||||
// Replace the element with the list.
|
||||
mNameLookupTable.Put(aName, listSupports);
|
||||
aTable.Put(aName, listSupports);
|
||||
} else {
|
||||
// There's already a list in the hash, add the child to the list
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
|
||||
@ -2395,6 +2548,17 @@ nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName)
|
||||
{
|
||||
if (!ShouldBeInElements(aChild)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return AddElementToTableInternal(mNameLookupTable, aChild, aName, mForm);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFormControlList::IndexOfControl(nsIFormControl* aControl,
|
||||
int32_t* aIndex)
|
||||
@ -2416,48 +2580,7 @@ nsFormControlList::RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
|
||||
if (!mNameLookupTable.Get(aName, getter_AddRefs(supports)))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIFormControl> fctrl(do_QueryInterface(supports));
|
||||
|
||||
if (fctrl) {
|
||||
// Single element in the hash, just remove it if it's the one
|
||||
// we're trying to remove...
|
||||
if (fctrl == aChild) {
|
||||
mNameLookupTable.Remove(aName);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList(do_QueryInterface(supports));
|
||||
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
|
||||
|
||||
// Upcast, uggly, but it works!
|
||||
nsBaseContentList *list = static_cast<nsBaseContentList*>(nodeList.get());
|
||||
|
||||
list->RemoveElement(aChild);
|
||||
|
||||
uint32_t length = 0;
|
||||
list->GetLength(&length);
|
||||
|
||||
if (!length) {
|
||||
// If the list is empty we remove if from our hash, this shouldn't
|
||||
// happen tho
|
||||
mNameLookupTable.Remove(aName);
|
||||
} else if (length == 1) {
|
||||
// Only one element left, replace the list in the hash with the
|
||||
// single element.
|
||||
nsIContent* node = list->Item(0);
|
||||
if (node) {
|
||||
mNameLookupTable.Put(aName, node);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return RemoveElementFromTableInternal(mNameLookupTable, aChild, aName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2581,3 +2704,55 @@ nsFormControlList::GetSupportedNames(nsTArray<nsString>& aNames)
|
||||
// this enumeration.
|
||||
mNameLookupTable.EnumerateRead(CollectNames, &aNames);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::AddImageElement(HTMLImageElement* aChild)
|
||||
{
|
||||
AddElementToList(mImageElements, aChild, this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::AddImageElementToTable(HTMLImageElement* aChild,
|
||||
const nsAString& aName)
|
||||
{
|
||||
return AddElementToTableInternal(mImageNameLookupTable, aChild, aName, this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::RemoveImageElement(HTMLImageElement* aChild)
|
||||
{
|
||||
uint32_t index = mImageElements.IndexOf(aChild);
|
||||
NS_ENSURE_STATE(index != mImageElements.NoIndex);
|
||||
|
||||
mImageElements.RemoveElementAt(index);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLFormElement::RemoveImageElementFromTable(HTMLImageElement* aElement,
|
||||
const nsAString& aName,
|
||||
RemoveElementReason aRemoveReason)
|
||||
{
|
||||
// If the element is being removed from the form, we have to remove it from
|
||||
// the past names map.
|
||||
if (aRemoveReason == ElementRemoved) {
|
||||
mPastNameLookupTable.Enumerate(RemovePastNames, aElement);
|
||||
}
|
||||
|
||||
return RemoveElementFromTableInternal(mImageNameLookupTable, aElement, aName);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLFormElement::AddToPastNamesMap(const nsAString& aName,
|
||||
nsISupports* aChild)
|
||||
{
|
||||
// If candidates contains exactly one node. Add a mapping from name to the
|
||||
// node in candidates in the form element's past names map, replacing the
|
||||
// previous entry with the same name, if any.
|
||||
nsCOMPtr<nsIContent> node = do_QueryInterface(aChild);
|
||||
if (node) {
|
||||
mPastNameLookupTable.Put(aName, aChild);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,12 @@ class nsFormControlList;
|
||||
class nsIMutableArray;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class HTMLImageElement;
|
||||
}
|
||||
}
|
||||
|
||||
class nsHTMLFormElement : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLFormElement,
|
||||
public nsIWebProgressListener,
|
||||
@ -121,8 +127,8 @@ public:
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLFormElement,
|
||||
nsGenericHTMLElement)
|
||||
|
||||
/**
|
||||
* Remove an element from this form's list of elements
|
||||
@ -143,10 +149,20 @@ public:
|
||||
*
|
||||
* @param aElement the element to remove
|
||||
* @param aName the name or id of the element to remove
|
||||
* @param aRemoveReason describe why this element is removed. If the element
|
||||
* is removed because it's removed from the form, it will be removed
|
||||
* from the past names map too, otherwise it will stay in the past
|
||||
* names map.
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
enum RemoveElementReason {
|
||||
AttributeUpdated,
|
||||
ElementRemoved
|
||||
};
|
||||
nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
|
||||
const nsAString& aName);
|
||||
const nsAString& aName,
|
||||
RemoveElementReason aRemoveReason);
|
||||
|
||||
/**
|
||||
* Add an element to end of this form's list of elements
|
||||
*
|
||||
@ -158,7 +174,7 @@ public:
|
||||
nsresult AddElement(nsGenericHTMLFormElement* aElement, bool aUpdateValidity,
|
||||
bool aNotify);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Add an element to the lookup table maintained by the form.
|
||||
*
|
||||
* We can't fold this method into AddElement() because when
|
||||
@ -168,6 +184,47 @@ public:
|
||||
*/
|
||||
nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
|
||||
const nsAString& aName);
|
||||
|
||||
/**
|
||||
* Remove an image element from this form's list of image elements
|
||||
*
|
||||
* @param aElement the image element to remove
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
nsresult RemoveImageElement(mozilla::dom::HTMLImageElement* aElement);
|
||||
|
||||
/**
|
||||
* Remove an image element from the lookup table maintained by the form.
|
||||
* We can't fold this method into RemoveImageElement() because when
|
||||
* RemoveImageElement() is called it doesn't know if the element is
|
||||
* removed because the id attribute has changed, or because the
|
||||
* name attribute has changed.
|
||||
*
|
||||
* @param aElement the image element to remove
|
||||
* @param aName the name or id of the element to remove
|
||||
* @return NS_OK if the element was successfully removed.
|
||||
*/
|
||||
nsresult RemoveImageElementFromTable(mozilla::dom::HTMLImageElement* aElement,
|
||||
const nsAString& aName,
|
||||
RemoveElementReason aRemoveReason);
|
||||
/**
|
||||
* Add an image element to the end of this form's list of image elements
|
||||
*
|
||||
* @param aElement the element to add
|
||||
* @return NS_OK if the element was successfully added
|
||||
*/
|
||||
nsresult AddImageElement(mozilla::dom::HTMLImageElement* aElement);
|
||||
|
||||
/**
|
||||
* Add an image element to the lookup table maintained by the form.
|
||||
*
|
||||
* We can't fold this method into AddImageElement() because when
|
||||
* AddImageElement() is called, the image attributes can change.
|
||||
* The name or id attributes of the image are used as a key into the table.
|
||||
*/
|
||||
nsresult AddImageElementToTable(mozilla::dom::HTMLImageElement* aChild,
|
||||
const nsAString& aName);
|
||||
|
||||
/**
|
||||
* Return whether there is one and only one input text control.
|
||||
*
|
||||
@ -363,6 +420,12 @@ protected:
|
||||
*/
|
||||
bool CheckFormValidity(nsIMutableArray* aInvalidElements) const;
|
||||
|
||||
// Clear the mImageNameLookupTable and mImageElements.
|
||||
void Clear();
|
||||
|
||||
// Insert a element into the past names map.
|
||||
void AddToPastNamesMap(const nsAString& aName, nsISupports* aChild);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Flush a possible pending submission. If there was a scripted submission
|
||||
@ -417,6 +480,25 @@ protected:
|
||||
/** The first submit element in mNotInElements -- WEAK */
|
||||
nsGenericHTMLFormElement* mFirstSubmitNotInElements;
|
||||
|
||||
// This array holds on to all HTMLImageElement(s).
|
||||
// This is needed to properly clean up the bi-directional references
|
||||
// (both weak and strong) between the form and its HTMLImageElements.
|
||||
|
||||
nsTArray<mozilla::dom::HTMLImageElement*> mImageElements; // Holds WEAK references
|
||||
|
||||
// A map from an ID or NAME attribute to the HTMLImageElement(s), this
|
||||
// hash holds strong references either to the named HTMLImageElement, or
|
||||
// to a list of named HTMLImageElement(s), in the case where this hash
|
||||
// holds on to a list of named HTMLImageElement(s) the list has weak
|
||||
// references to the HTMLImageElement.
|
||||
|
||||
nsInterfaceHashtable<nsStringHashKey,nsISupports> mImageNameLookupTable;
|
||||
|
||||
// A map from names to elements that were gotten by those names from this
|
||||
// form in that past. See "past names map" in the HTML5 specification.
|
||||
|
||||
nsInterfaceHashtable<nsStringHashKey,nsISupports> mPastNameLookupTable;
|
||||
|
||||
/**
|
||||
* Number of invalid and candidate for constraint validation elements in the
|
||||
* form the last time UpdateValidity has been called.
|
||||
|
@ -378,6 +378,8 @@ MOCHITEST_FILES = \
|
||||
wakelock.ogg \
|
||||
wakelock.ogv \
|
||||
test_bug869040.html \
|
||||
test_bug870787.html \
|
||||
test_bug879319.html \
|
||||
allowMedia.sjs \
|
||||
test_bug874758.html \
|
||||
$(NULL)
|
||||
|
84
content/html/content/test/test_bug870787.html
Normal file
84
content/html/content/test/test_bug870787.html
Normal file
@ -0,0 +1,84 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=870787
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 870787</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=870787">Mozilla Bug 870787</a>
|
||||
|
||||
<p id="msg"></p>
|
||||
|
||||
<form id="form0"></form>
|
||||
<img name="img0" id="img0id">
|
||||
|
||||
<img name="img1" id="img1id" />
|
||||
<form id="form1">
|
||||
<img name="img2" id="img2id" />
|
||||
</form>
|
||||
<img name="img3" id="img3id" />
|
||||
|
||||
<table>
|
||||
<form id="form2">
|
||||
<tr><td>
|
||||
<button name="input1" id="input1id" />
|
||||
<input name="input2" id="input2id" />
|
||||
</form>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<form id="form3">
|
||||
<tr><td>
|
||||
<img name="img4" id="img4id" />
|
||||
<img name="img5" id="img5id" />
|
||||
</form>
|
||||
</table>
|
||||
|
||||
<form id="form4"><img id="img6"></form>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 870787 **/
|
||||
|
||||
var form0 = document.getElementById("form0");
|
||||
ok(form0, "Form0 exists");
|
||||
ok(!form0.img0, "Form0.img0 doesn't exist");
|
||||
ok(!form0.img0id, "Form0.img0id doesn't exist");
|
||||
|
||||
var form1 = document.getElementById("form1");
|
||||
ok(form1, "Form1 exists");
|
||||
ok(!form1.img1, "Form1.img1 doesn't exist");
|
||||
ok(!form1.img1id, "Form1.img1id doesn't exist");
|
||||
is(form1.img2, document.getElementById("img2id"), "Form1.img2 exists");
|
||||
is(form1.img2id, document.getElementById("img2id"), "Form1.img2id exists");
|
||||
ok(!form1.img3, "Form1.img3 doesn't exist");
|
||||
ok(!form1.img3id, "Form1.img3id doesn't exist");
|
||||
|
||||
var form2 = document.getElementById("form2");
|
||||
ok(form2, "Form2 exists");
|
||||
is(form2.input1, document.getElementById("input1id"), "Form2.input1 exists");
|
||||
is(form2.input1id, document.getElementById("input1id"), "Form2.input1id exists");
|
||||
is(form2.input2, document.getElementById("input2id"), "Form2.input2 exists");
|
||||
is(form2.input2id, document.getElementById("input2id"), "Form2.input2id exists");
|
||||
|
||||
var form3 = document.getElementById("form3");
|
||||
ok(form3, "Form3 exists");
|
||||
is(form3.img4, document.getElementById("img4id"), "Form3.img4 doesn't exists");
|
||||
is(form3.img4id, document.getElementById("img4id"), "Form3.img4id doesn't exists");
|
||||
is(form3.img5, document.getElementById("img5id"), "Form3.img5 doesn't exists");
|
||||
is(form3.img5id, document.getElementById("img5id"), "Form3.img5id doesn't exists");
|
||||
|
||||
var form4 = document.getElementById("form4");
|
||||
ok(form4, "Form4 exists");
|
||||
is(Object.getOwnPropertyNames(form4.elements).indexOf("img6"), -1, "Form4.elements should not contain img6");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
91
content/html/content/test/test_bug879319.html
Normal file
91
content/html/content/test/test_bug879319.html
Normal file
@ -0,0 +1,91 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=879319
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 879319</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="reflect.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=879319">Mozilla Bug 879319</a>
|
||||
|
||||
<p id="msg"></p>
|
||||
|
||||
<form id="form">
|
||||
<img id="img0" name="bar0" />
|
||||
</form>
|
||||
<input id="input0" name="foo0" form="form" />
|
||||
<input id="input1" name="foo1" form="form" />
|
||||
<input id="input2" name="foo2" form="form" />
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 879319 **/
|
||||
|
||||
var input0 = document.getElementById("input0");
|
||||
ok(input0, "input0 exists");
|
||||
|
||||
var form = document.getElementById("form");
|
||||
ok(form, "form exists");
|
||||
is(form.foo0, input0, "Form.foo0 should exist");
|
||||
|
||||
ok("foo0" in form.elements, "foo0 in form.elements");
|
||||
is(input0.form, form, "input0.form is form");
|
||||
|
||||
input0.setAttribute("name", "tmp0");
|
||||
ok("tmp0" in form.elements, "tmp0 is in form.elements");
|
||||
ok(!("foo0" in form.elements), "foo0 is not in form.elements");
|
||||
is(form.tmp0, input0, "Form.tmp0 == input0");
|
||||
is(form.foo0, input0, "Form.foo0 is still here");
|
||||
|
||||
input0.setAttribute("name", "tmp1");
|
||||
ok("tmp1" in form.elements, "tmp1 is in form.elements");
|
||||
ok(!("tmp0" in form.elements), "tmp0 is not in form.elements");
|
||||
ok(!("foo0" in form.elements), "foo0 is not in form.elements");
|
||||
is(form.tmp0, input0, "Form.tmp0 == input0");
|
||||
is(form.tmp1, input0, "Form.tmp1 == input0");
|
||||
is(form.foo0, input0, "Form.foo0 is still here");
|
||||
|
||||
input0.setAttribute("form", "");
|
||||
ok(!("foo0" in form.elements), "foo0 is not in form.elements");
|
||||
todo_is(form.foo0, undefined, "Form.foo0 should not still be here");
|
||||
todo_is(form.tmp0, undefined, "Form.tmp0 should not still be here");
|
||||
todo_is(form.tmp1, undefined, "Form.tmp1 should not still be here");
|
||||
|
||||
var input1 = document.getElementById("input1");
|
||||
ok(input1, "input1 exists");
|
||||
is(form.foo1, input1, "Form.foo1 should exist");
|
||||
|
||||
ok("foo1" in form.elements, "foo1 in form.elements");
|
||||
is(input1.form, form, "input1.form is form");
|
||||
|
||||
input1.setAttribute("name", "foo0");
|
||||
ok("foo0" in form.elements, "foo0 is in form.elements");
|
||||
is(form.foo0, input1, "Form.foo0 should be input1");
|
||||
is(form.foo1, input1, "Form.foo1 should be input1");
|
||||
|
||||
var input2 = document.getElementById("input2");
|
||||
ok(input2, "input2 exists");
|
||||
is(form.foo2, input2, "Form.foo2 should exist");
|
||||
input2.parentNode.removeChild(input2);
|
||||
ok(!("foo2" in form.elements), "foo2 is not in form.elements");
|
||||
todo_is(form.foo2, undefined, "Form.foo2 should not longer be there");
|
||||
|
||||
var img0 = document.getElementById("img0");
|
||||
ok(img0, "img0 exists");
|
||||
is(form.bar0, img0, "Form.bar0 should exist");
|
||||
|
||||
img0.setAttribute("name", "old_bar0");
|
||||
is(form.bar0, img0, "Form.bar0 is still here");
|
||||
|
||||
img0.parentNode.removeChild(img0);
|
||||
todo_is(form.bar0, undefined, "Form.bar0 should not be here");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -2295,39 +2295,6 @@ nsHTMLDocument::ResolveName(const nsAString& aName, nsWrapperCache **aCache)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISupports>
|
||||
nsHTMLDocument::ResolveName(const nsAString& aName,
|
||||
nsIContent *aForm,
|
||||
nsWrapperCache **aCache)
|
||||
{
|
||||
nsISupports* result = ResolveName(aName, aCache);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> node = do_QueryInterface(result);
|
||||
if (!node) {
|
||||
// We create a nsFormContentList which will filter out the elements in the
|
||||
// list that don't belong to aForm.
|
||||
nsRefPtr<nsBaseContentList> list =
|
||||
new nsFormContentList(aForm, *static_cast<nsBaseContentList*>(result));
|
||||
if (list->Length() > 1) {
|
||||
*aCache = list;
|
||||
return list.forget();
|
||||
}
|
||||
|
||||
// After the nsFormContentList is done filtering there's either nothing or
|
||||
// one element in the list. Return that element, or null if there's no
|
||||
// element in the list.
|
||||
node = list->Item(0);
|
||||
} else if (!nsContentUtils::BelongsInForm(aForm, node)) {
|
||||
node = nullptr;
|
||||
}
|
||||
|
||||
*aCache = node;
|
||||
return node.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsHTMLDocument::NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
|
||||
ErrorResult& rv)
|
||||
|
@ -115,9 +115,6 @@ public:
|
||||
JSObject* GetAll(JSContext* aCx, mozilla::ErrorResult& aRv);
|
||||
|
||||
nsISupports* ResolveName(const nsAString& aName, nsWrapperCache **aCache);
|
||||
virtual already_AddRefed<nsISupports> ResolveName(const nsAString& aName,
|
||||
nsIContent *aForm,
|
||||
nsWrapperCache **aCache) MOZ_OVERRIDE;
|
||||
|
||||
virtual void AddedForm() MOZ_OVERRIDE;
|
||||
virtual void RemovedForm() MOZ_OVERRIDE;
|
||||
@ -297,7 +294,7 @@ protected:
|
||||
nsRefPtr<nsContentList> mForms;
|
||||
nsRefPtr<nsContentList> mFormControls;
|
||||
|
||||
JSObject* mAll;
|
||||
JS::Heap<JSObject*> mAll;
|
||||
|
||||
/** # of forms in the document, synchronously set */
|
||||
int32_t mNumForms;
|
||||
|
@ -33,10 +33,6 @@ public:
|
||||
*/
|
||||
virtual void SetCompatibilityMode(nsCompatibility aMode) = 0;
|
||||
|
||||
virtual already_AddRefed<nsISupports> ResolveName(const nsAString& aName,
|
||||
nsIContent *aForm,
|
||||
nsWrapperCache **aCache) = 0;
|
||||
|
||||
/**
|
||||
* Called when form->BindToTree() is called so that document knows
|
||||
* immediately when a form is added
|
||||
|
@ -1046,32 +1046,6 @@ void MediaDecoder::NotifyBytesConsumed(int64_t aBytes)
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::NextFrameUnavailableBuffering()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mOwner || mShuttingDown || !mDecoderStateMachine)
|
||||
return;
|
||||
|
||||
mOwner->UpdateReadyStateForData(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING);
|
||||
}
|
||||
|
||||
void MediaDecoder::NextFrameAvailable()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mOwner || mShuttingDown || !mDecoderStateMachine)
|
||||
return;
|
||||
|
||||
mOwner->UpdateReadyStateForData(MediaDecoderOwner::NEXT_FRAME_AVAILABLE);
|
||||
}
|
||||
|
||||
void MediaDecoder::NextFrameUnavailable()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!mOwner || mShuttingDown || !mDecoderStateMachine)
|
||||
return;
|
||||
mOwner->UpdateReadyStateForData(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE);
|
||||
}
|
||||
|
||||
void MediaDecoder::UpdateReadyStateForData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -710,12 +710,6 @@ public:
|
||||
// This must be called on the main thread only.
|
||||
void PlaybackPositionChanged();
|
||||
|
||||
// Calls mElement->UpdateReadyStateForData, telling it which state we have
|
||||
// entered. Main thread only.
|
||||
void NextFrameUnavailableBuffering();
|
||||
void NextFrameAvailable();
|
||||
void NextFrameUnavailable();
|
||||
|
||||
// Calls mElement->UpdateReadyStateForData, telling it whether we have
|
||||
// data for the next frame and if we're buffering. Main thread only.
|
||||
void UpdateReadyStateForData();
|
||||
|
@ -2620,21 +2620,16 @@ void MediaDecoderStateMachine::UpdateReadyState() {
|
||||
}
|
||||
mLastFrameStatus = nextFrameStatus;
|
||||
|
||||
/* This is a bit tricky. MediaDecoder::UpdateReadyStateForData will run on
|
||||
* the main thread and re-evaluate GetNextFrameStatus there, passing it to
|
||||
* HTMLMediaElement::UpdateReadyStateForData. It doesn't use the value of
|
||||
* GetNextFrameStatus we computed here, because what we're computing here
|
||||
* could be stale by the time MediaDecoder::UpdateReadyStateForData runs.
|
||||
* We only compute GetNextFrameStatus here to avoid posting runnables to the main
|
||||
* thread unnecessarily.
|
||||
*/
|
||||
nsCOMPtr<nsIRunnable> event;
|
||||
switch (nextFrameStatus) {
|
||||
case MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING:
|
||||
event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::NextFrameUnavailableBuffering);
|
||||
break;
|
||||
case MediaDecoderOwner::NEXT_FRAME_AVAILABLE:
|
||||
event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::NextFrameAvailable);
|
||||
break;
|
||||
case MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE:
|
||||
event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::NextFrameUnavailable);
|
||||
break;
|
||||
default:
|
||||
PR_NOT_REACHED("unhandled frame state");
|
||||
}
|
||||
|
||||
event = NS_NewRunnableMethod(mDecoder, &MediaDecoder::UpdateReadyStateForData);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ AudioBuffer::InitializeBuffers(uint32_t aNumberOfChannels, JSContext* aJSContext
|
||||
if (!array) {
|
||||
return false;
|
||||
}
|
||||
mJSChannels.AppendElement(array);
|
||||
mJSChannels.AppendElement(array.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -116,7 +116,7 @@ protected:
|
||||
|
||||
nsRefPtr<AudioContext> mContext;
|
||||
// Float32Arrays
|
||||
AutoFallibleTArray<JSObject*,2> mJSChannels;
|
||||
AutoFallibleTArray<JS::Heap<JSObject*>, 2> mJSChannels;
|
||||
|
||||
// mSharedChannels aggregates the data from mJSChannels. This is non-null
|
||||
// if and only if the mJSChannels are neutered.
|
||||
|
@ -37,7 +37,7 @@ private:
|
||||
void ClearCurve();
|
||||
|
||||
private:
|
||||
JSObject* mCurve;
|
||||
JS::Heap<JSObject*> mCurve;
|
||||
};
|
||||
|
||||
}
|
||||
|
145
content/xbl/src/nsXBLMaybeCompiled.h
Normal file
145
content/xbl/src/nsXBLMaybeCompiled.h
Normal file
@ -0,0 +1,145 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsXBLMaybeCompiled_h__
|
||||
#define nsXBLMaybeCompiled_h__
|
||||
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
/*
|
||||
* A union containing either a pointer representing uncompiled source or a
|
||||
* JSObject* representing the compiled result. The class is templated on the
|
||||
* source object type.
|
||||
*
|
||||
* The purpose of abstracting this as a separate class is to allow it to be
|
||||
* wrapped in a JS::Heap<T> to correctly handle post-barriering of the JSObject
|
||||
* pointer, when present.
|
||||
*/
|
||||
template <class UncompiledT>
|
||||
class nsXBLMaybeCompiled
|
||||
{
|
||||
public:
|
||||
nsXBLMaybeCompiled() : mUncompiled(BIT_UNCOMPILED) {}
|
||||
|
||||
nsXBLMaybeCompiled(UncompiledT* uncompiled)
|
||||
: mUncompiled(reinterpret_cast<uintptr_t>(uncompiled) | BIT_UNCOMPILED) {}
|
||||
|
||||
nsXBLMaybeCompiled(JSObject* compiled) : mCompiled(compiled) {}
|
||||
|
||||
bool IsCompiled() const
|
||||
{
|
||||
return !(mUncompiled & BIT_UNCOMPILED);
|
||||
}
|
||||
|
||||
UncompiledT* GetUncompiled() const
|
||||
{
|
||||
MOZ_ASSERT(!IsCompiled(), "Attempt to get compiled function as uncompiled");
|
||||
uintptr_t unmasked = mUncompiled & ~BIT_UNCOMPILED;
|
||||
return reinterpret_cast<UncompiledT*>(unmasked);
|
||||
}
|
||||
|
||||
JSObject* GetJSFunction() const
|
||||
{
|
||||
MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
|
||||
return mCompiled;
|
||||
}
|
||||
|
||||
private:
|
||||
JSObject*& UnsafeGetJSFunction()
|
||||
{
|
||||
MOZ_ASSERT(IsCompiled(), "Attempt to get uncompiled function as compiled");
|
||||
return mCompiled;
|
||||
}
|
||||
|
||||
enum { BIT_UNCOMPILED = 1 << 0 };
|
||||
|
||||
union
|
||||
{
|
||||
// An pointer that represents the function before being compiled, with
|
||||
// BIT_UNCOMPILED set.
|
||||
uintptr_t mUncompiled;
|
||||
|
||||
// The JS object for the compiled result.
|
||||
JSObject* mCompiled;
|
||||
};
|
||||
|
||||
friend class js::RootMethods<nsXBLMaybeCompiled<UncompiledT> >;
|
||||
};
|
||||
|
||||
/* Add support for JS::Heap<nsXBLMaybeCompiled>. */
|
||||
namespace js {
|
||||
|
||||
template <class UncompiledT>
|
||||
struct RootMethods<nsXBLMaybeCompiled<UncompiledT> > : public RootMethods<JSObject *>
|
||||
{
|
||||
typedef struct RootMethods<JSObject *> Base;
|
||||
|
||||
static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); }
|
||||
|
||||
static bool poisoned(nsXBLMaybeCompiled<UncompiledT> function)
|
||||
{
|
||||
return function.IsCompiled() && Base::poisoned(function.GetJSFunction());
|
||||
}
|
||||
|
||||
static bool needsPostBarrier(nsXBLMaybeCompiled<UncompiledT> function)
|
||||
{
|
||||
return function.IsCompiled() && Base::needsPostBarrier(function.GetJSFunction());
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
static void postBarrier(nsXBLMaybeCompiled<UncompiledT>* functionp)
|
||||
{
|
||||
Base::postBarrier(&functionp->UnsafeGetJSFunction());
|
||||
}
|
||||
|
||||
static void relocate(nsXBLMaybeCompiled<UncompiledT>* functionp)
|
||||
{
|
||||
Base::relocate(&functionp->UnsafeGetJSFunction());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class UncompiledT>
|
||||
class HeapBase<nsXBLMaybeCompiled<UncompiledT> >
|
||||
{
|
||||
const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() const {
|
||||
return *static_cast<const JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this);
|
||||
}
|
||||
|
||||
JS::Heap<nsXBLMaybeCompiled<UncompiledT> >& wrapper() {
|
||||
return *static_cast<JS::Heap<nsXBLMaybeCompiled<UncompiledT> >*>(this);
|
||||
}
|
||||
|
||||
const nsXBLMaybeCompiled<UncompiledT>* extract() const {
|
||||
return wrapper().address();
|
||||
}
|
||||
|
||||
nsXBLMaybeCompiled<UncompiledT>* extract() {
|
||||
return wrapper().unsafeGet();
|
||||
}
|
||||
|
||||
public:
|
||||
bool IsCompiled() const { return extract()->IsCompiled(); }
|
||||
UncompiledT* GetUncompiled() const { return extract()->GetUncompiled(); }
|
||||
JSObject* GetJSFunction() const { return extract()->GetJSFunction(); }
|
||||
|
||||
void SetUncompiled(UncompiledT* source) {
|
||||
wrapper().set(nsXBLMaybeCompiled<UncompiledT>(source));
|
||||
}
|
||||
|
||||
void SetJSFunction(JSObject* function) {
|
||||
wrapper().set(nsXBLMaybeCompiled<UncompiledT>(function));
|
||||
}
|
||||
|
||||
JS::Heap<JSObject*>& AsHeapObject()
|
||||
{
|
||||
MOZ_ASSERT(extract()->IsCompiled());
|
||||
return *reinterpret_cast<JS::Heap<JSObject*>*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif // nsXBLMaybeCompiled_h__
|
@ -24,8 +24,8 @@
|
||||
using namespace mozilla;
|
||||
|
||||
nsXBLProtoImplMethod::nsXBLProtoImplMethod(const PRUnichar* aName) :
|
||||
nsXBLProtoImplMember(aName),
|
||||
mUncompiledMethod(BIT_UNCOMPILED)
|
||||
nsXBLProtoImplMember(aName),
|
||||
mMethod()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXBLProtoImplMethod);
|
||||
}
|
||||
@ -108,12 +108,13 @@ nsXBLProtoImplMethod::InstallMember(JSContext* aCx,
|
||||
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||
if (mJSMethodObject) {
|
||||
JS::Rooted<JSObject*> jsMethodObject(aCx, GetCompiledMethod());
|
||||
if (jsMethodObject) {
|
||||
nsDependentString name(mName);
|
||||
|
||||
// First, make the function in the compartment of the scope object.
|
||||
JSAutoCompartment ac(aCx, scopeObject);
|
||||
JS::Rooted<JSObject*> method(aCx, ::JS_CloneFunctionObject(aCx, mJSMethodObject, scopeObject));
|
||||
JS::Rooted<JSObject*> method(aCx, ::JS_CloneFunctionObject(aCx, jsMethodObject, scopeObject));
|
||||
if (!method) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -149,7 +150,7 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||
// No parameters or body was supplied, so don't install method.
|
||||
if (!uncompiledMethod) {
|
||||
// Early return after which we consider ourselves compiled.
|
||||
mJSMethodObject = nullptr;
|
||||
SetCompiledMethod(nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -159,7 +160,7 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||
delete uncompiledMethod;
|
||||
|
||||
// Early return after which we consider ourselves compiled.
|
||||
mJSMethodObject = nullptr;
|
||||
SetCompiledMethod(nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -219,7 +220,7 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||
return rv;
|
||||
}
|
||||
|
||||
mJSMethodObject = methodObject;
|
||||
SetCompiledMethod(methodObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -227,8 +228,8 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
|
||||
void
|
||||
nsXBLProtoImplMethod::Trace(const TraceCallbacks& aCallbacks, void *aClosure)
|
||||
{
|
||||
if (IsCompiled() && mJSMethodObject) {
|
||||
aCallbacks.Trace(&mJSMethodObject, "mJSMethodObject", aClosure);
|
||||
if (IsCompiled() && GetCompiledMethod()) {
|
||||
aCallbacks.Trace(&mMethod.AsHeapObject(), "mMethod", aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,11 +244,7 @@ nsXBLProtoImplMethod::Read(nsIScriptContext* aContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
mJSMethodObject = methodObject;
|
||||
|
||||
#ifdef DEBUG
|
||||
mIsCompiled = true;
|
||||
#endif
|
||||
SetCompiledMethod(methodObject);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -256,15 +253,15 @@ nsresult
|
||||
nsXBLProtoImplMethod::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream)
|
||||
{
|
||||
if (mJSMethodObject) {
|
||||
MOZ_ASSERT(IsCompiled());
|
||||
if (GetCompiledMethod()) {
|
||||
nsresult rv = aStream->Write8(XBLBinding_Serialize_Method);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aStream->WriteWStringZ(mName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSMethodObject));
|
||||
return XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -275,7 +272,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
|
||||
{
|
||||
NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
|
||||
|
||||
if (!mJSMethodObject) {
|
||||
if (!GetCompiledMethod()) {
|
||||
// Nothing to do here
|
||||
return NS_OK;
|
||||
}
|
||||
@ -327,7 +324,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
|
||||
// Clone the function object, using thisObject as the parent so "this" is in
|
||||
// the scope chain of the resulting function (for backwards compat to the
|
||||
// days when this was an event handler).
|
||||
JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, mJSMethodObject, thisObject));
|
||||
JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, GetCompiledMethod(), thisObject));
|
||||
if (!method)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
@ -364,12 +361,12 @@ nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
|
||||
nsIObjectOutputStream* aStream,
|
||||
XBLBindingSerializeDetails aType)
|
||||
{
|
||||
if (mJSMethodObject) {
|
||||
MOZ_ASSERT(IsCompiled());
|
||||
if (GetCompiledMethod()) {
|
||||
nsresult rv = aStream->Write8(aType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSMethodObject));
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsString.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXBLMaybeCompiled.h"
|
||||
#include "nsXBLProtoImplMember.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
|
||||
@ -102,29 +103,31 @@ public:
|
||||
|
||||
bool IsCompiled() const
|
||||
{
|
||||
return !(mUncompiledMethod & BIT_UNCOMPILED);
|
||||
return mMethod.IsCompiled();
|
||||
}
|
||||
|
||||
void SetUncompiledMethod(nsXBLUncompiledMethod* aUncompiledMethod)
|
||||
{
|
||||
mUncompiledMethod = uintptr_t(aUncompiledMethod) | BIT_UNCOMPILED;
|
||||
mMethod.SetUncompiled(aUncompiledMethod);
|
||||
}
|
||||
|
||||
nsXBLUncompiledMethod* GetUncompiledMethod() const
|
||||
{
|
||||
uintptr_t unmasked = mUncompiledMethod & ~BIT_UNCOMPILED;
|
||||
return reinterpret_cast<nsXBLUncompiledMethod*>(unmasked);
|
||||
return mMethod.GetUncompiled();
|
||||
}
|
||||
|
||||
protected:
|
||||
enum { BIT_UNCOMPILED = 1 << 0 };
|
||||
void SetCompiledMethod(JSObject* aCompiledMethod)
|
||||
{
|
||||
mMethod.SetJSFunction(aCompiledMethod);
|
||||
}
|
||||
|
||||
union {
|
||||
uintptr_t mUncompiledMethod; // An object that represents the method before being compiled.
|
||||
JSObject* mJSMethodObject; // The JS object for the method (after compilation)
|
||||
};
|
||||
JSObject* GetCompiledMethod() const
|
||||
{
|
||||
return mMethod.GetJSFunction();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mIsCompiled;
|
||||
#endif
|
||||
JS::Heap<nsXBLMaybeCompiled<nsXBLUncompiledMethod> > mMethod;
|
||||
};
|
||||
|
||||
class nsXBLProtoImplAnonymousMethod : public nsXBLProtoImplMethod {
|
||||
|
@ -27,8 +27,6 @@ nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
||||
const PRUnichar* aReadOnly,
|
||||
uint32_t aLineNumber) :
|
||||
nsXBLProtoImplMember(aName),
|
||||
mGetterText(nullptr),
|
||||
mSetterText(nullptr),
|
||||
mJSAttributes(JSPROP_ENUMERATE)
|
||||
#ifdef DEBUG
|
||||
, mIsCompiled(false)
|
||||
@ -55,8 +53,6 @@ nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
||||
nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
|
||||
const bool aIsReadOnly)
|
||||
: nsXBLProtoImplMember(aName),
|
||||
mGetterText(nullptr),
|
||||
mSetterText(nullptr),
|
||||
mJSAttributes(JSPROP_ENUMERATE)
|
||||
#ifdef DEBUG
|
||||
, mIsCompiled(false)
|
||||
@ -72,12 +68,20 @@ nsXBLProtoImplProperty::~nsXBLProtoImplProperty()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXBLProtoImplProperty);
|
||||
|
||||
if (!(mJSAttributes & JSPROP_GETTER)) {
|
||||
delete mGetterText;
|
||||
if (!mGetter.IsCompiled()) {
|
||||
delete mGetter.GetUncompiled();
|
||||
}
|
||||
|
||||
if (!(mJSAttributes & JSPROP_SETTER)) {
|
||||
delete mSetterText;
|
||||
if (!mSetter.IsCompiled()) {
|
||||
delete mSetter.GetUncompiled();
|
||||
}
|
||||
}
|
||||
|
||||
void nsXBLProtoImplProperty::EnsureUncompiledText(PropertyOp& aPropertyOp)
|
||||
{
|
||||
if (!aPropertyOp.GetUncompiled()) {
|
||||
nsXBLTextWithLineNumber* text = new nsXBLTextWithLineNumber();
|
||||
aPropertyOp.SetUncompiled(text);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,13 +90,8 @@ nsXBLProtoImplProperty::AppendGetterText(const nsAString& aText)
|
||||
{
|
||||
NS_PRECONDITION(!mIsCompiled,
|
||||
"Must not be compiled when accessing getter text");
|
||||
if (!mGetterText) {
|
||||
mGetterText = new nsXBLTextWithLineNumber();
|
||||
if (!mGetterText)
|
||||
return;
|
||||
}
|
||||
|
||||
mGetterText->AppendText(aText);
|
||||
EnsureUncompiledText(mGetter);
|
||||
mGetter.GetUncompiled()->AppendText(aText);
|
||||
}
|
||||
|
||||
void
|
||||
@ -100,13 +99,8 @@ nsXBLProtoImplProperty::AppendSetterText(const nsAString& aText)
|
||||
{
|
||||
NS_PRECONDITION(!mIsCompiled,
|
||||
"Must not be compiled when accessing setter text");
|
||||
if (!mSetterText) {
|
||||
mSetterText = new nsXBLTextWithLineNumber();
|
||||
if (!mSetterText)
|
||||
return;
|
||||
}
|
||||
|
||||
mSetterText->AppendText(aText);
|
||||
EnsureUncompiledText(mSetter);
|
||||
mSetter.GetUncompiled()->AppendText(aText);
|
||||
}
|
||||
|
||||
void
|
||||
@ -114,13 +108,8 @@ nsXBLProtoImplProperty::SetGetterLineNumber(uint32_t aLineNumber)
|
||||
{
|
||||
NS_PRECONDITION(!mIsCompiled,
|
||||
"Must not be compiled when accessing getter text");
|
||||
if (!mGetterText) {
|
||||
mGetterText = new nsXBLTextWithLineNumber();
|
||||
if (!mGetterText)
|
||||
return;
|
||||
}
|
||||
|
||||
mGetterText->SetLineNumber(aLineNumber);
|
||||
EnsureUncompiledText(mGetter);
|
||||
mGetter.GetUncompiled()->SetLineNumber(aLineNumber);
|
||||
}
|
||||
|
||||
void
|
||||
@ -128,13 +117,8 @@ nsXBLProtoImplProperty::SetSetterLineNumber(uint32_t aLineNumber)
|
||||
{
|
||||
NS_PRECONDITION(!mIsCompiled,
|
||||
"Must not be compiled when accessing setter text");
|
||||
if (!mSetterText) {
|
||||
mSetterText = new nsXBLTextWithLineNumber();
|
||||
if (!mSetterText)
|
||||
return;
|
||||
}
|
||||
|
||||
mSetterText->SetLineNumber(aLineNumber);
|
||||
EnsureUncompiledText(mSetter);
|
||||
mSetter.GetUncompiled()->SetLineNumber(aLineNumber);
|
||||
}
|
||||
|
||||
const char* gPropertyArgs[] = { "val" };
|
||||
@ -145,25 +129,26 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
|
||||
{
|
||||
NS_PRECONDITION(mIsCompiled,
|
||||
"Should not be installing an uncompiled property");
|
||||
MOZ_ASSERT(mGetter.IsCompiled() && mSetter.IsCompiled());
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(aTargetClassObject, aCx));
|
||||
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
|
||||
JS::Rooted<JSObject*> scopeObject(aCx, xpc::GetXBLScope(aCx, globalObject));
|
||||
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// now we want to reevaluate our property using aContext and the script object for this window...
|
||||
if (mJSGetterObject || mJSSetterObject) {
|
||||
if (mGetter.GetJSFunction() || mSetter.GetJSFunction()) {
|
||||
// First, enter the compartment of the scope object and clone the functions.
|
||||
JSAutoCompartment ac(aCx, scopeObject);
|
||||
|
||||
JS::Rooted<JSObject*> getter(aCx, nullptr);
|
||||
if (mJSGetterObject) {
|
||||
if (!(getter = ::JS_CloneFunctionObject(aCx, mJSGetterObject, scopeObject)))
|
||||
if (mGetter.GetJSFunction()) {
|
||||
if (!(getter = ::JS_CloneFunctionObject(aCx, mGetter.GetJSFunction(), scopeObject)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> setter(aCx, nullptr);
|
||||
if (mJSSetterObject) {
|
||||
if (!(setter = ::JS_CloneFunctionObject(aCx, mJSSetterObject, scopeObject)))
|
||||
if (mSetter.GetJSFunction()) {
|
||||
if (!(setter = ::JS_CloneFunctionObject(aCx, mSetter.GetJSFunction(), scopeObject)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@ -192,6 +177,7 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
"Trying to compile an already-compiled property");
|
||||
NS_PRECONDITION(aClassObject,
|
||||
"Must have class object to compile");
|
||||
MOZ_ASSERT(!mGetter.IsCompiled() && !mSetter.IsCompiled());
|
||||
|
||||
if (!mName)
|
||||
return NS_ERROR_FAILURE; // Without a valid name, we can't install the member.
|
||||
@ -200,7 +186,7 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsAutoCString functionUri;
|
||||
if (mGetterText || mSetterText) {
|
||||
if (mGetter.GetUncompiled() || mSetter.GetUncompiled()) {
|
||||
functionUri = aClassStr;
|
||||
int32_t hash = functionUri.RFindChar('#');
|
||||
if (hash != kNotFound) {
|
||||
@ -209,13 +195,14 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
}
|
||||
|
||||
bool deletedGetter = false;
|
||||
if (mGetterText && mGetterText->GetText()) {
|
||||
nsDependentString getter(mGetterText->GetText());
|
||||
nsXBLTextWithLineNumber *getterText = mGetter.GetUncompiled();
|
||||
if (getterText && getterText->GetText()) {
|
||||
nsDependentString getter(getterText->GetText());
|
||||
if (!getter.IsEmpty()) {
|
||||
AutoPushJSContext cx(aContext->GetNativeContext());
|
||||
JSAutoCompartment ac(cx, aClassObject);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(functionUri.get(), mGetterText->GetLineNumber())
|
||||
options.setFileAndLine(functionUri.get(), getterText->GetLineNumber())
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
nsCString name = NS_LITERAL_CSTRING("get_") + NS_ConvertUTF16toUTF8(mName);
|
||||
JS::RootedObject rootedNull(cx, nullptr); // See bug 781070.
|
||||
@ -223,17 +210,16 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
rv = nsJSUtils::CompileFunction(cx, rootedNull, options, name, 0, nullptr,
|
||||
getter, getterObject.address());
|
||||
|
||||
// Make sure we free mGetterText here before setting mJSGetterObject, since
|
||||
// that'll overwrite mGetterText
|
||||
delete mGetterText;
|
||||
delete getterText;
|
||||
deletedGetter = true;
|
||||
mJSGetterObject = getterObject;
|
||||
|
||||
mGetter.SetJSFunction(getterObject);
|
||||
|
||||
if (mJSGetterObject && NS_SUCCEEDED(rv)) {
|
||||
if (mGetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
|
||||
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
mJSGetterObject = nullptr;
|
||||
mGetter.SetJSFunction(nullptr);
|
||||
mJSAttributes &= ~JSPROP_GETTER;
|
||||
/*chaining to return failure*/
|
||||
}
|
||||
@ -241,8 +227,8 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
} // if getter is not empty
|
||||
|
||||
if (!deletedGetter) { // Empty getter
|
||||
delete mGetterText;
|
||||
mJSGetterObject = nullptr;
|
||||
delete getterText;
|
||||
mGetter.SetJSFunction(nullptr);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -256,13 +242,14 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
}
|
||||
|
||||
bool deletedSetter = false;
|
||||
if (mSetterText && mSetterText->GetText()) {
|
||||
nsDependentString setter(mSetterText->GetText());
|
||||
nsXBLTextWithLineNumber *setterText = mSetter.GetUncompiled();
|
||||
if (setterText && setterText->GetText()) {
|
||||
nsDependentString setter(setterText->GetText());
|
||||
if (!setter.IsEmpty()) {
|
||||
AutoPushJSContext cx(aContext->GetNativeContext());
|
||||
JSAutoCompartment ac(cx, aClassObject);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(functionUri.get(), mSetterText->GetLineNumber())
|
||||
options.setFileAndLine(functionUri.get(), setterText->GetLineNumber())
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
nsCString name = NS_LITERAL_CSTRING("set_") + NS_ConvertUTF16toUTF8(mName);
|
||||
JS::RootedObject rootedNull(cx, nullptr); // See bug 781070.
|
||||
@ -270,17 +257,15 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
rv = nsJSUtils::CompileFunction(cx, rootedNull, options, name, 1,
|
||||
gPropertyArgs, setter, setterObject.address());
|
||||
|
||||
// Make sure we free mSetterText here before setting mJSGetterObject, since
|
||||
// that'll overwrite mSetterText
|
||||
delete mSetterText;
|
||||
delete setterText;
|
||||
deletedSetter = true;
|
||||
mJSSetterObject = setterObject;
|
||||
mSetter.SetJSFunction(setterObject);
|
||||
|
||||
if (mJSSetterObject && NS_SUCCEEDED(rv)) {
|
||||
if (mSetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
|
||||
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
mJSSetterObject = nullptr;
|
||||
mSetter.SetJSFunction(nullptr);
|
||||
mJSAttributes &= ~JSPROP_SETTER;
|
||||
/*chaining to return failure*/
|
||||
}
|
||||
@ -288,8 +273,8 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
|
||||
} // if setter wasn't empty....
|
||||
|
||||
if (!deletedSetter) { // Empty setter
|
||||
delete mSetterText;
|
||||
mJSSetterObject = nullptr;
|
||||
delete setterText;
|
||||
mSetter.SetJSFunction(nullptr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -303,11 +288,11 @@ void
|
||||
nsXBLProtoImplProperty::Trace(const TraceCallbacks& aCallbacks, void *aClosure)
|
||||
{
|
||||
if (mJSAttributes & JSPROP_GETTER) {
|
||||
aCallbacks.Trace(&mJSGetterObject, "mJSGetterObject", aClosure);
|
||||
aCallbacks.Trace(&mGetter.AsHeapObject(), "mGetter", aClosure);
|
||||
}
|
||||
|
||||
if (mJSAttributes & JSPROP_SETTER) {
|
||||
aCallbacks.Trace(&mJSSetterObject, "mJSSetterObject", aClosure);
|
||||
aCallbacks.Trace(&mSetter.AsHeapObject(), "mSetter", aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,27 +301,30 @@ nsXBLProtoImplProperty::Read(nsIScriptContext* aContext,
|
||||
nsIObjectInputStream* aStream,
|
||||
XBLBindingSerializeDetails aType)
|
||||
{
|
||||
MOZ_ASSERT(!mIsCompiled);
|
||||
MOZ_ASSERT(!mGetter.GetUncompiled() && !mSetter.GetUncompiled());
|
||||
|
||||
JSContext *cx = aContext->GetNativeContext();
|
||||
|
||||
JS::Rooted<JSObject*> getterObject(cx);
|
||||
if (aType == XBLBinding_Serialize_GetterProperty ||
|
||||
aType == XBLBinding_Serialize_GetterSetterProperty) {
|
||||
JS::Rooted<JSObject*> getterObject(cx);
|
||||
nsresult rv = XBL_DeserializeFunction(aContext, aStream, &getterObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mJSGetterObject = getterObject;
|
||||
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
|
||||
}
|
||||
|
||||
mGetter.SetJSFunction(getterObject);
|
||||
|
||||
JS::Rooted<JSObject*> setterObject(cx);
|
||||
if (aType == XBLBinding_Serialize_SetterProperty ||
|
||||
aType == XBLBinding_Serialize_GetterSetterProperty) {
|
||||
JS::Rooted<JSObject*> setterObject(cx);
|
||||
nsresult rv = XBL_DeserializeFunction(aContext, aStream, &setterObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mJSSetterObject = setterObject;
|
||||
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
|
||||
}
|
||||
mSetter.SetJSFunction(setterObject);
|
||||
|
||||
#ifdef DEBUG
|
||||
mIsCompiled = true;
|
||||
@ -370,14 +358,12 @@ nsXBLProtoImplProperty::Write(nsIScriptContext* aContext,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mJSAttributes & JSPROP_GETTER) {
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSGetterObject));
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mGetter.AsHeapObject());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mJSAttributes & JSPROP_SETTER) {
|
||||
rv = XBL_SerializeFunction(aContext, aStream,
|
||||
JS::Handle<JSObject*>::fromMarkedLocation(&mJSSetterObject));
|
||||
rv = XBL_SerializeFunction(aContext, aStream, mSetter.AsHeapObject());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "jsapi.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXBLSerialize.h"
|
||||
#include "nsXBLMaybeCompiled.h"
|
||||
#include "nsXBLProtoImplMember.h"
|
||||
|
||||
class nsXBLProtoImplProperty: public nsXBLProtoImplMember
|
||||
@ -48,21 +49,17 @@ public:
|
||||
nsIObjectOutputStream* aStream) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
union {
|
||||
// The raw text for the getter (prior to compilation).
|
||||
nsXBLTextWithLineNumber* mGetterText;
|
||||
// The JS object for the getter (after compilation)
|
||||
JSObject * mJSGetterObject;
|
||||
};
|
||||
typedef JS::Heap<nsXBLMaybeCompiled<nsXBLTextWithLineNumber> > PropertyOp;
|
||||
|
||||
union {
|
||||
// The raw text for the setter (prior to compilation).
|
||||
nsXBLTextWithLineNumber* mSetterText;
|
||||
// The JS object for the setter (after compilation)
|
||||
JSObject * mJSSetterObject;
|
||||
};
|
||||
void EnsureUncompiledText(PropertyOp& aPropertyOp);
|
||||
|
||||
// The raw text for the getter, or the JS object (after compilation).
|
||||
PropertyOp mGetter;
|
||||
|
||||
// The raw text for the setter, or the JS object (after compilation).
|
||||
PropertyOp mSetter;
|
||||
|
||||
unsigned mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
|
||||
unsigned mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
|
||||
|
||||
#ifdef DEBUG
|
||||
bool mIsCompiled;
|
||||
|
@ -2383,8 +2383,7 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
||||
rv = aStream->Write32(mLangVersion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// And delegate the writing to the nsIScriptContext
|
||||
rv = context->Serialize(aStream,
|
||||
JS::Handle<JSScript*>::fromMarkedLocation(&mScriptObject));
|
||||
rv = context->Serialize(aStream, mScriptObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -243,13 +243,13 @@ public:
|
||||
// &mScriptObject pointer can't go stale.
|
||||
JS::Handle<JSScript*> GetScriptObject()
|
||||
{
|
||||
return JS::Handle<JSScript*>::fromMarkedLocation(&mScriptObject);
|
||||
return JS::Handle<JSScript*>(mScriptObject);
|
||||
}
|
||||
|
||||
void TraceScriptObject(JSTracer* aTrc)
|
||||
{
|
||||
if (mScriptObject) {
|
||||
JS_CallScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script");
|
||||
JS_CallHeapScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script");
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ public:
|
||||
mozilla::dom::XULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
|
||||
uint32_t mLangVersion;
|
||||
private:
|
||||
JSScript* mScriptObject;
|
||||
JS::Heap<JSScript*> mScriptObject;
|
||||
};
|
||||
|
||||
class nsXULPrototypeText : public nsXULPrototypeNode
|
||||
|
@ -7890,17 +7890,6 @@ nsDocShell::RestoreFromHistory()
|
||||
// Restart plugins, and paint the content.
|
||||
if (shell) {
|
||||
shell->Thaw();
|
||||
|
||||
newVM = shell->GetViewManager();
|
||||
if (newVM) {
|
||||
// When we insert the root view above the resulting invalidate is
|
||||
// dropped because painting is suppressed in the presshell until we
|
||||
// call Thaw. So we issue the invalidate here.
|
||||
newRootView = newVM->GetRootView();
|
||||
if (newRootView) {
|
||||
newVM->InvalidateView(newRootView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return privWin->FireDelayedDOMEvents();
|
||||
|
@ -22,7 +22,7 @@ class DOMRequest : public nsDOMEventTargetHelper,
|
||||
public nsIDOMDOMRequest
|
||||
{
|
||||
protected:
|
||||
JS::Value mResult;
|
||||
JS::Heap<JS::Value> mResult;
|
||||
nsRefPtr<DOMError> mError;
|
||||
bool mDone;
|
||||
bool mRooted;
|
||||
|
@ -94,7 +94,7 @@ CPP_SOURCES += [
|
||||
'nsScriptNameSpaceManager.cpp',
|
||||
'nsStructuredCloneContainer.cpp',
|
||||
'nsWindowMemoryReporter.cpp',
|
||||
'nsWindowRoot.cpp',
|
||||
'nsWindowRoot.cpp'
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
|
@ -1588,7 +1588,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindow)
|
||||
|
||||
static PLDHashOperator
|
||||
MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JSObject* aData, void* aClosure)
|
||||
MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JS::Heap<JSObject*>& aData, void* aClosure)
|
||||
{
|
||||
xpc_UnmarkGrayObject(aData);
|
||||
return PL_DHASH_NEXT;
|
||||
@ -1597,7 +1597,7 @@ MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JSObject* aData, void* aClosure)
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
|
||||
if (tmp->IsBlackForCC()) {
|
||||
if (tmp->mCachedXBLPrototypeHandlers.IsInitialized()) {
|
||||
tmp->mCachedXBLPrototypeHandlers.EnumerateRead(MarkXBLHandlers, nullptr);
|
||||
tmp->mCachedXBLPrototypeHandlers.Enumerate(MarkXBLHandlers, nullptr);
|
||||
}
|
||||
nsEventListenerManager* elm = tmp->GetListenerManager(false);
|
||||
if (elm) {
|
||||
@ -1749,7 +1749,7 @@ struct TraceData
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
TraceXBLHandlers(nsXBLPrototypeHandler* aKey, JSObject*& aData, void* aClosure)
|
||||
TraceXBLHandlers(nsXBLPrototypeHandler* aKey, JS::Heap<JSObject*>& aData, void* aClosure)
|
||||
{
|
||||
TraceData* data = static_cast<TraceData*>(aClosure);
|
||||
data->callbacks.Trace(&aData, "Cached XBL prototype handler", data->closure);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsJSThingHashtable.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
// Interfaces Needed
|
||||
@ -1234,7 +1235,7 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
|
||||
|
||||
nsDataHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*> mCachedXBLPrototypeHandlers;
|
||||
nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*> mCachedXBLPrototypeHandlers;
|
||||
|
||||
nsCOMPtr<nsIDocument> mSuspendedDoc;
|
||||
|
||||
|
@ -268,7 +268,7 @@ protected:
|
||||
virtual void UpdateScopeObject(JS::Handle<JSObject*> aScopeObject) = 0;
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
JSObject* mScopeObject;
|
||||
JS::Heap<JSObject*> mScopeObject;
|
||||
nsISupports* mTarget;
|
||||
nsCOMPtr<nsIAtom> mEventName;
|
||||
nsEventHandler mHandler;
|
||||
|
@ -3523,7 +3523,7 @@ public:
|
||||
|
||||
protected:
|
||||
JSContext *mContext;
|
||||
JS::Value *mArgv;
|
||||
JS::Heap<JS::Value> *mArgv;
|
||||
uint32_t mArgc;
|
||||
};
|
||||
|
||||
@ -3534,9 +3534,10 @@ nsJSArgArray::nsJSArgArray(JSContext *aContext, uint32_t argc, JS::Value *argv,
|
||||
mArgc(argc)
|
||||
{
|
||||
// copy the array - we don't know its lifetime, and ours is tied to xpcom
|
||||
// refcounting. Alloc zero'd array so cleanup etc is safe.
|
||||
// refcounting.
|
||||
if (argc) {
|
||||
mArgv = (JS::Value *) PR_CALLOC(argc * sizeof(JS::Value));
|
||||
static const fallible_t fallible = fallible_t();
|
||||
mArgv = new (fallible) JS::Heap<JS::Value>[argc];
|
||||
if (!mArgv) {
|
||||
*prv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return;
|
||||
@ -3566,7 +3567,7 @@ void
|
||||
nsJSArgArray::ReleaseJSObjects()
|
||||
{
|
||||
if (mArgv) {
|
||||
PR_DELETE(mArgv);
|
||||
delete [] mArgv;
|
||||
}
|
||||
if (mArgc > 0) {
|
||||
mArgc = 0;
|
||||
|
@ -67,10 +67,11 @@ private:
|
||||
// caller of setTimeout()
|
||||
nsCString mFileName;
|
||||
uint32_t mLineNo;
|
||||
nsTArray<JS::Value> mArgs;
|
||||
nsTArray<JS::Heap<JS::Value> > mArgs;
|
||||
|
||||
// The JS expression to evaluate or function to call, if !mExpr
|
||||
JSFlatString *mExpr;
|
||||
// Note this is always a flat string.
|
||||
JS::Heap<JSString*> mExpr;
|
||||
nsRefPtr<Function> mFunction;
|
||||
};
|
||||
|
||||
@ -281,7 +282,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
|
||||
NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler);
|
||||
|
||||
mExpr = expr;
|
||||
mExpr = JS_FORGET_STRING_FLATNESS(expr);
|
||||
|
||||
// Get the calling location.
|
||||
const char *filename;
|
||||
@ -299,7 +300,8 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
// array.
|
||||
// std::max(argc - 2, 0) wouldn't work right because argc is unsigned.
|
||||
uint32_t argCount = std::max(argc, 2u) - 2;
|
||||
FallibleTArray<JS::Value> args;
|
||||
|
||||
FallibleTArray<JS::Heap<JS::Value> > args;
|
||||
if (!args.SetCapacity(argCount)) {
|
||||
// No need to drop here, since we already have a non-null mFunction
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
@ -319,7 +321,7 @@ const PRUnichar *
|
||||
nsJSScriptTimeoutHandler::GetHandlerText()
|
||||
{
|
||||
NS_ASSERTION(mExpr, "No expression, so no handler text!");
|
||||
return ::JS_GetFlatStringChars(mExpr);
|
||||
return ::JS_GetFlatStringChars(JS_ASSERT_STRING_IS_FLAT(mExpr));
|
||||
}
|
||||
|
||||
nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
struct JSTracer;
|
||||
class JSObject;
|
||||
@ -182,7 +182,7 @@ public:
|
||||
void TraceWrapper(const TraceCallbacks& aCallbacks, void* aClosure)
|
||||
{
|
||||
if (PreservingWrapper() && mWrapper) {
|
||||
aCallbacks.Trace(&mWrapper, "Preserved wrapper", aClosure);
|
||||
aCallbacks.Trace(&mWrapper, "Preserved wrapper", aClosure);
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,8 +280,8 @@ private:
|
||||
enum { kWrapperFlagsMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_DOM_BINDING |
|
||||
WRAPPER_HAS_SOW) };
|
||||
|
||||
JSObject* mWrapper;
|
||||
uint32_t mFlags;
|
||||
JS::Heap<JSObject*> mWrapper;
|
||||
uint32_t mFlags;
|
||||
};
|
||||
|
||||
enum { WRAPPER_CACHE_FLAGS_BITS_USED = 3 };
|
||||
|
@ -50,7 +50,7 @@ nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis)
|
||||
inline void
|
||||
nsWrapperCache::TraceWrapperJSObject(JSTracer* aTrc, const char* aName)
|
||||
{
|
||||
JS_CallObjectTracer(aTrc, &mWrapper, aName);
|
||||
JS_CallHeapObjectTracer(aTrc, &mWrapper, aName);
|
||||
}
|
||||
|
||||
#endif /* nsWrapperCache_h___ */
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
*/
|
||||
JS::Handle<JSObject*> CallbackPreserveColor() const
|
||||
{
|
||||
return JS::Handle<JSObject*>::fromMarkedLocation(&mCallback);
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
enum ExceptionHandling {
|
||||
@ -111,7 +111,7 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* mCallback;
|
||||
JS::Heap<JSObject*> mCallback;
|
||||
|
||||
class MOZ_STACK_CLASS CallSetup
|
||||
{
|
||||
|
@ -262,10 +262,12 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &mJsUuids))) {
|
||||
JS::Rooted<JSObject*> uuids(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
|
||||
NS_WARNING("Cannot set JS UUIDs object!");
|
||||
return;
|
||||
}
|
||||
mJsUuids = uuids;
|
||||
Root();
|
||||
} else if (name.EqualsLiteral("Devices")) {
|
||||
mDeviceAddresses = value.get_ArrayOfnsString();
|
||||
@ -280,11 +282,13 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
JS::Rooted<JSObject*> deviceAddresses(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses,
|
||||
&mJsDeviceAddresses))) {
|
||||
deviceAddresses.address()))) {
|
||||
NS_WARNING("Cannot set JS Devices object!");
|
||||
return;
|
||||
}
|
||||
mJsDeviceAddresses = deviceAddresses;
|
||||
Root();
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
|
@ -72,8 +72,8 @@ private:
|
||||
uint32_t mClass;
|
||||
nsTArray<nsString> mDeviceAddresses;
|
||||
nsTArray<nsString> mUuids;
|
||||
JSObject* mJsUuids;
|
||||
JSObject* mJsDeviceAddresses;
|
||||
JS::Heap<JSObject*> mJsUuids;
|
||||
JS::Heap<JSObject*> mJsDeviceAddresses;
|
||||
bool mIsRooted;
|
||||
};
|
||||
|
||||
|
@ -124,10 +124,12 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &mJsUuids))) {
|
||||
JS::Rooted<JSObject*> uuids(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, uuids.address()))) {
|
||||
NS_WARNING("Cannot set JS UUIDs object!");
|
||||
return;
|
||||
}
|
||||
mJsUuids = uuids;
|
||||
Root();
|
||||
} else if (name.EqualsLiteral("Services")) {
|
||||
mServices = value.get_ArrayOfnsString();
|
||||
@ -137,10 +139,12 @@ BluetoothDevice::SetPropertyByValue(const BluetoothNamedValue& aValue)
|
||||
|
||||
AutoPushJSContext cx(sc->GetNativeContext());
|
||||
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mServices, &mJsServices))) {
|
||||
JS::Rooted<JSObject*> services(cx);
|
||||
if (NS_FAILED(nsTArrayToJSArray(cx, mServices, services.address()))) {
|
||||
NS_WARNING("Cannot set JS Services object!");
|
||||
return;
|
||||
}
|
||||
mJsServices = services;
|
||||
Root();
|
||||
} else {
|
||||
nsCString warningMsg;
|
||||
|
@ -58,8 +58,8 @@ private:
|
||||
~BluetoothDevice();
|
||||
void Root();
|
||||
|
||||
JSObject* mJsUuids;
|
||||
JSObject* mJsServices;
|
||||
JS::Heap<JSObject*> mJsUuids;
|
||||
JS::Heap<JSObject*> mJsServices;
|
||||
|
||||
nsString mAdapterPath;
|
||||
nsString mAddress;
|
||||
|
@ -107,7 +107,7 @@ private:
|
||||
nsTArray<nsRefPtr<FutureCallback> > mResolveCallbacks;
|
||||
nsTArray<nsRefPtr<FutureCallback> > mRejectCallbacks;
|
||||
|
||||
JS::Value mResult;
|
||||
JS::Heap<JS::Value> mResult;
|
||||
FutureState mState;
|
||||
bool mTaskPending;
|
||||
};
|
||||
|
@ -544,7 +544,7 @@ IDBCursor::GetKey(JSContext* aCx,
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
nsresult rv = mKey.ToJSVal(aCx, &mCachedKey);
|
||||
nsresult rv = mKey.ToJSVal(aCx, mCachedKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHaveCachedKey = true;
|
||||
@ -578,7 +578,7 @@ IDBCursor::GetPrimaryKey(JSContext* aCx,
|
||||
|
||||
const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey;
|
||||
|
||||
nsresult rv = key.ToJSVal(aCx, &mCachedPrimaryKey);
|
||||
nsresult rv = key.ToJSVal(aCx, mCachedPrimaryKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHaveCachedPrimaryKey = true;
|
||||
@ -739,7 +739,7 @@ IDBCursor::Update(const jsval& aValue,
|
||||
}
|
||||
else {
|
||||
JS::Rooted<JS::Value> keyVal(aCx);
|
||||
rv = objectKey.ToJSVal(aCx, keyVal.address());
|
||||
rv = objectKey.ToJSVal(aCx, &keyVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mObjectStore->Put(aValue, keyVal, aCx, 1, getter_AddRefs(request));
|
||||
@ -810,7 +810,7 @@ IDBCursor::Delete(JSContext* aCx,
|
||||
Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||
|
||||
JS::Rooted<JS::Value> key(aCx);
|
||||
nsresult rv = objectKey.ToJSVal(aCx, key.address());
|
||||
nsresult rv = objectKey.ToJSVal(aCx, &key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIIDBRequest> request;
|
||||
|
@ -168,7 +168,7 @@ protected:
|
||||
nsRefPtr<IDBObjectStore> mObjectStore;
|
||||
nsRefPtr<IDBIndex> mIndex;
|
||||
|
||||
JSObject* mScriptOwner;
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
|
||||
Type mType;
|
||||
Direction mDirection;
|
||||
@ -176,9 +176,9 @@ protected:
|
||||
nsCString mContinueToQuery;
|
||||
|
||||
// These are cycle-collected!
|
||||
jsval mCachedKey;
|
||||
jsval mCachedPrimaryKey;
|
||||
jsval mCachedValue;
|
||||
JS::Heap<JS::Value> mCachedKey;
|
||||
JS::Heap<JS::Value> mCachedPrimaryKey;
|
||||
JS::Heap<JS::Value> mCachedValue;
|
||||
|
||||
Key mRangeKey;
|
||||
|
||||
|
@ -183,7 +183,7 @@ private:
|
||||
// If this factory lives on a window then mWindow must be non-null. Otherwise
|
||||
// mOwningObject must be non-null.
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
JSObject* mOwningObject;
|
||||
JS::Heap<JSObject*> mOwningObject;
|
||||
|
||||
IndexedDBChild* mActorChild;
|
||||
IndexedDBParent* mActorParent;
|
||||
|
@ -810,7 +810,7 @@ IDBIndex::GetKeyPath(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = GetKeyPath().ToJSVal(aCx, &mCachedKeyPath);
|
||||
nsresult rv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (JSVAL_IS_GCTHING(mCachedKeyPath)) {
|
||||
@ -1180,7 +1180,12 @@ nsresult
|
||||
GetKeyHelper::GetSuccessResult(JSContext* aCx,
|
||||
jsval* aVal)
|
||||
{
|
||||
return mKey.ToJSVal(aCx, aVal);
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = mKey.ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aVal = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1508,7 +1513,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
|
||||
NS_ASSERTION(!key.IsUnset(), "Bad key!");
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = key.ToJSVal(aCx, value.address());
|
||||
nsresult rv = key.ToJSVal(aCx, &value);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get jsval for key!");
|
||||
return rv;
|
||||
|
@ -157,7 +157,7 @@ private:
|
||||
int64_t mId;
|
||||
nsString mName;
|
||||
KeyPath mKeyPath;
|
||||
JS::Value mCachedKeyPath;
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
|
||||
IndexedDBIndexChild* mActorChild;
|
||||
IndexedDBIndexParent* mActorParent;
|
||||
|
@ -363,7 +363,7 @@ IDBKeyRange::GetLower(JSContext* aCx,
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
nsresult rv = Lower().ToJSVal(aCx, &mCachedLowerVal);
|
||||
nsresult rv = Lower().ToJSVal(aCx, mCachedLowerVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHaveCachedLowerVal = true;
|
||||
@ -385,7 +385,7 @@ IDBKeyRange::GetUpper(JSContext* aCx,
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
nsresult rv = Upper().ToJSVal(aCx, &mCachedUpperVal);
|
||||
nsresult rv = Upper().ToJSVal(aCx, mCachedUpperVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHaveCachedUpperVal = true;
|
||||
|
@ -157,8 +157,8 @@ private:
|
||||
|
||||
Key mLower;
|
||||
Key mUpper;
|
||||
jsval mCachedLowerVal;
|
||||
jsval mCachedUpperVal;
|
||||
JS::Heap<JS::Value> mCachedLowerVal;
|
||||
JS::Heap<JS::Value> mCachedUpperVal;
|
||||
bool mLowerOpen;
|
||||
bool mUpperOpen;
|
||||
bool mIsOnly;
|
||||
|
@ -2387,7 +2387,7 @@ IDBObjectStore::GetKeyPath(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = GetKeyPath().ToJSVal(aCx, &mCachedKeyPath);
|
||||
nsresult rv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (JSVAL_IS_GCTHING(mCachedKeyPath)) {
|
||||
@ -3134,7 +3134,12 @@ AddHelper::GetSuccessResult(JSContext* aCx,
|
||||
|
||||
mCloneWriteInfo.mCloneBuffer.clear();
|
||||
|
||||
return mKey.ToJSVal(aCx, aVal);
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = mKey.ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aVal = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -287,7 +287,7 @@ private:
|
||||
int64_t mId;
|
||||
nsString mName;
|
||||
KeyPath mKeyPath;
|
||||
JS::Value mCachedKeyPath;
|
||||
JS::Heap<JS::Value> mCachedKeyPath;
|
||||
bool mRooted;
|
||||
bool mAutoIncrement;
|
||||
nsCOMPtr<nsIAtom> mDatabaseId;
|
||||
|
@ -120,13 +120,15 @@ IDBRequest::NotifyHelperCompleted(HelperBase* aHelper)
|
||||
JSAutoCompartment ac(cx, global);
|
||||
AssertIsRooted();
|
||||
|
||||
rv = aHelper->GetSuccessResult(cx, &mResultVal);
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
rv = aHelper->GetSuccessResult(cx, value.address());
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("GetSuccessResult failed!");
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mError = nullptr;
|
||||
mResultVal = value;
|
||||
}
|
||||
else {
|
||||
SetError(rv);
|
||||
|
@ -109,7 +109,7 @@ protected:
|
||||
nsCOMPtr<nsISupports> mSource;
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
|
||||
jsval mResultVal;
|
||||
JS::Heap<JS::Value> mResultVal;
|
||||
nsRefPtr<mozilla::dom::DOMError> mError;
|
||||
IndexedDBRequestParentBase* mActorParent;
|
||||
nsString mFilename;
|
||||
|
@ -62,7 +62,7 @@ protected:
|
||||
virtual ~IDBWrapperCache();
|
||||
|
||||
private:
|
||||
JSObject* mScriptOwner;
|
||||
JS::Heap<JSObject*> mScriptOwner;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
@ -185,7 +185,7 @@ Key::EncodeJSValInternal(JSContext* aCx, const jsval aVal,
|
||||
// static
|
||||
nsresult
|
||||
Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
JSContext* aCx, uint8_t aTypeOffset, jsval* aVal,
|
||||
JSContext* aCx, uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal,
|
||||
uint16_t aRecursionDepth)
|
||||
{
|
||||
NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
|
||||
@ -208,7 +208,7 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) {
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
nsresult rv = DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset,
|
||||
val.address(), aRecursionDepth + 1);
|
||||
&val, aRecursionDepth + 1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aTypeOffset = 0;
|
||||
@ -223,12 +223,12 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
"Should have found end-of-array marker");
|
||||
++aPos;
|
||||
|
||||
*aVal = OBJECT_TO_JSVAL(array);
|
||||
aVal.setObject(*array);
|
||||
}
|
||||
else if (*aPos - aTypeOffset == eString) {
|
||||
nsString key;
|
||||
DecodeString(aPos, aEnd, key);
|
||||
if (!xpc::StringToJsval(aCx, key, aVal)) {
|
||||
if (!xpc::StringToJsval(aCx, key, aVal.address())) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
@ -240,10 +240,10 @@ Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd,
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
*aVal = OBJECT_TO_JSVAL(date);
|
||||
aVal.setObject(*date);
|
||||
}
|
||||
else if (*aPos - aTypeOffset == eFloat) {
|
||||
*aVal = DOUBLE_TO_JSVAL(DecodeNumber(aPos, aEnd));
|
||||
aVal.setDouble(DecodeNumber(aPos, aEnd));
|
||||
}
|
||||
else {
|
||||
NS_NOTREACHED("Unknown key type!");
|
||||
|
@ -179,10 +179,10 @@ public:
|
||||
}
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx,
|
||||
jsval* aVal) const
|
||||
JS::MutableHandle<JS::Value> aVal) const
|
||||
{
|
||||
if (IsUnset()) {
|
||||
*aVal = JSVAL_VOID;
|
||||
aVal.set(JSVAL_VOID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -196,6 +196,17 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx,
|
||||
JS::Heap<JS::Value>& aVal) const
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aVal = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult AppendItem(JSContext* aCx,
|
||||
bool aFirstOfArray,
|
||||
const jsval aVal)
|
||||
@ -304,7 +315,7 @@ private:
|
||||
// past the consumed value.
|
||||
static inline nsresult DecodeJSVal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd, JSContext* aCx,
|
||||
uint8_t aTypeOffset, jsval* aVal)
|
||||
uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal)
|
||||
{
|
||||
return DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, aVal, 0);
|
||||
}
|
||||
@ -324,7 +335,7 @@ private:
|
||||
static nsresult DecodeJSValInternal(const unsigned char*& aPos,
|
||||
const unsigned char* aEnd,
|
||||
JSContext* aCx, uint8_t aTypeOffset,
|
||||
jsval* aVal, uint16_t aRecursionDepth);
|
||||
JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth);
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
@ -457,7 +457,7 @@ KeyPath::DeserializeFromString(const nsAString& aString)
|
||||
}
|
||||
|
||||
nsresult
|
||||
KeyPath::ToJSVal(JSContext* aCx, JS::Value* aValue) const
|
||||
KeyPath::ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) const
|
||||
{
|
||||
if (IsArray()) {
|
||||
uint32_t len = mStrings.Length();
|
||||
@ -479,22 +479,33 @@ KeyPath::ToJSVal(JSContext* aCx, JS::Value* aValue) const
|
||||
}
|
||||
}
|
||||
|
||||
*aValue = OBJECT_TO_JSVAL(array);
|
||||
aValue.setObject(*array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsString()) {
|
||||
nsString tmp(mStrings[0]);
|
||||
if (!xpc::StringToJsval(aCx, tmp, aValue)) {
|
||||
if (!xpc::StringToJsval(aCx, tmp, aValue.address())) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aValue = JSVAL_NULL;
|
||||
aValue.setNull();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
KeyPath::ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aValue) const
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
nsresult rv = ToJSVal(aCx, &value);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aValue = value;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyPath::IsAllowedForObjectStore(bool aAutoIncrement) const
|
||||
{
|
||||
|
@ -87,7 +87,8 @@ public:
|
||||
void SerializeToString(nsAString& aString) const;
|
||||
static KeyPath DeserializeFromString(const nsAString& aString);
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx, JS::Value* aValue) const;
|
||||
nsresult ToJSVal(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) const;
|
||||
nsresult ToJSVal(JSContext* aCx, JS::Heap<JS::Value>& aValue) const;
|
||||
|
||||
bool IsAllowedForObjectStore(bool aAutoIncrement) const;
|
||||
|
||||
|
@ -1164,12 +1164,7 @@ public:
|
||||
|
||||
NS_METHOD GetFilename(nsAString& aFilename)
|
||||
{
|
||||
if (Preferences::GetBool("plugin.expose_full_path", false)) {
|
||||
CopyUTF8toUTF16(mPluginTag.mFullPath, aFilename);
|
||||
} else {
|
||||
CopyUTF8toUTF16(mPluginTag.mFileName, aFilename);
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(mPluginTag.mFileName, aFilename);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ class Telephony : public nsDOMEventTargetHelper,
|
||||
|
||||
// Cached calls array object. Cleared whenever mCalls changes and then rebuilt
|
||||
// once a page looks for the liveCalls attribute.
|
||||
JSObject* mCallsArray;
|
||||
JS::Heap<JSObject*> mCallsArray;
|
||||
|
||||
bool mRooted;
|
||||
bool mEnumerated;
|
||||
|
@ -15,12 +15,13 @@ namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
SourceSurfaceSkia::SourceSurfaceSkia()
|
||||
: mDrawTarget(nullptr)
|
||||
: mDrawTarget(nullptr), mLocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
SourceSurfaceSkia::~SourceSurfaceSkia()
|
||||
{
|
||||
MaybeUnlock();
|
||||
MarkIndependent();
|
||||
}
|
||||
|
||||
@ -85,17 +86,21 @@ SourceSurfaceSkia::InitFromData(unsigned char* aData,
|
||||
unsigned char*
|
||||
SourceSurfaceSkia::GetData()
|
||||
{
|
||||
mBitmap.lockPixels();
|
||||
unsigned char *pixels = (unsigned char *)mBitmap.getPixels();
|
||||
mBitmap.unlockPixels();
|
||||
return pixels;
|
||||
if (!mLocked) {
|
||||
mBitmap.lockPixels();
|
||||
mLocked = true;
|
||||
}
|
||||
|
||||
unsigned char *pixels = (unsigned char *)mBitmap.getPixels();
|
||||
return pixels;
|
||||
}
|
||||
|
||||
void
|
||||
SourceSurfaceSkia::DrawTargetWillChange()
|
||||
{
|
||||
if (mDrawTarget) {
|
||||
MaybeUnlock();
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
SkBitmap temp = mBitmap;
|
||||
mBitmap.reset();
|
||||
@ -118,5 +123,14 @@ SourceSurfaceSkia::MarkIndependent()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceSurfaceSkia::MaybeUnlock()
|
||||
{
|
||||
if (mLocked) {
|
||||
mBitmap.unlockPixels();
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -47,12 +47,14 @@ private:
|
||||
void DrawTargetWillChange();
|
||||
void DrawTargetDestroyed();
|
||||
void MarkIndependent();
|
||||
void MaybeUnlock();
|
||||
|
||||
SkBitmap mBitmap;
|
||||
SurfaceFormat mFormat;
|
||||
IntSize mSize;
|
||||
int32_t mStride;
|
||||
DrawTargetSkia* mDrawTarget;
|
||||
bool mLocked;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -466,6 +466,21 @@ public:
|
||||
*/
|
||||
virtual void SetIsFirstPaint() {}
|
||||
|
||||
/**
|
||||
* Make sure that the previous transaction has been entirely
|
||||
* completed.
|
||||
*
|
||||
* Note: This may sychronously wait on a remote compositor
|
||||
* to complete rendering.
|
||||
*/
|
||||
virtual void FlushRendering() { }
|
||||
|
||||
/**
|
||||
* Checks if we need to invalidate the OS widget to trigger
|
||||
* painting when updating this layer manager.
|
||||
*/
|
||||
virtual bool NeedsWidgetInvalidation() { return true; }
|
||||
|
||||
// We always declare the following logging symbols, because it's
|
||||
// extremely tricky to conditionally declare them. However, for
|
||||
// ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial
|
||||
|
@ -260,6 +260,16 @@ ClientLayerManager::MakeSnapshotIfRequired()
|
||||
mShadowTarget = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::FlushRendering()
|
||||
{
|
||||
if (mWidget) {
|
||||
if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
|
||||
remoteRenderer->SendFlushRendering();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::ForwardTransaction()
|
||||
{
|
||||
|
@ -53,6 +53,10 @@ public:
|
||||
virtual already_AddRefed<ColorLayer> CreateColorLayer();
|
||||
virtual already_AddRefed<RefLayer> CreateRefLayer();
|
||||
|
||||
virtual void FlushRendering() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool NeedsWidgetInvalidation() MOZ_OVERRIDE { return Compositor::GetBackend() == LAYERS_BASIC; }
|
||||
|
||||
ShadowableLayer* Hold(Layer* aLayer);
|
||||
|
||||
bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); }
|
||||
|
@ -249,6 +249,18 @@ CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvFlushRendering()
|
||||
{
|
||||
// If we're waiting to do a composite, then cancel it
|
||||
// and do it immediately instead.
|
||||
if (mCurrentCompositeTask) {
|
||||
mCurrentCompositeTask->Cancel();
|
||||
ComposeToTarget(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
@ -743,6 +755,7 @@ public:
|
||||
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
SurfaceDescriptor* aOutSnapshot)
|
||||
{ return true; }
|
||||
virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
|
||||
|
||||
virtual PLayerTransactionParent*
|
||||
AllocPLayerTransaction(const LayersBackend& aBackendType,
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
virtual bool RecvResume() MOZ_OVERRIDE;
|
||||
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
SurfaceDescriptor* aOutSnapshot);
|
||||
virtual bool RecvFlushRendering() MOZ_OVERRIDE;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -53,6 +53,10 @@ parent:
|
||||
sync MakeSnapshot(SurfaceDescriptor inSnapshot)
|
||||
returns (SurfaceDescriptor outSnapshot);
|
||||
|
||||
// Make sure any pending composites are started immediately and
|
||||
// block until they are completed.
|
||||
sync FlushRendering();
|
||||
|
||||
sync PLayerTransaction(LayersBackend layersBackendHint, uint64_t id)
|
||||
returns (TextureFactoryIdentifier textureFactoryIdentifier);
|
||||
};
|
||||
|
@ -181,18 +181,18 @@ class Heap : public js::HeapBase<T>
|
||||
Heap() {
|
||||
MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap<T>),
|
||||
"Heap<T> must be binary compatible with T.");
|
||||
set(js::RootMethods<T>::initial());
|
||||
init(js::RootMethods<T>::initial());
|
||||
}
|
||||
explicit Heap(T p) { set(p); }
|
||||
explicit Heap(const Heap<T> &p) { set(p.ptr); }
|
||||
explicit Heap(T p) { init(p); }
|
||||
explicit Heap(const Heap<T> &p) { init(p.ptr); }
|
||||
|
||||
~Heap() {
|
||||
if (js::RootMethods<T>::needsPostBarrier(ptr))
|
||||
relocate();
|
||||
}
|
||||
|
||||
bool operator!=(const T &other) { return *ptr != other; }
|
||||
bool operator==(const T &other) { return *ptr == other; }
|
||||
bool operator!=(const T &other) const { return ptr != other; }
|
||||
bool operator==(const T &other) const { return ptr == other; }
|
||||
|
||||
operator T() const { return ptr; }
|
||||
T operator->() const { return ptr; }
|
||||
@ -220,6 +220,13 @@ class Heap : public js::HeapBase<T>
|
||||
}
|
||||
|
||||
private:
|
||||
void init(T newPtr) {
|
||||
JS_ASSERT(!js::RootMethods<T>::poisoned(newPtr));
|
||||
ptr = newPtr;
|
||||
if (js::RootMethods<T>::needsPostBarrier(ptr))
|
||||
post();
|
||||
}
|
||||
|
||||
void post() {
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
JS_ASSERT(js::RootMethods<T>::needsPostBarrier(ptr));
|
||||
@ -320,8 +327,8 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
|
||||
operator const T&() const { return get(); }
|
||||
T operator->() const { return get(); }
|
||||
|
||||
bool operator!=(const T &other) { return *ptr != other; }
|
||||
bool operator==(const T &other) { return *ptr == other; }
|
||||
bool operator!=(const T &other) const { return *ptr != other; }
|
||||
bool operator==(const T &other) const { return *ptr == other; }
|
||||
|
||||
private:
|
||||
Handle() {}
|
||||
@ -605,8 +612,8 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
||||
ptr = value;
|
||||
}
|
||||
|
||||
bool operator!=(const T &other) { return ptr != other; }
|
||||
bool operator==(const T &other) { return ptr == other; }
|
||||
bool operator!=(const T &other) const { return ptr != other; }
|
||||
bool operator==(const T &other) const { return ptr == other; }
|
||||
|
||||
private:
|
||||
void commonInit(Rooted<void*> **thingGCRooters) {
|
||||
@ -766,8 +773,8 @@ class FakeRooted : public RootedBase<T>
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool operator!=(const T &other) { return ptr != other; }
|
||||
bool operator==(const T &other) { return ptr == other; }
|
||||
bool operator!=(const T &other) const { return ptr != other; }
|
||||
bool operator==(const T &other) const { return ptr == other; }
|
||||
|
||||
private:
|
||||
T ptr;
|
||||
|
@ -1420,6 +1420,7 @@ template <> struct RootMethods<JS::Value>
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Outer> class UnbarrieredMutableValueOperations;
|
||||
template <class Outer> class MutableValueOperations;
|
||||
|
||||
/*
|
||||
@ -1431,7 +1432,9 @@ template <class Outer> class MutableValueOperations;
|
||||
template <class Outer>
|
||||
class ValueOperations
|
||||
{
|
||||
friend class UnbarrieredMutableValueOperations<Outer>;
|
||||
friend class MutableValueOperations<Outer>;
|
||||
|
||||
const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
|
||||
|
||||
public:
|
||||
@ -1469,14 +1472,16 @@ class ValueOperations
|
||||
};
|
||||
|
||||
/*
|
||||
* A class designed for CRTP use in implementing the mutating parts of the
|
||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
||||
* MutableValueOperations<Outer> with visible extractMutable() and extract()
|
||||
* methods returning the const Value* and Value* abstracted by Outer.
|
||||
* A class designed for CRTP use in implementing the mutating parts of the Value
|
||||
* interface in Value-like classes that don't need post barriers. Outer must be
|
||||
* a class inheriting UnbarrieredMutableValueOperations<Outer> with visible
|
||||
* extractMutable() and extract() methods returning the const Value* and Value*
|
||||
* abstracted by Outer.
|
||||
*/
|
||||
template <class Outer>
|
||||
class MutableValueOperations : public ValueOperations<Outer>
|
||||
class UnbarrieredMutableValueOperations : public ValueOperations<Outer>
|
||||
{
|
||||
friend class MutableValueOperations<Outer>;
|
||||
JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
|
||||
|
||||
public:
|
||||
@ -1484,26 +1489,65 @@ class MutableValueOperations : public ValueOperations<Outer>
|
||||
void setUndefined() { value()->setUndefined(); }
|
||||
void setInt32(int32_t i) { value()->setInt32(i); }
|
||||
void setDouble(double d) { value()->setDouble(d); }
|
||||
void setString(JSString *str) { value()->setString(str); }
|
||||
void setString(const JS::Anchor<JSString *> &str) { value()->setString(str); }
|
||||
void setObject(JSObject &obj) { value()->setObject(obj); }
|
||||
void setBoolean(bool b) { value()->setBoolean(b); }
|
||||
void setMagic(JSWhyMagic why) { value()->setMagic(why); }
|
||||
bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
|
||||
bool setNumber(double d) { return value()->setNumber(d); }
|
||||
void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(arg); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Augment the generic Heap<T> interface when T = Value with type-querying
|
||||
* and value-extracting operations.
|
||||
* A class designed for CRTP use in implementing all the mutating parts of the
|
||||
* Value interface in Value-like classes. Outer must be a class inheriting
|
||||
* MutableValueOperations<Outer> with visible extractMutable() and extract()
|
||||
* methods returning the const Value* and Value* abstracted by Outer.
|
||||
*/
|
||||
template <class Outer>
|
||||
class MutableValueOperations : public UnbarrieredMutableValueOperations<Outer>
|
||||
{
|
||||
public:
|
||||
void setString(JSString *str) { this->value()->setString(str); }
|
||||
void setString(const JS::Anchor<JSString *> &str) { this->value()->setString(str); }
|
||||
void setObject(JSObject &obj) { this->value()->setObject(obj); }
|
||||
void setObjectOrNull(JSObject *arg) { this->value()->setObjectOrNull(arg); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Augment the generic Heap<T> interface when T = Value with
|
||||
* type-querying, value-extracting, and mutating operations.
|
||||
*/
|
||||
template <>
|
||||
class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
|
||||
class HeapBase<JS::Value> : public UnbarrieredMutableValueOperations<JS::Heap<JS::Value> >
|
||||
{
|
||||
friend class ValueOperations<JS::Heap<JS::Value> >;
|
||||
const JS::Value * extract() const {
|
||||
return static_cast<const JS::Heap<JS::Value>*>(this)->address();
|
||||
typedef JS::Heap<JS::Value> Outer;
|
||||
|
||||
friend class ValueOperations<Outer>;
|
||||
friend class UnbarrieredMutableValueOperations<Outer>;
|
||||
|
||||
const JS::Value * extract() const { return static_cast<const Outer*>(this)->address(); }
|
||||
JS::Value * extractMutable() { return static_cast<Outer*>(this)->unsafeGet(); }
|
||||
|
||||
/*
|
||||
* Setters that potentially change the value to a GC thing from a non-GC
|
||||
* thing must call JS::Heap::set() to trigger the post barrier.
|
||||
*
|
||||
* Changing from a GC thing to a non-GC thing value will leave the heap
|
||||
* value in the store buffer, but it will be ingored so this is not a
|
||||
* problem.
|
||||
*/
|
||||
void setBarriered(const JS::Value &v) {
|
||||
static_cast<JS::Heap<JS::Value> *>(this)->set(v);
|
||||
}
|
||||
|
||||
public:
|
||||
void setString(JSString *str) { setBarriered(JS::StringValue(str)); }
|
||||
void setString(const JS::Anchor<JSString *> &str) { setBarriered(JS::StringValue(str.get())); }
|
||||
void setObject(JSObject &obj) { setBarriered(JS::ObjectValue(obj)); }
|
||||
|
||||
void setObjectOrNull(JSObject *arg) {
|
||||
if (arg)
|
||||
setObject(*arg);
|
||||
else
|
||||
setNull();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1532,6 +1576,7 @@ class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHa
|
||||
return static_cast<const JS::MutableHandle<JS::Value>*>(this)->address();
|
||||
}
|
||||
|
||||
friend class UnbarrieredMutableValueOperations<JS::MutableHandle<JS::Value> >;
|
||||
friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
|
||||
JS::Value * extractMutable() {
|
||||
return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
|
||||
@ -1550,6 +1595,7 @@ class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value
|
||||
return static_cast<const JS::Rooted<JS::Value>*>(this)->address();
|
||||
}
|
||||
|
||||
friend class UnbarrieredMutableValueOperations<JS::Rooted<JS::Value> >;
|
||||
friend class MutableValueOperations<JS::Rooted<JS::Value> >;
|
||||
JS::Value * extractMutable() {
|
||||
return static_cast<JS::Rooted<JS::Value>*>(this)->address();
|
||||
|
@ -305,6 +305,19 @@ case "$target" in
|
||||
if test ! -d "$android_platform_tools" ; then
|
||||
android_platform_tools="$android_sdk"/tools # SDK Tools < r8
|
||||
fi
|
||||
# The build tools got moved around to different directories in
|
||||
# SDK Tools r22. Try to locate them.
|
||||
android_build_tools=""
|
||||
for suffix in 17.0.0 android-4.2.2; do
|
||||
tools_directory="$android_sdk/../../build-tools/$suffix"
|
||||
if test -d "$tools_directory" ; then
|
||||
android_build_tools="$tools_directory"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$android_build_tools" ; then
|
||||
android_build_tools="$android_platform_tools" # SDK Tools < r22
|
||||
fi
|
||||
ANDROID_SDK="${android_sdk}"
|
||||
if test -e "${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar" ; then
|
||||
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/compatibility/v4/android-support-v4.jar"
|
||||
@ -312,12 +325,14 @@ case "$target" in
|
||||
ANDROID_COMPAT_LIB="${android_sdk}/../../extras/android/support/v4/android-support-v4.jar";
|
||||
fi
|
||||
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
|
||||
ANDROID_BUILD_TOOLS="${android_build_tools}"
|
||||
AC_SUBST(ANDROID_SDK)
|
||||
AC_SUBST(ANDROID_COMPAT_LIB)
|
||||
if ! test -e $ANDROID_COMPAT_LIB ; then
|
||||
AC_MSG_ERROR([You must download the Android support library when targeting Android. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_COMPAT_LIB)])
|
||||
fi
|
||||
AC_SUBST(ANDROID_PLATFORM_TOOLS)
|
||||
AC_SUBST(ANDROID_BUILD_TOOLS)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user