mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge the last PGO-green inbound changeset to m-c.
This commit is contained in:
commit
8567838adc
@ -161,6 +161,7 @@
|
||||
@BINPATH@/components/dom.xpt
|
||||
@BINPATH@/components/dom_apps.xpt
|
||||
@BINPATH@/components/dom_base.xpt
|
||||
@BINPATH@/components/dom_system.xpt
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_wifi.xpt
|
||||
|
@ -10,6 +10,7 @@ VPATH = @srcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dom
|
||||
XPIDL_MODULE = dom_system
|
||||
LIBRARY_NAME = domsystem_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
@ -31,6 +32,9 @@ endif
|
||||
|
||||
DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIOSFileConstantsService.idl \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsDeviceSensors.cpp \
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "nsString.h"
|
||||
|
||||
#include "OSFileConstants.h"
|
||||
#include "nsIOSFileConstantsService.h"
|
||||
|
||||
/**
|
||||
* This module defines the basic libc constants (error numbers, open modes,
|
||||
@ -64,7 +65,7 @@ nsresult InitOSFileConstants()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (gInitialized) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gInitialized = true;
|
||||
@ -86,15 +87,15 @@ nsresult InitOSFileConstants()
|
||||
return libDir->GetPath(*gLibDirectory);
|
||||
}
|
||||
|
||||
nsresult CleanupOSFileConstants()
|
||||
void CleanupOSFileConstants()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!gInitialized) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return;
|
||||
}
|
||||
|
||||
gInitialized = false;
|
||||
delete gLibDirectory;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -474,5 +475,36 @@ bool DefineOSFileConstants(JSContext *cx, JSObject *global)
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
NS_IMPL_ISUPPORTS1(OSFileConstantsService, nsIOSFileConstantsService)
|
||||
|
||||
OSFileConstantsService::OSFileConstantsService()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
OSFileConstantsService::~OSFileConstantsService()
|
||||
{
|
||||
mozilla::CleanupOSFileConstants();
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
OSFileConstantsService::Init(JSContext *aCx)
|
||||
{
|
||||
nsresult rv = mozilla::InitOSFileConstants();
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSObject *global = JS_GetGlobalForScopeChain(aCx);
|
||||
if (!global) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!mozilla::DefineOSFileConstants(aCx, global)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define mozilla_osfileconstants_h__
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "nsIOSFileConstantsService.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -14,8 +15,9 @@ namespace mozilla {
|
||||
*
|
||||
* This function _must_ be called:
|
||||
* - from the main thread;
|
||||
* - only once;
|
||||
* - before any Chrome Worker is created.
|
||||
*
|
||||
* The function is idempotent.
|
||||
*/
|
||||
nsresult InitOSFileConstants();
|
||||
|
||||
@ -24,10 +26,11 @@ nsresult InitOSFileConstants();
|
||||
*
|
||||
* This function _must_ be called:
|
||||
* - from the main thread;
|
||||
* - only once;
|
||||
* - after all Chrome Workers are dead.
|
||||
*
|
||||
* The function is idempotent.
|
||||
*/
|
||||
nsresult CleanupOSFileConstants();
|
||||
void CleanupOSFileConstants();
|
||||
|
||||
/**
|
||||
* Define OS-specific constants.
|
||||
@ -37,6 +40,19 @@ nsresult CleanupOSFileConstants();
|
||||
*/
|
||||
bool DefineOSFileConstants(JSContext *cx, JSObject *global);
|
||||
|
||||
/**
|
||||
* XPConnect initializer, for use in the main thread.
|
||||
*/
|
||||
class OSFileConstantsService: public nsIOSFileConstantsService
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOSFILECONSTANTSSERVICE
|
||||
OSFileConstantsService();
|
||||
private:
|
||||
~OSFileConstantsService();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // mozilla_osfileconstants_h__
|
||||
|
28
dom/system/nsIOSFileConstantsService.idl
Normal file
28
dom/system/nsIOSFileConstantsService.idl
Normal file
@ -0,0 +1,28 @@
|
||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=40: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(d6dd239f-34d6-4b34-baa1-f69ab4a20bc4)]
|
||||
interface nsIOSFileConstantsService: nsISupports
|
||||
{
|
||||
/**
|
||||
* Inject module OS.Constants in the environment.
|
||||
*
|
||||
* This method must be called only from the main thread.
|
||||
* Method is idempotent.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void init();
|
||||
};
|
||||
|
||||
%{ C++
|
||||
|
||||
// {4BBE1B96-8956-457F-A03F-9C27435F2AFA}
|
||||
#define OSFILECONSTANTSSERVICE_CID {0x4BBE1B96,0x8956,0x457F,{0xA0,0x3F,0x9C,0x27,0x43,0x5F,0x2A,0xFA}}
|
||||
#define OSFILECONSTANTSSERVICE_CONTRACTID "@mozilla.org/net/osfileconstantsservice;1"
|
||||
|
||||
%}
|
@ -16,8 +16,33 @@
|
||||
|
||||
let worker;
|
||||
|
||||
function test_xul() {
|
||||
let lib;
|
||||
isnot(null, OS.Constants.Path.libxul, "libxulpath is defined");
|
||||
try {
|
||||
lib = ctypes.open(OS.Constants.Path.libxul);
|
||||
lib.declare("DumpJSStack", ctypes.default_abi, ctypes.void_t);
|
||||
} catch (x) {
|
||||
success = false;
|
||||
ok(false, "Could not open libxul " + x);
|
||||
}
|
||||
if (lib) {
|
||||
lib.close();
|
||||
}
|
||||
ok(true, "test_xul: opened libxul successfully");
|
||||
}
|
||||
|
||||
function test() {
|
||||
ok(true, "test_constants.xul: Starting test");
|
||||
|
||||
// Test 1: Load libxul from main thread
|
||||
Components.classes["@mozilla.org/net/osfileconstantsservice;1"].
|
||||
getService(Components.interfaces.nsIOSFileConstantsService).
|
||||
init();
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
test_xul();
|
||||
|
||||
// Test 2: Load libxul from chrome thread
|
||||
worker = new ChromeWorker("worker_constants.js");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
ok(true, "test_constants.xul: Chrome worker created");
|
||||
|
@ -1050,10 +1050,7 @@ RuntimeService::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = CleanupOSFileConstants();
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_NOT_REACHED("Could not cleanup OSFileConstants");
|
||||
}
|
||||
CleanupOSFileConstants();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -1539,8 +1539,6 @@ JS_WrapValue(JSContext *cx, jsval *vp)
|
||||
* is used to make this happen if an object other than |target| is used.
|
||||
*/
|
||||
|
||||
static bool RemapWrappers(JSContext *cx, JSObject *orig, JSObject *target);
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
|
||||
{
|
||||
@ -1582,7 +1580,7 @@ JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
|
||||
|
||||
// Now, iterate through other scopes looking for references to the
|
||||
// old object, and update the relevant cross-compartment wrappers.
|
||||
if (!RemapWrappers(cx, origobj, newIdentity))
|
||||
if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
|
||||
return NULL;
|
||||
|
||||
// Lastly, update the original object to point to the new one.
|
||||
@ -1601,60 +1599,6 @@ JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
|
||||
return newIdentity;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap cross-compartment wrappers pointing to |src| to point to |dst|. All
|
||||
* wrappers are recomputed.
|
||||
*/
|
||||
static bool
|
||||
RemapWrappers(JSContext *cx, JSObject *orig, JSObject *target)
|
||||
{
|
||||
Value origv = ObjectValue(*orig);
|
||||
Value targetv = ObjectValue(*target);
|
||||
|
||||
CompartmentVector &vector = cx->runtime->compartments;
|
||||
AutoValueVector toTransplant(cx);
|
||||
if (!toTransplant.reserve(vector.length()))
|
||||
return false;
|
||||
|
||||
for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
|
||||
WrapperMap &pmap = (*p)->crossCompartmentWrappers;
|
||||
if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
|
||||
// We found a wrapper. Remember and root it.
|
||||
toTransplant.infallibleAppend(wp->value);
|
||||
}
|
||||
}
|
||||
|
||||
for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
|
||||
JSObject *wobj = &begin->toObject();
|
||||
JSCompartment *wcompartment = wobj->compartment();
|
||||
WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
|
||||
|
||||
// When we remove origv from the wrapper map, its wrapper, wobj, must
|
||||
// immediately cease to be a cross-compartment wrapper. Neuter it.
|
||||
JS_ASSERT(pmap.lookup(origv));
|
||||
pmap.remove(origv);
|
||||
NukeCrossCompartmentWrapper(wobj);
|
||||
|
||||
// First, we wrap it in the new compartment. This will return
|
||||
// a new wrapper.
|
||||
AutoCompartment ac(cx, wobj);
|
||||
JSObject *tobj = target;
|
||||
if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
|
||||
return false;
|
||||
|
||||
// Now, because we need to maintain object identity, we do a
|
||||
// brain transplant on the old object. At the same time, we
|
||||
// update the entry in the compartment's wrapper map to point
|
||||
// to the old wrapper.
|
||||
JS_ASSERT(tobj != wobj);
|
||||
if (!wobj->swap(cx, tobj))
|
||||
return false;
|
||||
pmap.put(targetv, ObjectValue(*wobj));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The location object is special. There is the location object itself and
|
||||
* then the location object wrapper. Because there are no direct references to
|
||||
@ -1706,7 +1650,7 @@ js_TransplantObjectWithWrapper(JSContext *cx,
|
||||
// Now, iterate through other scopes looking for references to the old
|
||||
// object. Note that the entries in the maps are for |origobj| and not
|
||||
// |origwrapper|. They need to be updated to point at the new object.
|
||||
if (!RemapWrappers(cx, origobj, targetobj))
|
||||
if (!RemapAllWrappersForObject(cx, origobj, targetobj))
|
||||
return NULL;
|
||||
|
||||
// Lastly, update things in the original compartment. Our invariants dictate
|
||||
@ -1736,7 +1680,7 @@ js_TransplantObjectWithWrapper(JSContext *cx,
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return RemapWrappers(cx, obj, obj);
|
||||
return RemapAllWrappersForObject(cx, obj, obj);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -1174,10 +1174,7 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
|
||||
* all the allocations and released the empty GC chunks.
|
||||
*/
|
||||
ShrinkGCBuffers(this);
|
||||
{
|
||||
AutoLockGC lock(this);
|
||||
gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
}
|
||||
gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
if (!p)
|
||||
p = OffTheBooks::malloc_(nbytes);
|
||||
else if (p == reinterpret_cast<void *>(1))
|
||||
|
@ -259,6 +259,10 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
||||
if (!wrapper)
|
||||
return false;
|
||||
|
||||
// We maintain the invariant that the key in the cross-compartment wrapper
|
||||
// map is always directly wrapped by the value.
|
||||
JS_ASSERT(Wrapper::wrappedObject(wrapper) == &key.reference().toObject());
|
||||
|
||||
vp->setObject(*wrapper);
|
||||
|
||||
if (wrapper->getProto() != proto && !SetProto(cx, wrapper, proto, false))
|
||||
|
@ -828,7 +828,9 @@ js_InitGC(JSRuntime *rt, uint32_t maxbytes)
|
||||
rt->gcMaxBytes = maxbytes;
|
||||
rt->setGCMaxMallocBytes(maxbytes);
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1664,7 +1666,6 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
if (secondAttempt)
|
||||
break;
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
}
|
||||
|
||||
@ -2495,6 +2496,7 @@ MaybeGC(JSContext *cx)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
/*
|
||||
* Access to the counters and, on 32 bit, setting gcNextFullGCTime below
|
||||
* is not atomic and a race condition could trigger or suppress the GC. We
|
||||
@ -2511,6 +2513,7 @@ MaybeGC(JSContext *cx)
|
||||
rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2788,12 +2791,11 @@ GCHelperThread::prepareForBackgroundSweep()
|
||||
#endif /* JS_THREADSAFE */
|
||||
}
|
||||
|
||||
/* Must be called with the GC lock taken. */
|
||||
void
|
||||
GCHelperThread::startBackgroundSweep(bool shouldShrink)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/* The caller takes the GC lock. */
|
||||
AutoLockGC lock(rt);
|
||||
JS_ASSERT(state == IDLE);
|
||||
JS_ASSERT(!sweepFlag);
|
||||
sweepFlag = true;
|
||||
@ -2833,11 +2835,11 @@ GCHelperThread::startBackgroundShrink()
|
||||
}
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
/* Must be called with the GC lock taken. */
|
||||
void
|
||||
GCHelperThread::waitBackgroundSweepEnd()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
AutoLockGC lock(rt);
|
||||
while (state == SWEEPING)
|
||||
PR_WaitCondVar(done, PR_INTERVAL_NO_TIMEOUT);
|
||||
#else
|
||||
@ -2845,11 +2847,11 @@ GCHelperThread::waitBackgroundSweepEnd()
|
||||
#endif /* JS_THREADSAFE */
|
||||
}
|
||||
|
||||
/* Must be called with the GC lock taken. */
|
||||
void
|
||||
GCHelperThread::waitBackgroundSweepOrAllocEnd()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
AutoLockGC lock(rt);
|
||||
if (state == ALLOCATING)
|
||||
state = CANCEL_ALLOCATION;
|
||||
while (state == SWEEPING || state == CANCEL_ALLOCATION)
|
||||
@ -2944,12 +2946,15 @@ GCHelperThread::doSweep()
|
||||
static bool
|
||||
ReleaseObservedTypes(JSRuntime *rt)
|
||||
{
|
||||
bool releaseTypes = false;
|
||||
bool releaseTypes = rt->gcZeal() != 0;
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
int64_t now = PRMJ_Now();
|
||||
if (rt->gcZeal() || now >= rt->gcJitReleaseTime) {
|
||||
if (now >= rt->gcJitReleaseTime)
|
||||
releaseTypes = true;
|
||||
if (releaseTypes)
|
||||
rt->gcJitReleaseTime = now + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return releaseTypes;
|
||||
}
|
||||
@ -3028,7 +3033,7 @@ ShouldPreserveJITCode(JSCompartment *c, int64_t currentTime)
|
||||
}
|
||||
|
||||
static void
|
||||
BeginMarkPhase(JSRuntime *rt)
|
||||
BeginMarkPhase(JSRuntime *rt, bool isIncremental)
|
||||
{
|
||||
int64_t currentTime = PRMJ_Now();
|
||||
|
||||
@ -3045,7 +3050,7 @@ BeginMarkPhase(JSRuntime *rt)
|
||||
JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
|
||||
|
||||
/* For non-incremental GC the following sweep discards the jit code. */
|
||||
if (rt->gcIncrementalState != NO_INCREMENTAL) {
|
||||
if (isIncremental) {
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DISCARD_CODE);
|
||||
c->discardJitCode(rt->defaultFreeOp());
|
||||
@ -3127,7 +3132,7 @@ ValidateIncrementalMarking(JSRuntime *rt);
|
||||
#endif
|
||||
|
||||
static void
|
||||
EndMarkPhase(JSRuntime *rt)
|
||||
EndMarkPhase(JSRuntime *rt, bool isIncremental)
|
||||
{
|
||||
{
|
||||
gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK);
|
||||
@ -3138,7 +3143,7 @@ EndMarkPhase(JSRuntime *rt)
|
||||
JS_ASSERT(rt->gcMarker.isDrained());
|
||||
|
||||
#ifdef DEBUG
|
||||
if (rt->gcIncrementalState != NO_INCREMENTAL)
|
||||
if (isIncremental)
|
||||
ValidateIncrementalMarking(rt);
|
||||
#endif
|
||||
|
||||
@ -3214,7 +3219,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
|
||||
|
||||
/* Re-do all the marking, but non-incrementally. */
|
||||
js::gc::State state = rt->gcIncrementalState;
|
||||
rt->gcIncrementalState = NO_INCREMENTAL;
|
||||
rt->gcIncrementalState = MARK_ROOTS;
|
||||
|
||||
/* As we're re-doing marking, we need to reset the weak map list. */
|
||||
WeakMapBase::resetWeakMapList(rt);
|
||||
@ -3228,6 +3233,7 @@ ValidateIncrementalMarking(JSRuntime *rt)
|
||||
MarkRuntime(gcmarker, true);
|
||||
|
||||
SliceBudget budget;
|
||||
rt->gcIncrementalState = MARK;
|
||||
rt->gcMarker.drainMarkStack(budget);
|
||||
MarkGrayAndWeak(rt);
|
||||
|
||||
@ -3472,7 +3478,10 @@ AutoGCSession::~AutoGCSession()
|
||||
for (GCCompartmentsIter c(runtime); !c.done(); c.next())
|
||||
c->setCollecting(false);
|
||||
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
runtime->gcNextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN;
|
||||
#endif
|
||||
|
||||
runtime->gcChunkAllocationSinceLastGC = false;
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
@ -3581,13 +3590,18 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, boo
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isIncremental = rt->gcIncrementalState != NO_INCREMENTAL ||
|
||||
budget != SliceBudget::Unlimited ||
|
||||
zeal == ZealIncrementalRootsThenFinish ||
|
||||
zeal == ZealIncrementalMarkAllThenFinish;
|
||||
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL) {
|
||||
rt->gcIncrementalState = MARK_ROOTS;
|
||||
rt->gcLastMarkSlice = false;
|
||||
}
|
||||
|
||||
if (rt->gcIncrementalState == MARK_ROOTS) {
|
||||
BeginMarkPhase(rt);
|
||||
BeginMarkPhase(rt, isIncremental);
|
||||
rt->gcIncrementalState = MARK;
|
||||
|
||||
if (zeal == ZealIncrementalRootsThenFinish)
|
||||
@ -3625,7 +3639,7 @@ IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, boo
|
||||
{
|
||||
rt->gcLastMarkSlice = true;
|
||||
} else {
|
||||
EndMarkPhase(rt);
|
||||
EndMarkPhase(rt, isIncremental);
|
||||
rt->gcIncrementalState = NO_INCREMENTAL;
|
||||
*shouldSweep = true;
|
||||
}
|
||||
@ -3738,7 +3752,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
|
||||
if (rt->inOOMReport)
|
||||
return;
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoGCSession gcsession(rt);
|
||||
|
||||
/*
|
||||
@ -3754,8 +3767,6 @@ GCCycle(JSRuntime *rt, bool incremental, int64_t budget, JSGCInvocationKind gcki
|
||||
|
||||
bool startBackgroundSweep = false;
|
||||
{
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
if (!incremental) {
|
||||
/* If non-incremental GC was requested, reset incremental GC. */
|
||||
ResetIncrementalGC(rt, "requested");
|
||||
@ -3962,11 +3973,9 @@ TraceRuntime(JSTracer *trc)
|
||||
{
|
||||
JSRuntime *rt = trc->runtime;
|
||||
if (!rt->gcRunning) {
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
RecordNativeStackTopForGC(rt);
|
||||
@ -4022,10 +4031,8 @@ IterateCompartmentsArenasCells(JSRuntime *rt, void *data,
|
||||
{
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
@ -4047,10 +4054,8 @@ IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
|
||||
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
|
||||
chunkCallback(rt, data, r.front());
|
||||
@ -4063,10 +4068,8 @@ IterateCells(JSRuntime *rt, JSCompartment *compartment, AllocKind thingKind,
|
||||
/* :XXX: Any way to common this preamble with IterateCompartmentsArenasCells? */
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
|
||||
@ -4091,10 +4094,8 @@ IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, vo
|
||||
JSRuntime *rt = compartment->rt;
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
|
||||
@ -4453,7 +4454,6 @@ StartVerifyBarriers(JSRuntime *rt)
|
||||
if (rt->gcVerifyData || rt->gcIncrementalState != NO_INCREMENTAL)
|
||||
return;
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
|
||||
if (!IsIncrementalGCSafe(rt))
|
||||
@ -4461,8 +4461,6 @@ StartVerifyBarriers(JSRuntime *rt)
|
||||
|
||||
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
RecordNativeStackTopForGC(rt);
|
||||
|
||||
@ -4584,13 +4582,10 @@ AssertMarkedOrAllocated(const EdgeValue &edge)
|
||||
static void
|
||||
EndVerifyBarriers(JSRuntime *rt)
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
|
||||
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
AutoCopyFreeListToArenas copy(rt);
|
||||
RecordNativeStackTopForGC(rt);
|
||||
|
||||
@ -4805,10 +4800,8 @@ JS_IterateCompartments(JSRuntime *rt, void *data,
|
||||
{
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
|
||||
AutoLockGC lock(rt);
|
||||
AutoHeapSession session(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
(*compartmentCallback)(rt, data, c);
|
||||
|
@ -1477,18 +1477,11 @@ proxy_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
JSObject *referent = &GetProxyPrivate(obj).toObject();
|
||||
if (referent->compartment() != obj->compartment()) {
|
||||
/*
|
||||
* Assert that this proxy is tracked in the wrapper map. Normally,
|
||||
* the wrapped object will be the key in the wrapper map. However,
|
||||
* sometimes when wrapping Location objects, the wrapped object is
|
||||
* not the key. In that case, we unwrap to find the key.
|
||||
* Assert that this proxy is tracked in the wrapper map. We maintain
|
||||
* the invariant that the wrapped object is the key in the wrapper map.
|
||||
*/
|
||||
Value key = ObjectValue(*referent);
|
||||
WrapperMap::Ptr p = obj->compartment()->crossCompartmentWrappers.lookup(key);
|
||||
if (!p) {
|
||||
key = ObjectValue(*UnwrapObject(referent));
|
||||
p = obj->compartment()->crossCompartmentWrappers.lookup(key);
|
||||
JS_ASSERT(p.found());
|
||||
}
|
||||
JS_ASSERT(p->value.get() == ObjectValue(*obj));
|
||||
}
|
||||
}
|
||||
|
@ -1120,3 +1120,114 @@ js::NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj,
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Given a cross-compartment wrapper |wobj|, update it to point to
|
||||
// |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
|
||||
// useful even if wrapper already points to newTarget.
|
||||
bool
|
||||
js::RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget)
|
||||
{
|
||||
JS_ASSERT(IsCrossCompartmentWrapper(wobj));
|
||||
JSObject *origTarget = Wrapper::wrappedObject(wobj);
|
||||
JS_ASSERT(origTarget);
|
||||
Value origv = ObjectValue(*origTarget);
|
||||
JSCompartment *wcompartment = wobj->compartment();
|
||||
WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
|
||||
|
||||
// When we remove origv from the wrapper map, its wrapper, wobj, must
|
||||
// immediately cease to be a cross-compartment wrapper. Neuter it.
|
||||
JS_ASSERT(pmap.lookup(origv));
|
||||
pmap.remove(origv);
|
||||
NukeCrossCompartmentWrapper(wobj);
|
||||
|
||||
// First, we wrap it in the new compartment. This will return
|
||||
// a new wrapper.
|
||||
AutoCompartment ac(cx, wobj);
|
||||
JSObject *tobj = newTarget;
|
||||
if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
|
||||
return false;
|
||||
|
||||
// Now, because we need to maintain object identity, we do a
|
||||
// brain transplant on the old object. At the same time, we
|
||||
// update the entry in the compartment's wrapper map to point
|
||||
// to the old wrapper.
|
||||
JS_ASSERT(tobj != wobj);
|
||||
if (!wobj->swap(cx, tobj))
|
||||
return false;
|
||||
pmap.put(ObjectValue(*newTarget), ObjectValue(*wobj));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remap all cross-compartment wrappers pointing to |oldTarget| to point to
|
||||
// |newTarget|. All wrappers are recomputed.
|
||||
bool
|
||||
js::RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
|
||||
JSObject *newTarget)
|
||||
{
|
||||
Value origv = ObjectValue(*oldTarget);
|
||||
Value targetv = ObjectValue(*newTarget);
|
||||
|
||||
AutoValueVector toTransplant(cx);
|
||||
if (!toTransplant.reserve(cx->runtime->compartments.length()))
|
||||
return false;
|
||||
|
||||
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
|
||||
WrapperMap &pmap = c->crossCompartmentWrappers;
|
||||
if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
|
||||
// We found a wrapper. Remember and root it.
|
||||
toTransplant.infallibleAppend(wp->value);
|
||||
}
|
||||
}
|
||||
|
||||
for (Value *begin = toTransplant.begin(), *end = toTransplant.end();
|
||||
begin != end; ++begin)
|
||||
{
|
||||
if (!RemapWrapper(cx, &begin->toObject(), newTarget))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
|
||||
const CompartmentFilter &targetFilter)
|
||||
{
|
||||
AutoValueVector toRecompute(cx);
|
||||
|
||||
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
|
||||
// Filter by source compartment.
|
||||
if (!sourceFilter.match(c))
|
||||
continue;
|
||||
|
||||
// Iterate over the wrappers, filtering appropriately.
|
||||
WrapperMap &pmap = c->crossCompartmentWrappers;
|
||||
for (WrapperMap::Enum e(pmap); !e.empty(); e.popFront()) {
|
||||
// Filter out non-objects.
|
||||
const CrossCompartmentKey &k = e.front().key;
|
||||
if (k.kind != CrossCompartmentKey::ObjectWrapper)
|
||||
continue;
|
||||
|
||||
// Filter by target compartment.
|
||||
Value wrapper = e.front().value.get();
|
||||
if (!targetFilter.match(k.wrapped->compartment()))
|
||||
continue;
|
||||
|
||||
// Add it to the list.
|
||||
if (!toRecompute.append(wrapper))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Recompute all the wrappers in the list.
|
||||
for (Value *begin = toRecompute.begin(), *end = toRecompute.end(); begin != end; ++begin)
|
||||
{
|
||||
JSObject *wrapper = &begin->toObject();
|
||||
JSObject *wrapped = Wrapper::wrappedObject(wrapper);
|
||||
if (!RemapWrapper(cx, wrapper, wrapped))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -334,6 +334,50 @@ IsCrossCompartmentWrapper(const JSObject *obj);
|
||||
void
|
||||
NukeCrossCompartmentWrapper(JSObject *wrapper);
|
||||
|
||||
bool
|
||||
RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget);
|
||||
|
||||
bool
|
||||
RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
|
||||
JSObject *newTarget);
|
||||
|
||||
// API to recompute all cross-compartment wrappers whose source and target
|
||||
// match the given filters.
|
||||
//
|
||||
// These filters are designed to be ephemeral stack classes, and thus don't
|
||||
// do any rooting or holding of their members.
|
||||
struct CompartmentFilter {
|
||||
virtual bool match(JSCompartment *c) const = 0;
|
||||
};
|
||||
|
||||
struct AllCompartments : public CompartmentFilter {
|
||||
virtual bool match(JSCompartment *c) const { return true; };
|
||||
};
|
||||
|
||||
struct ContentCompartmentsOnly : public CompartmentFilter {
|
||||
virtual bool match(JSCompartment *c) const {
|
||||
return !IsSystemCompartment(c);
|
||||
};
|
||||
};
|
||||
|
||||
struct SingleCompartment : public CompartmentFilter {
|
||||
JSCompartment *ours;
|
||||
SingleCompartment(JSCompartment *c) : ours(c) {};
|
||||
virtual bool match(JSCompartment *c) const { return c == ours; };
|
||||
};
|
||||
|
||||
struct CompartmentsWithPrincipals : public CompartmentFilter {
|
||||
JSPrincipals *principals;
|
||||
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {};
|
||||
virtual bool match(JSCompartment *c) const {
|
||||
return JS_GetCompartmentPrincipals(c) == principals;
|
||||
};
|
||||
};
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
|
||||
const CompartmentFilter &targetFilter);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include "nsJSON.h"
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/OSFileConstants.h"
|
||||
|
||||
using mozilla::dom::indexedDB::IndexedDatabaseManager;
|
||||
using mozilla::dom::DOMRequestService;
|
||||
@ -618,6 +619,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsSystemPrincipal,
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNullPrincipal, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStructuredCloneContainer)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(OSFileConstantsService)
|
||||
|
||||
static nsresult
|
||||
Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
@ -771,6 +774,7 @@ NS_DEFINE_NAMED_CID(SMS_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(SMS_DATABASE_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(SMS_REQUEST_MANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(OSFILECONSTANTSSERVICE_CID);
|
||||
|
||||
static nsresult
|
||||
CreateWindowCommandTableConstructor(nsISupports *aOuter,
|
||||
@ -1038,6 +1042,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
||||
{ &kSMS_DATABASE_SERVICE_CID, false, NULL, nsISmsDatabaseServiceConstructor },
|
||||
{ &kSMS_REQUEST_MANAGER_CID, false, NULL, SmsRequestManagerConstructor },
|
||||
{ &kNS_POWERMANAGERSERVICE_CID, false, NULL, nsIPowerManagerServiceConstructor },
|
||||
{ &kOSFILECONSTANTSSERVICE_CID, true, NULL, OSFileConstantsServiceConstructor },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -1170,6 +1175,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
||||
{ SMS_DATABASE_SERVICE_CONTRACTID, &kSMS_DATABASE_SERVICE_CID },
|
||||
{ SMS_REQUEST_MANAGER_CONTRACTID, &kSMS_REQUEST_MANAGER_CID },
|
||||
{ POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID },
|
||||
{ OSFILECONSTANTSSERVICE_CONTRACTID, &kOSFILECONSTANTSSERVICE_CID },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -355,6 +355,10 @@ TelemetryPing.prototype = {
|
||||
if (this._addons)
|
||||
ret.addons = this._addons;
|
||||
|
||||
let flashVersion = this.getFlashVersion();
|
||||
if (flashVersion)
|
||||
ret.flashVersion = flashVersion;
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
@ -734,6 +738,18 @@ TelemetryPing.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
getFlashVersion: function getFlashVersion() {
|
||||
let host = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let tags = host.getPluginTags();
|
||||
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
if (tags[i].name == "Shockwave Flash")
|
||||
return tags[i].version;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove observers to avoid leaks
|
||||
*/
|
||||
|
@ -19,6 +19,7 @@ const IGNORE_HISTOGRAM_TO_CLONE = "MEMORY_HEAP_ALLOCATED";
|
||||
const IGNORE_CLONED_HISTOGRAM = "test::ignore_me_also";
|
||||
const ADDON_NAME = "Telemetry test addon";
|
||||
const ADDON_HISTOGRAM = "addon-histogram";
|
||||
const FLASH_VERSION = "1.1.1.1";
|
||||
|
||||
const BinaryInputStream = Components.Constructor(
|
||||
"@mozilla.org/binaryinputstream;1",
|
||||
@ -125,7 +126,8 @@ function checkPayloadInfo(payload, reason) {
|
||||
appVersion: "1",
|
||||
appName: "XPCShell",
|
||||
appBuildID: "2007010101",
|
||||
platformBuildID: "2007010101"
|
||||
platformBuildID: "2007010101",
|
||||
flashVersion: FLASH_VERSION
|
||||
};
|
||||
|
||||
for (let f in expected_info) {
|
||||
@ -326,6 +328,40 @@ function dummyTheme(id) {
|
||||
};
|
||||
}
|
||||
|
||||
// A fake plugin host for testing flash version telemetry
|
||||
var PluginHost = {
|
||||
getPluginTags: function(countRef) {
|
||||
let plugins = [{name: "Shockwave Flash", version: FLASH_VERSION}];
|
||||
countRef.value = plugins.length;
|
||||
return plugins;
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsIPluginHost)
|
||||
|| iid.equals(Ci.nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
var PluginHostFactory = {
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return PluginHost.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
const PLUGINHOST_CONTRACTID = "@mozilla.org/plugin/host;1";
|
||||
const PLUGINHOST_CID = Components.ID("{2329e6ea-1f15-4cbe-9ded-6e98e842de0e}");
|
||||
|
||||
function registerFakePluginHost() {
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(PLUGINHOST_CID, "Fake Plugin Host",
|
||||
PLUGINHOST_CONTRACTID, PluginHostFactory);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
try {
|
||||
var gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfoDebug);
|
||||
@ -346,10 +382,13 @@ function run_test() {
|
||||
gInternalManager.observe(null, "addons-startup", null);
|
||||
LightweightThemeManager.currentTheme = dummyTheme("1234");
|
||||
|
||||
// fake plugin host for consistent flash version data
|
||||
registerFakePluginHost();
|
||||
|
||||
Services.obs.addObserver(nonexistentServerObserver, "telemetry-test-xhr-complete", false);
|
||||
telemetry_ping();
|
||||
// spin the event loop
|
||||
do_test_pending();
|
||||
// ensure that test runs to completion
|
||||
do_register_cleanup(function () do_check_true(gFinished));
|
||||
}
|
||||
}
|
||||
|
@ -480,14 +480,16 @@ nsWindow::GetLayerManager(PLayersChild* aShadowManager,
|
||||
if (mLayerManager)
|
||||
return mLayerManager;
|
||||
|
||||
// Set mUseAcceleratedRendering here to make it consistent with
|
||||
// nsBaseWidget::GetLayerManager
|
||||
// Set mUseAcceleratedRendering here to make it consistent with
|
||||
// nsBaseWidget::GetLayerManager
|
||||
mUseAcceleratedRendering = GetShouldAccelerate();
|
||||
if (!mUseAcceleratedRendering) {
|
||||
sFramebufferOpen = Framebuffer::Open();
|
||||
if (!sFramebufferOpen) {
|
||||
LOG("Failed to mmap fb(?!?), aborting ...");
|
||||
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
|
||||
sFramebufferOpen = Framebuffer::Open();
|
||||
if (!sFramebufferOpen) {
|
||||
LOG("Failed to mmap fb(?!?), aborting ...");
|
||||
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,7 +507,9 @@ nsWindow::GetLayerManager(PLayersChild* aShadowManager,
|
||||
}
|
||||
|
||||
DebugOnly<nsIntRect> fbBounds = gScreenBounds;
|
||||
sGLContext = GLContextProvider::CreateForWindow(this);
|
||||
if (!sGLContext) {
|
||||
sGLContext = GLContextProvider::CreateForWindow(this);
|
||||
}
|
||||
MOZ_ASSERT(fbBounds.value == gScreenBounds);
|
||||
if (sGLContext) {
|
||||
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
||||
|
@ -26,12 +26,11 @@
|
||||
#include "nsIModule.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
||||
// class definition headers
|
||||
#include "nsWindow.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsAppShellSingleton.h"
|
||||
#include "nsBidiKeyboard.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsDragService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsFilePicker.h"
|
||||
|
@ -22,6 +22,7 @@
|
||||
* - Window Message Handlers
|
||||
* - Drag & Drop - Target methods
|
||||
* - Keyboard Handlers
|
||||
* - IME
|
||||
* - Event Dispatch
|
||||
*
|
||||
*/
|
||||
@ -42,11 +43,10 @@
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "wdgtos2rc.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include <os2im.h>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//=============================================================================
|
||||
// Macros
|
||||
//=============================================================================
|
||||
@ -163,9 +163,16 @@ static PRUint32 sDragStatus = 0;
|
||||
#ifdef DEBUG_FOCUS
|
||||
int currentWindowIdentifier = 0;
|
||||
#endif
|
||||
// IME stuffs
|
||||
static HMODULE sIm32Mod = NULLHANDLE;
|
||||
static APIRET (APIENTRY *spfnImGetInstance)(HWND, PHIMI);
|
||||
static APIRET (APIENTRY *spfnImReleaseInstance)(HWND, HIMI);
|
||||
static APIRET (APIENTRY *spfnImGetConversionString)(HIMI, ULONG, PVOID,
|
||||
PULONG);
|
||||
static APIRET (APIENTRY *spfnImGetResultString)(HIMI, ULONG, PVOID, PULONG);
|
||||
static APIRET (APIENTRY *spfnImRequestIME)(HIMI, ULONG, ULONG, ULONG);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static PRUint32 WMChar2KeyCode(MPARAM mp1, MPARAM mp2);
|
||||
|
||||
//=============================================================================
|
||||
@ -189,7 +196,7 @@ nsWindow::nsWindow() : nsBaseWidget()
|
||||
mClipWnd = 0;
|
||||
mCssCursorHPtr = 0;
|
||||
mThebesSurface = 0;
|
||||
|
||||
mIsComposing = false;
|
||||
if (!gOS2Flags) {
|
||||
InitGlobals();
|
||||
}
|
||||
@ -274,8 +281,48 @@ void nsWindow::InitGlobals()
|
||||
if (Preferences::GetBool("os2.trackpoint", false)) {
|
||||
gOS2Flags |= kIsTrackPoint;
|
||||
}
|
||||
|
||||
InitIME();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Determine whether to use IME
|
||||
static
|
||||
void InitIME()
|
||||
{
|
||||
if (!getenv("MOZ_IME_OVERTHESPOT")) {
|
||||
CHAR szName[CCHMAXPATH];
|
||||
ULONG rc;
|
||||
|
||||
rc = DosLoadModule(szName, sizeof(szName), "os2im", &sIm32Mod);
|
||||
|
||||
if (!rc)
|
||||
rc = DosQueryProcAddr(sIm32Mod, 104, NULL,
|
||||
(PFN *)&spfnImGetInstance);
|
||||
|
||||
if (!rc)
|
||||
rc = DosQueryProcAddr(sIm32Mod, 106, NULL,
|
||||
(PFN *)&spfnImReleaseInstance);
|
||||
|
||||
if (!rc)
|
||||
rc = DosQueryProcAddr(sIm32Mod, 118, NULL,
|
||||
(PFN *)&spfnImGetConversionString);
|
||||
|
||||
if (!rc)
|
||||
rc = DosQueryProcAddr(sIm32Mod, 122, NULL,
|
||||
(PFN *)&spfnImGetResultString);
|
||||
|
||||
if (!rc)
|
||||
rc = DosQueryProcAddr(sIm32Mod, 131, NULL,
|
||||
(PFN *)&spfnImRequestIME);
|
||||
|
||||
if (rc) {
|
||||
DosFreeModule(sIm32Mod);
|
||||
|
||||
sIm32Mod = NULLHANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Release Module-level variables.
|
||||
|
||||
@ -1841,6 +1888,10 @@ MRESULT nsWindow::ProcessMessage(ULONG msg, MPARAM mp1, MPARAM mp2)
|
||||
case WM_QUERYCONVERTPOS:
|
||||
isDone = OnQueryConvertPos(mp1, mresult);
|
||||
break;
|
||||
|
||||
case WM_IMEREQUEST:
|
||||
isDone = OnImeRequest(mp1, mp2);
|
||||
break;
|
||||
}
|
||||
// If an event handler signalled that we should consume the event,
|
||||
// return. Otherwise, pass it on to the default wndproc.
|
||||
@ -2416,6 +2467,156 @@ bool nsWindow::OnQueryConvertPos(MPARAM mp1, MRESULT& mresult)
|
||||
|
||||
return true;
|
||||
}
|
||||
bool nsWindow::ImeResultString(HIMI himi)
|
||||
{
|
||||
PCHAR pBuf;
|
||||
ULONG ulBufLen;
|
||||
|
||||
// Get a buffer size
|
||||
ulBufLen = 0;
|
||||
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, NULL, &ulBufLen))
|
||||
return false;
|
||||
|
||||
pBuf = new CHAR[ulBufLen];
|
||||
if (!pBuf)
|
||||
return false;
|
||||
|
||||
if (spfnImGetResultString(himi, IMR_RESULT_RESULTSTRING, pBuf,
|
||||
&ulBufLen)) {
|
||||
delete pBuf;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mIsComposing) {
|
||||
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
|
||||
InitEvent(start);
|
||||
DispatchWindowEvent(&start);
|
||||
|
||||
mIsComposing = true;
|
||||
}
|
||||
|
||||
nsAutoChar16Buffer outBuf;
|
||||
PRInt32 outBufLen;
|
||||
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
|
||||
|
||||
delete pBuf;
|
||||
|
||||
nsTextEvent text(true, NS_TEXT_TEXT, this);
|
||||
InitEvent(text);
|
||||
text.theText = outBuf.Elements();
|
||||
DispatchWindowEvent(&text);
|
||||
|
||||
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
|
||||
InitEvent(end);
|
||||
end.data = text.theText;
|
||||
DispatchWindowEvent(&end);
|
||||
mIsComposing = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsWindow::ImeConversionString(HIMI himi)
|
||||
{
|
||||
PCHAR pBuf;
|
||||
ULONG ulBufLen;
|
||||
|
||||
// Get a buffer size
|
||||
ulBufLen = 0;
|
||||
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, NULL,
|
||||
&ulBufLen))
|
||||
return false;
|
||||
|
||||
pBuf = new CHAR[ulBufLen];
|
||||
if (!pBuf)
|
||||
return false;
|
||||
|
||||
if (spfnImGetConversionString(himi, IMR_CONV_CONVERSIONSTRING, pBuf,
|
||||
&ulBufLen)) {
|
||||
delete pBuf;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mIsComposing) {
|
||||
nsCompositionEvent start(true, NS_COMPOSITION_START, this);
|
||||
InitEvent(start);
|
||||
DispatchWindowEvent(&start);
|
||||
|
||||
mIsComposing = true;
|
||||
}
|
||||
|
||||
nsAutoChar16Buffer outBuf;
|
||||
PRInt32 outBufLen;
|
||||
MultiByteToWideChar(0, pBuf, ulBufLen, outBuf, outBufLen);
|
||||
|
||||
delete pBuf;
|
||||
|
||||
nsAutoTArray<nsTextRange, 4> textRanges;
|
||||
|
||||
// Is there a conversion string ?
|
||||
if (outBufLen) {
|
||||
nsTextRange newRange;
|
||||
newRange.mStartOffset = 0;
|
||||
newRange.mEndOffset = outBufLen;
|
||||
newRange.mRangeType = NS_TEXTRANGE_SELECTEDRAWTEXT;
|
||||
textRanges.AppendElement(newRange);
|
||||
|
||||
newRange.mStartOffset = outBufLen;
|
||||
newRange.mEndOffset = newRange.mStartOffset;
|
||||
newRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
|
||||
textRanges.AppendElement(newRange);
|
||||
}
|
||||
|
||||
nsTextEvent text(true, NS_TEXT_TEXT, this);
|
||||
InitEvent(text);
|
||||
text.theText = outBuf.Elements();
|
||||
text.rangeArray = textRanges.Elements();
|
||||
text.rangeCount = textRanges.Length();
|
||||
DispatchWindowEvent(&text);
|
||||
|
||||
if (outBufLen) {
|
||||
nsCompositionEvent update(true, NS_COMPOSITION_UPDATE, this);
|
||||
InitEvent(update);
|
||||
update.data = text.theText;
|
||||
DispatchWindowEvent(&update);
|
||||
} else { // IME conversion was canceled ?
|
||||
nsCompositionEvent end(true, NS_COMPOSITION_END, this);
|
||||
InitEvent(end);
|
||||
end.data = text.theText;
|
||||
DispatchWindowEvent(&end);
|
||||
|
||||
mIsComposing = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsWindow::OnImeRequest(MPARAM mp1, MPARAM mp2)
|
||||
{
|
||||
HIMI himi;
|
||||
bool rc;
|
||||
|
||||
if (!sIm32Mod)
|
||||
return false;
|
||||
|
||||
if (SHORT1FROMMP(mp1) != IMR_CONVRESULT)
|
||||
return false;
|
||||
|
||||
if (spfnImGetInstance(mWnd, &himi))
|
||||
return false;
|
||||
|
||||
if (LONGFROMMP(mp2) & IMR_RESULT_RESULTSTRING)
|
||||
rc = ImeResultString(himi);
|
||||
else if (LONGFROMMP(mp2) & IMR_CONV_CONVERSIONSTRING)
|
||||
rc = ImeConversionString(himi);
|
||||
else
|
||||
rc = true;
|
||||
|
||||
spfnImReleaseInstance(mWnd, himi);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Key handler. Specs for the various text messages are really confused;
|
||||
@ -2840,6 +3041,14 @@ bool nsWindow::DispatchMouseEvent(PRUint32 aEventType, MPARAM mp1, MPARAM mp2,
|
||||
? nsMouseEvent::eContextMenuKey
|
||||
: nsMouseEvent::eNormal);
|
||||
event.button = aButton;
|
||||
if (aEventType == NS_MOUSE_BUTTON_DOWN && mIsComposing) {
|
||||
// If IME is composing, let it complete.
|
||||
HIMI himi;
|
||||
|
||||
spfnImGetInstance(mWnd, &himi);
|
||||
spfnImRequestIME(himi, REQ_CONVERSIONSTRING, CNV_COMPLETE, 0);
|
||||
spfnImReleaseInstance(mWnd, himi);
|
||||
}
|
||||
|
||||
if (aEventType == NS_MOUSE_ENTER || aEventType == NS_MOUSE_EXIT) {
|
||||
// Ignore enter/leave msgs forwarded from the frame to FID_CLIENT
|
||||
|
@ -55,10 +55,10 @@
|
||||
#define INCL_NLS
|
||||
#define INCL_GPI
|
||||
#include <os2.h>
|
||||
#include <os2im.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Items that may not be in the OS/2 Toolkit headers
|
||||
|
||||
// For WM_MOUSEENTER/LEAVE, mp2 is the other window.
|
||||
#ifndef WM_MOUSEENTER
|
||||
#define WM_MOUSEENTER 0x041E
|
||||
@ -231,6 +231,9 @@ protected:
|
||||
bool ReleaseIfDragHPS(HPS aHps);
|
||||
bool OnTranslateAccelerator(PQMSG pQmsg);
|
||||
bool OnQueryConvertPos(MPARAM mp1, MRESULT& mresult);
|
||||
bool ImeResultString(HIMI himi);
|
||||
bool ImeConversionString(HIMI himi);
|
||||
bool OnImeRequest(MPARAM mp1, MPARAM mp2);
|
||||
bool DispatchKeyEvent(MPARAM mp1, MPARAM mp2);
|
||||
void InitEvent(nsGUIEvent& event, nsIntPoint* pt = 0);
|
||||
bool DispatchWindowEvent(nsGUIEvent* event);
|
||||
@ -267,6 +270,7 @@ protected:
|
||||
HPOINTER mCssCursorHPtr; // created by SetCursor(imgIContainer*)
|
||||
nsCOMPtr<imgIContainer> mCssCursorImg;// saved by SetCursor(imgIContainer*)
|
||||
nsRefPtr<gfxOS2Surface> mThebesSurface;
|
||||
bool mIsComposing;
|
||||
#ifdef DEBUG_FOCUS
|
||||
int mWindowIdentifier; // a serial number for each new window
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user