author | Hub Figuière <hfiguiere@mozilla.com> |
Tue, 10 Apr 2012 12:41:47 -0700 | |
changeset 91343 | 1df10e8b5ce2d854b1dae34543bdfd4ec09e815d |
parent 91342 | 57d8b862905b34ecb1011cc20741c44a31587821 (current diff) |
parent 91341 | 24e84699e39548d1462b19deb57288d00bace05c (diff) |
child 91344 | c3276660b556c28e271c847cefdb2e5b9eec7971 |
push id | 8164 |
push user | hfiguiere@mozilla.com |
push date | Tue, 10 Apr 2012 19:42:18 +0000 |
treeherder | mozilla-inbound@1df10e8b5ce2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bustage |
milestone | 14.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/build/mobile/robocop/FennecMochitestAssert.java.in +++ b/build/mobile/robocop/FennecMochitestAssert.java.in @@ -58,22 +58,22 @@ public class FennecMochitestAssert imple // Measure the time it takes to run test case private long mStartTime = 0; public FennecMochitestAssert() { } /** Write information to a logfile and logcat */ public void dumpLog(String message) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message); } /** Write information to a logfile and logcat */ public void dumpLog(String message, Throwable t) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message, t); } /** Set the filename used for dumpLog. */ public void setLogFile(String filename) { FennecNativeDriver.setLogFile(filename); String message; if (!mLogStarted) {
--- a/build/mobile/robocop/FennecNativeActions.java.in +++ b/build/mobile/robocop/FennecNativeActions.java.in @@ -58,16 +58,18 @@ import android.os.SystemClock; import android.view.View; import android.view.KeyEvent; import android.util.Log; import org.json.*; import com.jayway.android.robotium.solo.Solo; +import static @ANDROID_PACKAGE_NAME@.FennecNativeDriver.LogLevel; + public class FennecNativeActions implements Actions { private Solo mSolo; private Instrumentation mInstr; private Activity mGeckoApp; // Objects for reflexive access of fennec classes. private ClassLoader mClassLoader; private Class mGel; @@ -99,25 +101,25 @@ public class FennecNativeActions impleme parameters = new Class[1]; parameters[0] = mGe; mSendGE = mGas.getMethod("sendEventToGecko", parameters); mGetLayerClient = activity.getClass().getMethod("getLayerClient"); Class gslc = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient"); mDrawListener = mClassLoader.loadClass("org.mozilla.gecko.gfx.GeckoLayerClient$DrawListener"); mSetDrawListener = gslc.getDeclaredMethod("setDrawListener", mDrawListener); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } + } catch (ClassNotFoundException e) { + FennecNativeDriver.log(LogLevel.ERROR, e); + } catch (SecurityException e) { + FennecNativeDriver.log(LogLevel.ERROR, e); + } catch (NoSuchMethodException e) { + FennecNativeDriver.log(LogLevel.ERROR, e); + } catch (IllegalArgumentException e) { + FennecNativeDriver.log(LogLevel.ERROR, e); + } } class wakeInvocationHandler implements InvocationHandler { private final GeckoEventExpecter mEventExpecter; public wakeInvocationHandler(GeckoEventExpecter expecter) { mEventExpecter = expecter; } @@ -132,17 +134,17 @@ public class FennecNativeActions impleme return this == args[0]; } if(methodName.equals("clone")) { return this; } if(methodName.equals("hashCode")) { return 314; } - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "Waking up on "+methodName); mEventExpecter.notifyOfEvent(); return null; } } class GeckoEventExpecter implements EventExpecter { private final String mGeckoEvent; @@ -154,80 +156,80 @@ public class FennecNativeActions impleme mRegistrationParams = registrationParams; } public synchronized void blockForEvent() { while (! mEventReceived) { try { this.wait(); } catch (InterruptedException ie) { - ie.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, ie); break; } } - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "unblocked on expecter for " + mGeckoEvent); } public synchronized boolean eventReceived() { return mEventReceived; } void notifyOfEvent() { try { mUnregisterGEL.invoke(null, mRegistrationParams); } catch (IllegalAccessException e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "received event " + mGeckoEvent); synchronized (this) { mEventReceived = true; this.notifyAll(); } } } public EventExpecter expectGeckoEvent(String geckoEvent) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "waiting for "+geckoEvent); try { Class [] interfaces = new Class[1]; interfaces[0] = mGel; Object[] finalParams = new Object[2]; finalParams[0] = geckoEvent; GeckoEventExpecter expecter = new GeckoEventExpecter(geckoEvent, finalParams); wakeInvocationHandler wIH = new wakeInvocationHandler(expecter); Object proxy = Proxy.newProxyInstance(mClassLoader, interfaces, wIH); finalParams[1] = proxy; mRegisterGEL.invoke(null, finalParams); return expecter; } catch (IllegalAccessException e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } return null; } class DrawListenerProxy implements InvocationHandler { private final PaintExpecter mPaintExpecter; DrawListenerProxy(PaintExpecter paintExpecter) { mPaintExpecter = paintExpecter; } public Object invoke(Object proxy, Method method, Object[] args) { String methodName = method.getName(); if ("drawFinished".equals(methodName)) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_DEBUG, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "Received drawFinished notification"); mPaintExpecter.notifyOfEvent(); } else if ("toString".equals(methodName)) { return "DrawListenerProxy"; } else if ("equals".equals(methodName)) { return false; } else if ("hashCode".equals(methodName)) { return 0; @@ -252,74 +254,74 @@ public class FennecNativeActions impleme } } public synchronized void blockForEvent() { while (!mPaintDone) { try { this.wait(); } catch (InterruptedException ie) { - ie.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, ie); break; } } try { mSetDrawListener.invoke(mLayerClient, (Object)null); } catch (Exception e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } } public synchronized boolean eventReceived() { return mPaintDone; } public synchronized void blockUntilClear(long millis) { if (millis <= 0) { throw new IllegalArgumentException("millis must be > 0"); } // wait for at least one event while (!mPaintDone) { try { this.wait(); } catch (InterruptedException ie) { - ie.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, ie); break; } } // now wait for a period of millis where we don't get an event long startTime = SystemClock.uptimeMillis(); while (true) { try { this.wait(millis); } catch (InterruptedException ie) { - ie.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, ie); break; } long endTime = SystemClock.uptimeMillis(); if (endTime - startTime >= millis) { // success break; } // we got a notify() before we could wait long enough, so we need to start over startTime = endTime; } try { mSetDrawListener.invoke(mLayerClient, (Object)null); } catch (Exception e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); } } } public RepeatedEventExpecter expectPaint() { try { return new PaintExpecter(); } catch (Exception e) { - e.printStackTrace(); + FennecNativeDriver.log(LogLevel.ERROR, e); return null; } } public void sendSpecialKey(SpecialKey button) { switch(button) { case DOWN: mInstr.sendCharacterSync(KeyEvent.KEYCODE_DPAD_DOWN);
--- a/build/mobile/robocop/FennecNativeDriver.java.in +++ b/build/mobile/robocop/FennecNativeDriver.java.in @@ -73,37 +73,37 @@ public class FennecNativeDriver implemen private static final int FRAME_TIME_THRESHOLD = 17; // allow 17ms per frame (~60fps) // Map of IDs to element names. private HashMap mLocators = null; private Activity mActivity; private Solo mSolo; private static String mLogFile = null; - private static LogLevel mLogLevel = LogLevel.LOG_LEVEL_INFO; + private static LogLevel mLogLevel = LogLevel.INFO; // Objects for reflexive access of fennec classes. private ClassLoader mClassLoader; private Class mGel; private Class mGe; private Class mGas; private Method mRegisterGEL; private Method mUnregisterGEL; private Method mSendGE; private Method _startFrameRecording; private Method _stopFrameRecording; private Method _startCheckerboardRecording; private Method _stopCheckerboardRecording; private Method _getPixels; public enum LogLevel { - LOG_LEVEL_DEBUG(1), - LOG_LEVEL_INFO(2), - LOG_LEVEL_WARN(3), - LOG_LEVEL_ERROR(4); + DEBUG(1), + INFO(2), + WARN(3), + ERROR(4); private int mValue; LogLevel(int value) { mValue = value; } public boolean isEnabled(LogLevel configuredLevel) { return mValue >= configuredLevel.getValue(); } @@ -137,25 +137,25 @@ public class FennecNativeDriver implemen Class gfx = mClassLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI"); _startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording"); _stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording"); _startCheckerboardRecording = gfx.getDeclaredMethod("startCheckerboardRecording"); _stopCheckerboardRecording = gfx.getDeclaredMethod("stopCheckerboardRecording"); Class layerView = mClassLoader.loadClass("org.mozilla.gecko.gfx.LayerView"); _getPixels = layerView.getDeclaredMethod("getPixels"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } + } catch (ClassNotFoundException e) { + log(LogLevel.ERROR, e); + } catch (SecurityException e) { + log(LogLevel.ERROR, e); + } catch (NoSuchMethodException e) { + log(LogLevel.ERROR, e); + } catch (IllegalArgumentException e) { + log(LogLevel.ERROR, e); + } } //Information on the location of the Gecko Frame. private boolean mGeckoInfo = false; private int mGeckoTop = 100; private int mGeckoLeft = 0; private int mGeckoHeight= 700; private int mGeckoWidth = 1024; @@ -213,19 +213,19 @@ public class FennecNativeDriver implemen throw new RoboCopException("Element does not exist in the list"); } public void startFrameRecording() { try { Object [] params = null; _startFrameRecording.invoke(null, params); } catch (IllegalAccessException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } } public int stopFrameRecording() { Class [] parameters = new Class[1]; parameters[0] = null; try { @@ -234,80 +234,80 @@ public class FennecNativeDriver implemen int numDelays = 0; for (int i = 1; i < frames.size(); i++) { if (frames.get(i) - frames.get(i-1) > FRAME_TIME_THRESHOLD) { numDelays++; } } return numDelays; } catch (IllegalAccessException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } return 0; } public void startCheckerboardRecording() { try { Object [] params = null; _startCheckerboardRecording.invoke(null, params); } catch (IllegalAccessException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } } public float stopCheckerboardRecording() { Class [] parameters = new Class[1]; parameters[0] = null; try { Object [] params = null; List<Float> checkerboard = (List<Float>)_stopCheckerboardRecording.invoke(null, params); float completeness = 0; for (float val : checkerboard) { completeness += (1.0f - val); } return completeness / (float)checkerboard.size(); } catch (IllegalAccessException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } return 0.0f; } private View getSurfaceView() { try { Class c = Class.forName("org.mozilla.gecko.gfx.LayerView"); for (View v : mSolo.getCurrentViews()) { if (c.isInstance(v)) { return v; } } } catch (ClassNotFoundException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } return null; } public PaintedSurface getPaintedSurface() { View view = getSurfaceView(); if (view == null) { return null; } IntBuffer pixelBuffer; try { pixelBuffer = (IntBuffer)_getPixels.invoke(view); } catch (Exception e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); return null; } // now we need to (1) flip the image, because GL likes to do things up-side-down, // and (2) rearrange the bits from AGBR-8888 to ARGB-8888. int w = view.getWidth(); int h = view.getHeight(); pixelBuffer.position(0); @@ -336,17 +336,17 @@ public class FennecNativeDriver implemen dos.close(); } // closing dos automatically closes bos if (fos != null) { fos.flush(); fos.close(); } } catch (IOException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); throw new RoboCopException("exception closing pixel writer on file: " + mapFile); } } return new PaintedSurface(mapFile, w, h); } public int mHeight=0; public int mScrollHeight=0; @@ -361,17 +361,17 @@ public class FennecNativeDriver implemen mScrollHeight = jo.getInt("y"); mHeight = jo.getInt("cheight"); // We don't want a height of 0. That means it's a bad response. if (mHeight > 0) { mPageHeight = jo.getInt("height"); } } catch( Throwable e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN, "WARNING: ScrollReceived, but read wrong!"); } return null; } } public int getScrollHeight() { return mScrollHeight; @@ -388,19 +388,19 @@ public class FennecNativeDriver implemen try { Class [] interfaces = new Class[1]; interfaces[0] = mGel; Object[] finalParams = new Object[2]; finalParams[0] = "robocop:scroll"; finalParams[1] = Proxy.newProxyInstance(mClassLoader, interfaces, new scrollHandler()); mRegisterGEL.invoke(null, finalParams); } catch (IllegalAccessException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } catch (InvocationTargetException e) { - e.printStackTrace(); + log(LogLevel.ERROR, e); } } /** * Takes a filename, loads the file, and returns a string version of the entire file. */ public static String getFile(String filename) @@ -411,18 +411,18 @@ public class FennecNativeDriver implemen try { br = new BufferedReader(new FileReader(filename)); String line; while ((line = br.readLine()) != null) { text.append(line); text.append('\n'); } - } catch(IOException e) { - e.printStackTrace(); + } catch (IOException e) { + log(LogLevel.ERROR, e); } finally { try { br.close(); } catch (IOException e) { } } return text.toString(); } @@ -488,19 +488,19 @@ public class FennecNativeDriver implemen } // PrintWriter doesn't throw IOE but sets an error flag instead, // so check for that if (pw.checkError()) { Log.e("Robocop", "exception with file writer on: " + mLogFile); } } - if (level == LogLevel.LOG_LEVEL_INFO) { + if (level == LogLevel.INFO) { Log.i("Robocop", message, t); - } else if (level == LogLevel.LOG_LEVEL_DEBUG) { + } else if (level == LogLevel.DEBUG) { Log.d("Robocop", message, t); - } else if (level == LogLevel.LOG_LEVEL_WARN) { + } else if (level == LogLevel.WARN) { Log.w("Robocop", message, t); - } else if (level == LogLevel.LOG_LEVEL_ERROR) { + } else if (level == LogLevel.ERROR) { Log.e("Robocop", message, t); } } }
--- a/build/mobile/robocop/FennecNativeElement.java.in +++ b/build/mobile/robocop/FennecNativeElement.java.in @@ -71,29 +71,29 @@ public class FennecNativeElement impleme public void click() { final SynchronousQueue syncQueue = new SynchronousQueue(); mActivity.runOnUiThread( new Runnable() { public void run() { View view = (View)mActivity.findViewById(mId); if(view != null) { if (!view.performClick()) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_WARN, + FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN, "Robocop called click on an element with no listener"); } } else { throw new RoboCopException("click: unable to find view "+mId); } syncQueue.offer(new Object()); } }); try { syncQueue.take(); } catch (InterruptedException e) { - e.printStackTrace(); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); } } private Object mText; public String getText() { final SynchronousQueue syncQueue = new SynchronousQueue(); mActivity.runOnUiThread( @@ -124,17 +124,17 @@ public class FennecNativeElement impleme syncQueue.offer(new Object()); } // end of run() method definition } // end of anonymous Runnable object instantiation ); try { // Wait for the UiThread code to finish running syncQueue.take(); } catch (InterruptedException e) { - e.printStackTrace(); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); } if (mText == null) { throw new RoboCopException("getText: Text is null for view "+mId); } return mText.toString(); } private boolean mDisplayed; @@ -150,14 +150,14 @@ public class FennecNativeElement impleme mDisplayed = true; } syncQueue.offer(new Object()); } }); try { syncQueue.take(); } catch (InterruptedException e) { - e.printStackTrace(); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); } return mDisplayed; } }
--- a/build/mobile/robocop/FennecTalosAssert.java.in +++ b/build/mobile/robocop/FennecTalosAssert.java.in @@ -41,22 +41,22 @@ package @ANDROID_PACKAGE_NAME@; public class FennecTalosAssert implements Assert { public FennecTalosAssert() { } /** * Write information to a logfile and logcat */ public void dumpLog(String message) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message); } /** Write information to a logfile and logcat */ public void dumpLog(String message, Throwable t) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message, t); } /** * Set the filename used for dumpLog. */ public void setLogFile(String filename) { FennecNativeDriver.setLogFile(filename); }
--- a/build/mobile/robocop/PaintedSurface.java.in +++ b/build/mobile/robocop/PaintedSurface.java.in @@ -24,19 +24,19 @@ public class PaintedSurface { try { File f = new File(filename); int pixelSize = (int)f.length(); FileInputStream pixelFile = new FileInputStream(filename); mPixelBuffer = pixelFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, pixelSize); } catch (java.io.FileNotFoundException e) { - e.printStackTrace(); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); } catch (java.io.IOException e) { - e.printStackTrace(); + FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); } } public final int getPixelAt(int x, int y) { if (mPixelBuffer == null) { throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer"); }
--- a/js/src/jsanalyze.cpp +++ b/js/src/jsanalyze.cpp @@ -1043,23 +1043,24 @@ ScriptAnalysis::addVariable(JSContext *c } inline void ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offset, LifetimeVariable **&saved, unsigned &savedCount) { if (!var.lifetime) { /* Make a point lifetime indicating the write. */ - if (!var.saved) - saved[savedCount++] = &var; - var.saved = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved); - if (!var.saved) { + Lifetime *lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved); + if (!lifetime) { setOOM(cx); return; } + if (!var.saved) + saved[savedCount++] = &var; + var.saved = lifetime; var.saved->write = true; var.savedEnd = 0; return; } JS_ASSERT_IF(!var.ensured, offset < var.lifetime->start); unsigned start = var.lifetime->start;
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2721,23 +2721,23 @@ TypeObject::getFromPrototypes(JSContext if (!proto) return; if (proto->getType(cx)->unknownProperties()) { types->addType(cx, Type::UnknownType()); return; } - TypeSet *protoTypes = proto->type()->getProperty(cx, id, false); + TypeSet *protoTypes = proto->getType(cx)->getProperty(cx, id, false); if (!protoTypes) return; protoTypes->addSubset(cx, types); - proto->type()->getFromPrototypes(cx, id, protoTypes); + proto->getType(cx)->getFromPrototypes(cx, id, protoTypes); } static inline void UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, const Shape *shape, bool force) { types->setOwnProperty(cx, false); if (!shape->writable()) types->setOwnProperty(cx, true); @@ -5305,18 +5305,20 @@ IgnorePushed(const jsbytecode *pc, unsig bool JSScript::makeTypes(JSContext *cx) { JS_ASSERT(!types); if (!cx->typeInferenceEnabled()) { types = (TypeScript *) cx->calloc_(sizeof(TypeScript)); - if (!types) + if (!types) { + js_ReportOutOfMemory(cx); return false; + } new(types) TypeScript(); return true; } AutoEnterTypeInference enter(cx); unsigned count = TypeScript::NumTypeSets(this); @@ -5515,26 +5517,34 @@ JSObject::splicePrototype(JSContext *cx, } return true; } void JSObject::makeLazyType(JSContext *cx) { - JS_ASSERT(cx->typeInferenceEnabled() && hasLazyType()); - AutoEnterTypeInference enter(cx); + JS_ASSERT(hasLazyType()); TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, JSProto_Object, getProto()); if (!type) { - cx->compartment->types.setPendingNukeTypes(cx); + if (cx->typeInferenceEnabled()) + cx->compartment->types.setPendingNukeTypes(cx); return; } + if (!cx->typeInferenceEnabled()) { + /* This can only happen if types were previously nuked. */ + type_ = type; + return; + } + + AutoEnterTypeInference enter(cx); + /* Fill in the type according to the state of this object. */ type->singleton = this; if (isFunction() && toFunction()->isInterpreted()) { type->interpretedFunction = toFunction(); JSScript *script = type->interpretedFunction->script(); if (script->uninlineable)
--- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -324,33 +324,35 @@ MarkIteratorUnknown(JSContext *cx) if (cx->typeInferenceEnabled()) MarkIteratorUnknownSlow(cx); } /* * Monitor a javascript call, either on entry to the interpreter or made * from within the interpreter. */ -inline void +inline bool TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing) { extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args, bool constructing); JSObject *callee = &args.callee(); if (callee->isFunction()) { JSFunction *fun = callee->toFunction(); if (fun->isInterpreted()) { JSScript *script = fun->script(); if (!script->ensureRanAnalysis(cx, fun->environment())) - return; + return false; if (cx->typeInferenceEnabled()) TypeMonitorCallSlow(cx, callee, args, constructing); } } + + return true; } inline bool TrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id) { if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties()) return false;
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -510,17 +510,18 @@ js::InvokeKernel(JSContext *cx, CallArgs } /* Invoke native functions. */ JSFunction *fun = callee.toFunction(); JS_ASSERT_IF(construct, !fun->isNativeConstructor()); if (fun->isNative()) return CallJSNative(cx, fun->native(), args); - TypeMonitorCall(cx, args, construct); + if (!TypeMonitorCall(cx, args, construct)) + return false; /* Get pointer to new frame/slots, prepare arguments. */ InvokeFrameGuard ifg; if (!cx->stack.pushInvokeFrame(cx, args, initial, &ifg)) return false; /* Now that the new frame is rooted, maybe create a call object. */ StackFrame *fp = ifg.fp(); @@ -2688,17 +2689,18 @@ BEGIN_CASE(JSOP_FUNCALL) Value *newsp = args.spAfterCall(); TypeScript::Monitor(cx, script, regs.pc, newsp[-1]); regs.sp = newsp; CHECK_INTERRUPT_HANDLER(); len = JSOP_CALL_LENGTH; DO_NEXT_OP(len); } - TypeMonitorCall(cx, args, construct); + if (!TypeMonitorCall(cx, args, construct)) + goto error; InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE; JSScript *newScript = fun->script(); if (newScript->compileAndGo && newScript->hasClearedGlobal()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE); goto error;
--- a/js/src/methodjit/BaseCompiler.h +++ b/js/src/methodjit/BaseCompiler.h @@ -133,19 +133,17 @@ class LinkerHelper : public JSC::LinkBuf #endif { } ~LinkerHelper() { JS_ASSERT(verifiedRange); } bool verifyRange(const JSC::JITCode &other) { -#ifdef DEBUG - verifiedRange = true; -#endif + markVerified(); #ifdef JS_CPU_X64 return VerifyRange(m_code, m_size, other.start(), other.size()); #else return true; #endif } bool verifyRange(JITChunk *chunk) { @@ -157,16 +155,17 @@ class LinkerHelper : public JSC::LinkBuf // The pool is incref'd after this call, so it's necessary to release() // on any failure. JSScript *script = cx->fp()->script(); JSC::ExecutableAllocator *allocator = script->compartment()->jaegerCompartment()->execAlloc(); allocator->setDestroyCallback(Probes::discardExecutableRegion); JSC::ExecutablePool *pool; m_code = executableAllocAndCopy(masm, allocator, &pool); if (!m_code) { + markVerified(); js_ReportOutOfMemory(cx); return NULL; } m_size = masm.size(); // must come after call to executableAllocAndCopy()! return pool; } JSC::CodeLocationLabel finalize(VMFrame &f) { @@ -181,16 +180,23 @@ class LinkerHelper : public JSC::LinkBuf if (!jump.isSet()) return; link(jump.get(), label); } size_t size() const { return m_size; } + + protected: + void markVerified() { +#ifdef DEBUG + verifiedRange = true; +#endif + } }; class NativeStubLinker : public LinkerHelper { public: #ifdef JS_CPU_X64 typedef JSC::MacroAssembler::DataLabelPtr FinalJump; #else
--- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -293,17 +293,18 @@ UncachedInlineCall(VMFrame &f, InitialFr JSFunction *newfun = args.callee().toFunction(); JSScript *newscript = newfun->script(); bool construct = InitialFrameFlagsAreConstructing(initial); bool newType = construct && cx->typeInferenceEnabled() && types::UseNewType(cx, f.script(), f.pc()); - types::TypeMonitorCall(cx, args, construct); + if (!types::TypeMonitorCall(cx, args, construct)) + return false; /* Try to compile if not already compiled. */ CompileStatus status = CanMethodJIT(cx, newscript, newscript->code, construct, CompileRequest_Interpreter); if (status == Compile_Error) { /* A runtime exception was thrown, get out. */ return false; } if (status == Compile_Abort)
--- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -217,16 +217,17 @@ class EqualityICLinker : public LinkerHe { } bool init(JSContext *cx) { JSC::ExecutablePool *pool = LinkerHelper::init(cx); if (!pool) return false; JS_ASSERT(!f.regs.inlined()); if (!f.chunk()->execPools.append(pool)) { + markVerified(); pool->release(); js_ReportOutOfMemory(cx); return false; } return true; } }; @@ -433,16 +434,17 @@ NativeStubLinker::init(JSContext *cx) if (!pool) return false; NativeCallStub stub; stub.pc = pc; stub.pool = pool; stub.jump = locationOf(done); if (!chunk->nativeCallStubs.append(stub)) { + markVerified(); pool->release(); return false; } return true; } /*
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -81,16 +81,17 @@ class PICLinker : public LinkerHelper : LinkerHelper(masm, JSC::METHOD_CODE), ic(ic) { } bool init(JSContext *cx) { JSC::ExecutablePool *pool = LinkerHelper::init(cx); if (!pool) return false; if (!ic.addPool(cx, pool)) { + markVerified(); pool->release(); js_ReportOutOfMemory(cx); return false; } return true; } };
--- a/js/src/methodjit/Retcon.cpp +++ b/js/src/methodjit/Retcon.cpp @@ -357,16 +357,18 @@ ExpandInlineFrames(JSCompartment *compar void ClearAllFrames(JSCompartment *compartment) { if (!compartment || !compartment->hasJaegerCompartment()) return; ExpandInlineFrames(compartment); + compartment->types.recompilations++; + for (VMFrame *f = compartment->jaegerCompartment()->activeFrame(); f != NULL; f = f->previous) { Recompiler::patchFrame(compartment, f, f->fp()->script()); // Clear ncode values from all frames associated with the VMFrame. // Patching the VMFrame's return address will cause all its frames to
--- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -358,17 +358,17 @@ pref("places.frecency.tempRedirectVisitB pref("places.frecency.defaultVisitBonus", 0); pref("places.frecency.unvisitedBookmarkBonus", 140); pref("places.frecency.unvisitedTypedBonus", 200); // disable color management pref("gfx.color_management.mode", 0); #ifdef ANDROID // 0=fixed margin, 1=velocity bias, 2=dynamic resolution, 3=no margins -pref("gfx.displayport.strategy", 0); +pref("gfx.displayport.strategy", 1); #endif // don't allow JS to move and resize existing windows pref("dom.disable_window_move_resize", true); // prevent click image resizing for nsImageDocument pref("browser.enable_click_image_resizing", false);
--- a/mobile/android/base/gfx/DisplayPortCalculator.java +++ b/mobile/android/base/gfx/DisplayPortCalculator.java @@ -10,17 +10,17 @@ import android.graphics.RectF; import android.util.Log; import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.GeckoAppShell; final class DisplayPortCalculator { private static final String LOGTAG = "GeckoDisplayPortCalculator"; private static final PointF ZERO_VELOCITY = new PointF(0, 0); - private static DisplayPortStrategy sStrategy = new FixedMarginStrategy(); + private static DisplayPortStrategy sStrategy = new VelocityBiasStrategy(); static DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { return sStrategy.calculate(metrics, (velocity == null ? ZERO_VELOCITY : velocity)); } static boolean aboutToCheckerboard(ImmutableViewportMetrics metrics, PointF velocity, DisplayPortMetrics displayPort) { if (displayPort == null) { return true; @@ -211,24 +211,27 @@ final class DisplayPortCalculator { } /** * This class implements the variation with a small fixed-size margin with velocity bias. * In this variation, the default margins are pretty small relative to the view size, but * they are affected by the panning velocity. Specifically, if we are panning on one axis, * we remove the margins on the other axis because we are likely axis-locked. Also once * we are panning in one direction above a certain threshold velocity, we shift the buffer - * so that it is entirely in the direction of the pan. + * so that it is almost entirely in the direction of the pan, with a little bit in the + * reverse direction. */ private static class VelocityBiasStrategy implements DisplayPortStrategy { // The length of each axis of the display port will be the corresponding view length // multiplied by this factor. - private static final float SIZE_MULTIPLIER = 1.2f; + private static final float SIZE_MULTIPLIER = 1.5f; // The velocity above which we apply the velocity bias private static final float VELOCITY_THRESHOLD = GeckoAppShell.getDpi() / 32f; + // How much of the buffer to keep in the reverse direction of the velocity + private static final float REVERSE_BUFFER = 0.2f; public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) { float displayPortWidth = metrics.getWidth() * SIZE_MULTIPLIER; float displayPortHeight = metrics.getHeight() * SIZE_MULTIPLIER; // but if we're panning on one axis, set the margins for the other axis to zero since we are likely // axis locked and won't be displaying that extra area. if (Math.abs(velocity.x) > VELOCITY_THRESHOLD && FloatUtils.fuzzyEquals(velocity.y, 0)) { @@ -244,31 +247,33 @@ final class DisplayPortCalculator { float horizontalBuffer = displayPortWidth - metrics.getWidth(); float verticalBuffer = displayPortHeight - metrics.getHeight(); // if we're panning above the VELOCITY_THRESHOLD on an axis, apply the margin so that it // is entirely in the direction of panning. Otherwise, split the margin evenly on both sides of // the display port. RectF margins = new RectF(); if (velocity.x > VELOCITY_THRESHOLD) { - margins.right = horizontalBuffer; + margins.left = horizontalBuffer * REVERSE_BUFFER; } else if (velocity.x < -VELOCITY_THRESHOLD) { - margins.left = horizontalBuffer; + margins.left = horizontalBuffer * (1.0f - REVERSE_BUFFER); } else { margins.left = horizontalBuffer / 2.0f; - margins.right = horizontalBuffer - margins.left; } + margins.right = horizontalBuffer - margins.left; + if (velocity.y > VELOCITY_THRESHOLD) { - margins.bottom = verticalBuffer; + margins.top = verticalBuffer * REVERSE_BUFFER; } else if (velocity.y < -VELOCITY_THRESHOLD) { - margins.top = verticalBuffer; + margins.top = verticalBuffer * (1.0f - REVERSE_BUFFER); } else { margins.top = verticalBuffer / 2.0f; - margins.bottom = verticalBuffer - margins.top; } + margins.bottom = verticalBuffer - margins.top; + // and finally shift the margins to account for page bounds margins = shiftMarginsForPageBounds(margins, metrics); return new DisplayPortMetrics(metrics.viewportRectLeft - margins.left, metrics.viewportRectTop - margins.top, metrics.viewportRectRight + margins.right, metrics.viewportRectBottom + margins.bottom, metrics.zoomFactor);
--- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -65,17 +65,17 @@ class HTMLElement(object): def find_element(self, method, target): return self.marionette.find_element(method, target, self.id) def find_elements(self, method, target): return self.marionette.find_elements(method, target, self.id) def get_attribute(self, attribute): - return self.marionette._send_message('getElementAttribute', 'value', element=self.id, name=attribute) + return self.marionette._send_message('getAttributeValue', 'value', element=self.id, name=attribute) def click(self): return self.marionette._send_message('clickElement', 'ok', element=self.id) def text(self): return self.marionette._send_message('getElementText', 'value', element=self.id) def send_keys(self, string):
--- a/testing/marionette/client/marionette/tests/unit/test_click.py +++ b/testing/marionette/client/marionette/tests/unit/test_click.py @@ -39,8 +39,34 @@ from marionette_test import MarionetteTe class TestClick(MarionetteTestCase): def test_click(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) link = self.marionette.find_element("id", "mozLink") link.click() self.assertEqual("Clicked", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;")) +class TestClickChrome(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) + + def test_click(self): + wins = self.marionette.get_windows() + wins.remove(self.win) + newWin = wins.pop() + self.marionette.switch_to_window(newWin) + box = self.marionette.find_element("id", "testBox") + self.assertFalse(self.marionette.execute_script("return arguments[0].checked;", [box])) + box.click() + self.assertTrue(self.marionette.execute_script("return arguments[0].checked;", [box]))
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_elementState.py @@ -0,0 +1,86 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ # +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Marionette Client. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import os +from marionette_test import MarionetteTestCase + +class TestState(MarionetteTestCase): + def test_isEnabled(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("name", "myCheckBox") + self.assertTrue(l.enabled()) + self.marionette.execute_script("arguments[0].disabled = true;", [l]) + self.assertFalse(l.enabled()) + + def test_isDisplayed(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("name", "myCheckBox") + self.assertTrue(l.displayed()) + self.marionette.execute_script("arguments[0].hidden = true;", [l]) + self.assertFalse(l.displayed()) + +class TestStateChrome(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) + + def test_isEnabled(self): + l = self.marionette.find_element("id", "textInput") + self.assertTrue(l.enabled()) + self.marionette.execute_script("arguments[0].disabled = true;", [l]) + self.assertFalse(l.enabled()) + self.marionette.execute_script("arguments[0].disabled = false;", [l]) + + def test_isDisplayed(self): + l = self.marionette.find_element("id", "textInput") + self.assertTrue(l.displayed()) + self.marionette.execute_script("arguments[0].hidden = true;", [l]) + self.assertFalse(l.displayed()) + self.marionette.execute_script("arguments[0].hidden = false;", [l]) +
--- a/testing/marionette/client/marionette/tests/unit/test_findelement.py +++ b/testing/marionette/client/marionette/tests/unit/test_findelement.py @@ -40,73 +40,90 @@ from errors import NoSuchElementExceptio class TestElements(MarionetteTestCase): def test_id(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementById('mozLink');") found_el = self.marionette.find_element("id", "mozLink") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) + + def test_child_element(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + el = self.marionette.find_element("id", "divLink") + div = self.marionette.find_element("id", "testDiv") + found_el = div.find_element("tag name", "a") + self.assertEqual(HTMLElement, type(found_el)) + self.assertEqual(el.id, found_el.id) + + def test_child_elements(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + el = self.marionette.find_element("id", "divLink2") + div = self.marionette.find_element("id", "testDiv") + found_els = div.find_elements("tag name", "a") + self.assertTrue(el.id in [found_el.id for found_el in found_els]) def test_tag_name(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementsByTagName('body')[0];") found_el = self.marionette.find_element("tag name", "body") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_class_name(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementsByClassName('linkClass')[0];") found_el = self.marionette.find_element("class name", "linkClass") self.assertEqual(HTMLElement, type(found_el)); - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_name(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementsByName('myInput')[0];") found_el = self.marionette.find_element("name", "myInput") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_selector(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementById('testh1');") found_el = self.marionette.find_element("css selector", "h1") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_link_text(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementById('mozLink');") found_el = self.marionette.find_element("link text", "Click me!") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_partial_link_text(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementById('mozLink');") found_el = self.marionette.find_element("partial link text", "Click m") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_xpath(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) el = self.marionette.execute_script("return window.document.getElementById('mozLink');") found_el = self.marionette.find_element("xpath", "id('mozLink')") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_not_found(self): test_html = self.marionette.absolute_url("test.html") self.marionette.navigate(test_html) self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page") def test_timeout(self): test_html = self.marionette.absolute_url("test.html") @@ -115,43 +132,68 @@ class TestElements(MarionetteTestCase): self.assertTrue(True, self.marionette.set_search_timeout(4000)) self.marionette.navigate(test_html) self.assertEqual(HTMLElement, type(self.marionette.find_element("id", "newDiv"))) class TestElementsChrome(MarionetteTestCase): def setUp(self): MarionetteTestCase.setUp(self) self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) def test_id(self): - el = self.marionette.execute_script("return window.document.getElementById('main-window');") - found_el = self.marionette.find_element("id", "main-window") + el = self.marionette.execute_script("return window.document.getElementById('textInput');") + found_el = self.marionette.find_element("id", "textInput") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) + + def test_child_element(self): + el = self.marionette.find_element("id", "textInput") + parent = self.marionette.find_element("id", "things") + found_el = parent.find_element("tag name", "textbox") + self.assertEqual(HTMLElement, type(found_el)) + self.assertEqual(el.id, found_el.id) + + def test_child_elements(self): + el = self.marionette.find_element("id", "textInput3") + parent = self.marionette.find_element("id", "things") + found_els = parent.find_elements("tag name", "textbox") + self.assertTrue(el.id in [found_el.id for found_el in found_els]) def test_tag_name(self): - el = self.marionette.execute_script("return window.document.getElementsByTagName('window')[0];") - found_el = self.marionette.find_element("tag name", "window") + el = self.marionette.execute_script("return window.document.getElementsByTagName('vbox')[0];") + found_el = self.marionette.find_element("tag name", "vbox") self.assertEqual(HTMLElement, type(found_el)) - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_class_name(self): - el = self.marionette.execute_script("return window.document.getElementsByClassName('editBookmarkPanelHeaderButton')[0];") - found_el = self.marionette.find_element("class name", "editBookmarkPanelHeaderButton") + el = self.marionette.execute_script("return window.document.getElementsByClassName('asdf')[0];") + found_el = self.marionette.find_element("class name", "asdf") self.assertEqual(HTMLElement, type(found_el)); - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_xpath(self): - el = self.marionette.execute_script("return window.document.getElementById('main-window');") - found_el = self.marionette.find_element("xpath", "id('main-window')") + el = self.marionette.execute_script("return window.document.getElementById('testBox');") + found_el = self.marionette.find_element("xpath", "id('testBox')") self.assertEqual(HTMLElement, type(found_el)); - self.assertTrue(el.id, found_el.id) + self.assertEqual(el.id, found_el.id) def test_not_found(self): self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "I'm not on the page") def test_timeout(self): self.assertRaises(NoSuchElementException, self.marionette.find_element, "id", "myid") self.assertTrue(True, self.marionette.set_search_timeout(4000)) - self.marionette.execute_script("window.setTimeout(function() {var b = window.document.createElement('button'); b.id = 'myid'; document.getElementById('main-window').appendChild(b);}, 1000)") + self.marionette.execute_script("window.setTimeout(function() {var b = window.document.createElement('button'); b.id = 'myid'; document.getElementById('things').appendChild(b);}, 1000)") self.assertEqual(HTMLElement, type(self.marionette.find_element("id", "myid"))) - self.marionette.execute_script("window.document.getElementById('main-window').removeChild(window.document.getElementById('myid'));") + self.marionette.execute_script("window.document.getElementById('things').removeChild(window.document.getElementById('myid'));")
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_getattr.py @@ -0,0 +1,67 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ # +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Marionette Client. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import os +from marionette_test import MarionetteTestCase + +class TestGetAttribute(MarionetteTestCase): + def test_getAttribute(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("id", "mozLink") + self.assertEqual("mozLink", l.get_attribute("id")) + +class TestGetAttributeChrome(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) + + def test_getAttribute(self): + el = self.marionette.execute_script("return window.document.getElementById('textInput');") + found_el = self.marionette.find_element("id", "textInput") + self.assertEqual(el.get_attribute("id"), "textInput") +
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_selected.py @@ -0,0 +1,73 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ # +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Marionette Client. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import os +from marionette_test import MarionetteTestCase + +class TestSelected(MarionetteTestCase): + def test_selected(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + box = self.marionette.find_element("name", "myCheckBox") + self.assertFalse(box.selected()) + box.click() + self.assertTrue(box.selected()) + +class TestSelectedChrome(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) + + def test_selected(self): + wins = self.marionette.get_windows() + wins.remove(self.win) + newWin = wins.pop() + self.marionette.switch_to_window(newWin) + box = self.marionette.find_element("id", "testBox") + self.assertFalse(box.selected()) + self.assertFalse(self.marionette.execute_script("arguments[0].checked = true;", [box])) + self.assertTrue(box.selected())
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_text.py @@ -0,0 +1,105 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ # +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Marionette Client. +# +# The Initial Developer of the Original Code is +# Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import os +from marionette_test import MarionetteTestCase + +class TestText(MarionetteTestCase): + def test_getText(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("id", "mozLink") + self.assertEqual("Click me!", l.text()) + + def test_clearText(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("name", "myInput") + self.assertEqual("asdf", self.marionette.execute_script("return arguments[0].value;", [l])) + l.clear() + self.assertEqual("", self.marionette.execute_script("return arguments[0].value;", [l])) + + def test_sendKeys(self): + test_html = self.marionette.absolute_url("test.html") + self.marionette.navigate(test_html) + l = self.marionette.find_element("name", "myInput") + self.assertEqual("asdf", self.marionette.execute_script("return arguments[0].value;", [l])) + l.send_keys("o") + self.assertEqual("asdfo", self.marionette.execute_script("return arguments[0].value;", [l])) + +class TestTextChrome(MarionetteTestCase): + def setUp(self): + MarionetteTestCase.setUp(self) + self.marionette.set_context("chrome") + self.win = self.marionette.get_window() + #need to get the file:// path for xul + unit = os.path.abspath(os.path.join(os.path.realpath(__file__), os.path.pardir)) + tests = os.path.abspath(os.path.join(unit, os.path.pardir)) + mpath = os.path.abspath(os.path.join(tests, os.path.pardir)) + xul = "file://" + os.path.join(mpath, "www", "test.xul") + self.marionette.execute_script("window.open('" + xul +"', '_blank', 'chrome,centerscreen');") + + def tearDown(self): + self.marionette.execute_script("window.close();") + self.marionette.switch_to_window(self.win) + MarionetteTestCase.tearDown(self) + + def test_getText(self): + wins = self.marionette.get_windows() + wins.remove(self.win) + newWin = wins.pop() + self.marionette.switch_to_window(newWin) + box = self.marionette.find_element("id", "textInput") + self.assertEqual("test", box.text()) + + def test_clearText(self): + wins = self.marionette.get_windows() + wins.remove(self.win) + newWin = wins.pop() + self.marionette.switch_to_window(newWin) + box = self.marionette.find_element("id", "textInput") + self.assertEqual("test", box.text()) + box.clear() + self.assertEqual("", box.text()) + + def test_sendKeys(self): + wins = self.marionette.get_windows() + wins.remove(self.win) + newWin = wins.pop() + self.marionette.switch_to_window(newWin) + box = self.marionette.find_element("id", "textInput") + self.assertEqual("test", box.text()) + box.send_keys("at") + self.assertEqual("attest", box.text())
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -1,10 +1,18 @@ [test_click.py] b2g = false +[test_selected.py] +b2g = false +[test_getattr.py] +b2g = false +[test_elementState.py] +b2g = false +[test_text.py] +b2g = false [test_log.py] [test_execute_async_script.py] [test_execute_script.py] [test_simpletest_fail.js] [test_findelement.py] b2g = false
--- a/testing/marionette/client/marionette/www/test.html +++ b/testing/marionette/client/marionette/www/test.html @@ -16,12 +16,16 @@ document.body.appendChild(newDiv); } function clicked() { var link = document.getElementById("mozLink"); link.innerHTML = "Clicked"; } </script> <a href="#" id="mozLink" class="linkClass" onclick="clicked()">Click me!</a> - <a href="#" id="mozLink" class="linkClass" onclick="clicked()">Click me!</a> - <input name="myInput" type="text" /> + <div id="testDiv"> + <a href="#" id="divLink" class="linkClass" onclick="clicked()">Div click me!</a> + <a href="#" id="divLink2" class="linkClass" onclick="clicked()">Div click me!</a> + </div> + <input name="myInput" type="text" value="asdf"/> + <input name="myCheckBox" type="checkbox" /> </body> </html>
new file mode 100644 --- /dev/null +++ b/testing/marionette/client/marionette/www/test.xul @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<!DOCTYPE window [ +]> + +<dialog id="dia" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <vbox id="things"> + <checkbox id="testBox" label="box" /> + <textbox id="textInput" size="6" value="test" label="input" /> + <textbox id="textInput2" size="6" value="test" label="input" /> + <textbox id="textInput3" class="asdf" size="6" value="test" label="input" /> + </vbox> + +</dialog>