Merge m-c to b-i
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 19 Oct 2013 22:56:18 -0700
changeset 166283 5062b395d7ce89c15b8788eb941dfc3855fcffc5
parent 166282 0b04313c144d25174ca9b98f1553a6c21dfbc6c3 (current diff)
parent 166180 4b3b07791e46e31e2503ab788650e72c8efcf5f4 (diff)
child 166284 2d8c746776836b08a1b9f97c1a89be2a8c859e9d
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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
Merge m-c to b-i
browser/extensions/shumway/components/FlashStreamConverter.js
mobile/android/base/apache/commons/codec/BinaryDecoder.java
mobile/android/base/apache/commons/codec/BinaryEncoder.java
mobile/android/base/apache/commons/codec/CharEncoding.java
mobile/android/base/apache/commons/codec/Decoder.java
mobile/android/base/apache/commons/codec/DecoderException.java
mobile/android/base/apache/commons/codec/Encoder.java
mobile/android/base/apache/commons/codec/EncoderException.java
mobile/android/base/apache/commons/codec/StringDecoder.java
mobile/android/base/apache/commons/codec/StringEncoder.java
mobile/android/base/apache/commons/codec/StringEncoderComparator.java
mobile/android/base/apache/commons/codec/binary/Base32.java
mobile/android/base/apache/commons/codec/binary/Base32InputStream.java
mobile/android/base/apache/commons/codec/binary/Base32OutputStream.java
mobile/android/base/apache/commons/codec/binary/Base64.java
mobile/android/base/apache/commons/codec/binary/Base64InputStream.java
mobile/android/base/apache/commons/codec/binary/Base64OutputStream.java
mobile/android/base/apache/commons/codec/binary/BaseNCodec.java
mobile/android/base/apache/commons/codec/binary/BaseNCodecInputStream.java
mobile/android/base/apache/commons/codec/binary/BaseNCodecOutputStream.java
mobile/android/base/apache/commons/codec/binary/BinaryCodec.java
mobile/android/base/apache/commons/codec/binary/Hex.java
mobile/android/base/apache/commons/codec/binary/StringUtils.java
mobile/android/base/apache/commons/codec/binary/package.html
mobile/android/base/apache/commons/codec/digest/DigestUtils.java
mobile/android/base/apache/commons/codec/digest/package.html
mobile/android/base/apache/commons/codec/language/AbstractCaverphone.java
mobile/android/base/apache/commons/codec/language/Caverphone.java
mobile/android/base/apache/commons/codec/language/Caverphone1.java
mobile/android/base/apache/commons/codec/language/Caverphone2.java
mobile/android/base/apache/commons/codec/language/ColognePhonetic.java
mobile/android/base/apache/commons/codec/language/DoubleMetaphone.java
mobile/android/base/apache/commons/codec/language/Metaphone.java
mobile/android/base/apache/commons/codec/language/RefinedSoundex.java
mobile/android/base/apache/commons/codec/language/Soundex.java
mobile/android/base/apache/commons/codec/language/SoundexUtils.java
mobile/android/base/apache/commons/codec/language/package.html
mobile/android/base/apache/commons/codec/net/BCodec.java
mobile/android/base/apache/commons/codec/net/QCodec.java
mobile/android/base/apache/commons/codec/net/QuotedPrintableCodec.java
mobile/android/base/apache/commons/codec/net/RFC1522Codec.java
mobile/android/base/apache/commons/codec/net/URLCodec.java
mobile/android/base/apache/commons/codec/net/Utils.java
mobile/android/base/apache/commons/codec/net/package.html
mobile/android/base/apache/commons/codec/overview.html
mobile/android/base/apache/commons/codec/package.html
mobile/android/base/braille/com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java
mobile/android/base/braille/com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java
mobile/android/base/braille/com/googlecode/eyesfree/braille/selfbraille/WriteData.java
mobile/android/base/httpclientandroidlib/ConnectionClosedException.java
mobile/android/base/httpclientandroidlib/ConnectionReuseStrategy.java
mobile/android/base/httpclientandroidlib/FormattedHeader.java
mobile/android/base/httpclientandroidlib/Header.java
mobile/android/base/httpclientandroidlib/HeaderElement.java
mobile/android/base/httpclientandroidlib/HeaderElementIterator.java
mobile/android/base/httpclientandroidlib/HeaderIterator.java
mobile/android/base/httpclientandroidlib/HttpClientConnection.java
mobile/android/base/httpclientandroidlib/HttpConnection.java
mobile/android/base/httpclientandroidlib/HttpConnectionMetrics.java
mobile/android/base/httpclientandroidlib/HttpEntity.java
mobile/android/base/httpclientandroidlib/HttpEntityEnclosingRequest.java
mobile/android/base/httpclientandroidlib/HttpException.java
mobile/android/base/httpclientandroidlib/HttpHeaders.java
mobile/android/base/httpclientandroidlib/HttpHost.java
mobile/android/base/httpclientandroidlib/HttpInetConnection.java
mobile/android/base/httpclientandroidlib/HttpMessage.java
mobile/android/base/httpclientandroidlib/HttpRequest.java
mobile/android/base/httpclientandroidlib/HttpRequestFactory.java
mobile/android/base/httpclientandroidlib/HttpRequestInterceptor.java
mobile/android/base/httpclientandroidlib/HttpResponse.java
mobile/android/base/httpclientandroidlib/HttpResponseFactory.java
mobile/android/base/httpclientandroidlib/HttpResponseInterceptor.java
mobile/android/base/httpclientandroidlib/HttpServerConnection.java
mobile/android/base/httpclientandroidlib/HttpStatus.java
mobile/android/base/httpclientandroidlib/HttpVersion.java
mobile/android/base/httpclientandroidlib/MalformedChunkCodingException.java
mobile/android/base/httpclientandroidlib/MethodNotSupportedException.java
mobile/android/base/httpclientandroidlib/NameValuePair.java
mobile/android/base/httpclientandroidlib/NoHttpResponseException.java
mobile/android/base/httpclientandroidlib/ParseException.java
mobile/android/base/httpclientandroidlib/ProtocolException.java
mobile/android/base/httpclientandroidlib/ProtocolVersion.java
mobile/android/base/httpclientandroidlib/README.txt
mobile/android/base/httpclientandroidlib/ReasonPhraseCatalog.java
mobile/android/base/httpclientandroidlib/RequestLine.java
mobile/android/base/httpclientandroidlib/StatusLine.java
mobile/android/base/httpclientandroidlib/TokenIterator.java
mobile/android/base/httpclientandroidlib/TruncatedChunkException.java
mobile/android/base/httpclientandroidlib/UnsupportedHttpVersionException.java
mobile/android/base/httpclientandroidlib/androidextra/HttpClientAndroidLog.java
mobile/android/base/httpclientandroidlib/annotation/GuardedBy.java
mobile/android/base/httpclientandroidlib/annotation/Immutable.java
mobile/android/base/httpclientandroidlib/annotation/NotThreadSafe.java
mobile/android/base/httpclientandroidlib/annotation/ThreadSafe.java
mobile/android/base/httpclientandroidlib/auth/AUTH.java
mobile/android/base/httpclientandroidlib/auth/AuthScheme.java
mobile/android/base/httpclientandroidlib/auth/AuthSchemeFactory.java
mobile/android/base/httpclientandroidlib/auth/AuthSchemeRegistry.java
mobile/android/base/httpclientandroidlib/auth/AuthScope.java
mobile/android/base/httpclientandroidlib/auth/AuthState.java
mobile/android/base/httpclientandroidlib/auth/AuthenticationException.java
mobile/android/base/httpclientandroidlib/auth/BasicUserPrincipal.java
mobile/android/base/httpclientandroidlib/auth/ContextAwareAuthScheme.java
mobile/android/base/httpclientandroidlib/auth/Credentials.java
mobile/android/base/httpclientandroidlib/auth/InvalidCredentialsException.java
mobile/android/base/httpclientandroidlib/auth/MalformedChallengeException.java
mobile/android/base/httpclientandroidlib/auth/NTCredentials.java
mobile/android/base/httpclientandroidlib/auth/NTUserPrincipal.java
mobile/android/base/httpclientandroidlib/auth/UsernamePasswordCredentials.java
mobile/android/base/httpclientandroidlib/auth/package.html
mobile/android/base/httpclientandroidlib/auth/params/AuthPNames.java
mobile/android/base/httpclientandroidlib/auth/params/AuthParamBean.java
mobile/android/base/httpclientandroidlib/auth/params/AuthParams.java
mobile/android/base/httpclientandroidlib/auth/params/package.html
mobile/android/base/httpclientandroidlib/client/AuthCache.java
mobile/android/base/httpclientandroidlib/client/AuthenticationHandler.java
mobile/android/base/httpclientandroidlib/client/CircularRedirectException.java
mobile/android/base/httpclientandroidlib/client/ClientProtocolException.java
mobile/android/base/httpclientandroidlib/client/CookieStore.java
mobile/android/base/httpclientandroidlib/client/CredentialsProvider.java
mobile/android/base/httpclientandroidlib/client/HttpClient.java
mobile/android/base/httpclientandroidlib/client/HttpRequestRetryHandler.java
mobile/android/base/httpclientandroidlib/client/HttpResponseException.java
mobile/android/base/httpclientandroidlib/client/NonRepeatableRequestException.java
mobile/android/base/httpclientandroidlib/client/RedirectException.java
mobile/android/base/httpclientandroidlib/client/RedirectHandler.java
mobile/android/base/httpclientandroidlib/client/RedirectStrategy.java
mobile/android/base/httpclientandroidlib/client/RequestDirector.java
mobile/android/base/httpclientandroidlib/client/ResponseHandler.java
mobile/android/base/httpclientandroidlib/client/UserTokenHandler.java
mobile/android/base/httpclientandroidlib/client/entity/DecompressingEntity.java
mobile/android/base/httpclientandroidlib/client/entity/DeflateDecompressingEntity.java
mobile/android/base/httpclientandroidlib/client/entity/GzipDecompressingEntity.java
mobile/android/base/httpclientandroidlib/client/entity/UrlEncodedFormEntity.java
mobile/android/base/httpclientandroidlib/client/entity/package.html
mobile/android/base/httpclientandroidlib/client/methods/AbortableHttpRequest.java
mobile/android/base/httpclientandroidlib/client/methods/HttpDelete.java
mobile/android/base/httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java
mobile/android/base/httpclientandroidlib/client/methods/HttpGet.java
mobile/android/base/httpclientandroidlib/client/methods/HttpHead.java
mobile/android/base/httpclientandroidlib/client/methods/HttpOptions.java
mobile/android/base/httpclientandroidlib/client/methods/HttpPost.java
mobile/android/base/httpclientandroidlib/client/methods/HttpPut.java
mobile/android/base/httpclientandroidlib/client/methods/HttpRequestBase.java
mobile/android/base/httpclientandroidlib/client/methods/HttpTrace.java
mobile/android/base/httpclientandroidlib/client/methods/HttpUriRequest.java
mobile/android/base/httpclientandroidlib/client/methods/package.html
mobile/android/base/httpclientandroidlib/client/package.html
mobile/android/base/httpclientandroidlib/client/params/AllClientPNames.java
mobile/android/base/httpclientandroidlib/client/params/AuthPolicy.java
mobile/android/base/httpclientandroidlib/client/params/ClientPNames.java
mobile/android/base/httpclientandroidlib/client/params/ClientParamBean.java
mobile/android/base/httpclientandroidlib/client/params/CookiePolicy.java
mobile/android/base/httpclientandroidlib/client/params/HttpClientParams.java
mobile/android/base/httpclientandroidlib/client/params/package.html
mobile/android/base/httpclientandroidlib/client/protocol/ClientContext.java
mobile/android/base/httpclientandroidlib/client/protocol/ClientContextConfigurer.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestAcceptEncoding.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestAddCookies.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestAuthCache.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestClientConnControl.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestDefaultHeaders.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestProxyAuthentication.java
mobile/android/base/httpclientandroidlib/client/protocol/RequestTargetAuthentication.java
mobile/android/base/httpclientandroidlib/client/protocol/ResponseAuthCache.java
mobile/android/base/httpclientandroidlib/client/protocol/ResponseContentEncoding.java
mobile/android/base/httpclientandroidlib/client/protocol/ResponseProcessCookies.java
mobile/android/base/httpclientandroidlib/client/protocol/package.html
mobile/android/base/httpclientandroidlib/client/utils/CloneUtils.java
mobile/android/base/httpclientandroidlib/client/utils/Idn.java
mobile/android/base/httpclientandroidlib/client/utils/JdkIdn.java
mobile/android/base/httpclientandroidlib/client/utils/Punycode.java
mobile/android/base/httpclientandroidlib/client/utils/Rfc3492Idn.java
mobile/android/base/httpclientandroidlib/client/utils/URIUtils.java
mobile/android/base/httpclientandroidlib/client/utils/URLEncodedUtils.java
mobile/android/base/httpclientandroidlib/client/utils/package.html
mobile/android/base/httpclientandroidlib/conn/BasicEofSensorWatcher.java
mobile/android/base/httpclientandroidlib/conn/BasicManagedEntity.java
mobile/android/base/httpclientandroidlib/conn/ClientConnectionManager.java
mobile/android/base/httpclientandroidlib/conn/ClientConnectionManagerFactory.java
mobile/android/base/httpclientandroidlib/conn/ClientConnectionOperator.java
mobile/android/base/httpclientandroidlib/conn/ClientConnectionRequest.java
mobile/android/base/httpclientandroidlib/conn/ConnectTimeoutException.java
mobile/android/base/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java
mobile/android/base/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java
mobile/android/base/httpclientandroidlib/conn/ConnectionReleaseTrigger.java
mobile/android/base/httpclientandroidlib/conn/EofSensorInputStream.java
mobile/android/base/httpclientandroidlib/conn/EofSensorWatcher.java
mobile/android/base/httpclientandroidlib/conn/HttpHostConnectException.java
mobile/android/base/httpclientandroidlib/conn/HttpRoutedConnection.java
mobile/android/base/httpclientandroidlib/conn/ManagedClientConnection.java
mobile/android/base/httpclientandroidlib/conn/MultihomePlainSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/OperatedClientConnection.java
mobile/android/base/httpclientandroidlib/conn/package.html
mobile/android/base/httpclientandroidlib/conn/params/ConnConnectionPNames.java
mobile/android/base/httpclientandroidlib/conn/params/ConnConnectionParamBean.java
mobile/android/base/httpclientandroidlib/conn/params/ConnManagerPNames.java
mobile/android/base/httpclientandroidlib/conn/params/ConnManagerParamBean.java
mobile/android/base/httpclientandroidlib/conn/params/ConnManagerParams.java
mobile/android/base/httpclientandroidlib/conn/params/ConnPerRoute.java
mobile/android/base/httpclientandroidlib/conn/params/ConnPerRouteBean.java
mobile/android/base/httpclientandroidlib/conn/params/ConnRoutePNames.java
mobile/android/base/httpclientandroidlib/conn/params/ConnRouteParamBean.java
mobile/android/base/httpclientandroidlib/conn/params/ConnRouteParams.java
mobile/android/base/httpclientandroidlib/conn/params/package.html
mobile/android/base/httpclientandroidlib/conn/routing/BasicRouteDirector.java
mobile/android/base/httpclientandroidlib/conn/routing/HttpRoute.java
mobile/android/base/httpclientandroidlib/conn/routing/HttpRouteDirector.java
mobile/android/base/httpclientandroidlib/conn/routing/HttpRoutePlanner.java
mobile/android/base/httpclientandroidlib/conn/routing/RouteInfo.java
mobile/android/base/httpclientandroidlib/conn/routing/RouteTracker.java
mobile/android/base/httpclientandroidlib/conn/routing/package.html
mobile/android/base/httpclientandroidlib/conn/scheme/HostNameResolver.java
mobile/android/base/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactoryAdaptor.java
mobile/android/base/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java
mobile/android/base/httpclientandroidlib/conn/scheme/PlainSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/scheme/Scheme.java
mobile/android/base/httpclientandroidlib/conn/scheme/SchemeRegistry.java
mobile/android/base/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java
mobile/android/base/httpclientandroidlib/conn/scheme/SocketFactory.java
mobile/android/base/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java
mobile/android/base/httpclientandroidlib/conn/scheme/package.html
mobile/android/base/httpclientandroidlib/conn/ssl/AbstractVerifier.java
mobile/android/base/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java
mobile/android/base/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java
mobile/android/base/httpclientandroidlib/conn/ssl/SSLSocketFactory.java
mobile/android/base/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java
mobile/android/base/httpclientandroidlib/conn/ssl/TrustManagerDecorator.java
mobile/android/base/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java
mobile/android/base/httpclientandroidlib/conn/ssl/TrustStrategy.java
mobile/android/base/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java
mobile/android/base/httpclientandroidlib/conn/ssl/package.html
mobile/android/base/httpclientandroidlib/conn/util/InetAddressUtils.java
mobile/android/base/httpclientandroidlib/conn/util/package.html
mobile/android/base/httpclientandroidlib/cookie/ClientCookie.java
mobile/android/base/httpclientandroidlib/cookie/Cookie.java
mobile/android/base/httpclientandroidlib/cookie/CookieAttributeHandler.java
mobile/android/base/httpclientandroidlib/cookie/CookieIdentityComparator.java
mobile/android/base/httpclientandroidlib/cookie/CookieOrigin.java
mobile/android/base/httpclientandroidlib/cookie/CookiePathComparator.java
mobile/android/base/httpclientandroidlib/cookie/CookieRestrictionViolationException.java
mobile/android/base/httpclientandroidlib/cookie/CookieSpec.java
mobile/android/base/httpclientandroidlib/cookie/CookieSpecFactory.java
mobile/android/base/httpclientandroidlib/cookie/CookieSpecRegistry.java
mobile/android/base/httpclientandroidlib/cookie/MalformedCookieException.java
mobile/android/base/httpclientandroidlib/cookie/SM.java
mobile/android/base/httpclientandroidlib/cookie/SetCookie.java
mobile/android/base/httpclientandroidlib/cookie/SetCookie2.java
mobile/android/base/httpclientandroidlib/cookie/package.html
mobile/android/base/httpclientandroidlib/cookie/params/CookieSpecPNames.java
mobile/android/base/httpclientandroidlib/cookie/params/CookieSpecParamBean.java
mobile/android/base/httpclientandroidlib/cookie/params/package.html
mobile/android/base/httpclientandroidlib/entity/AbstractHttpEntity.java
mobile/android/base/httpclientandroidlib/entity/BasicHttpEntity.java
mobile/android/base/httpclientandroidlib/entity/BufferedHttpEntity.java
mobile/android/base/httpclientandroidlib/entity/ByteArrayEntity.java
mobile/android/base/httpclientandroidlib/entity/ContentLengthStrategy.java
mobile/android/base/httpclientandroidlib/entity/ContentProducer.java
mobile/android/base/httpclientandroidlib/entity/EntityTemplate.java
mobile/android/base/httpclientandroidlib/entity/FileEntity.java
mobile/android/base/httpclientandroidlib/entity/HttpEntityWrapper.java
mobile/android/base/httpclientandroidlib/entity/InputStreamEntity.java
mobile/android/base/httpclientandroidlib/entity/SerializableEntity.java
mobile/android/base/httpclientandroidlib/entity/StringEntity.java
mobile/android/base/httpclientandroidlib/entity/package.html
mobile/android/base/httpclientandroidlib/impl/AbstractHttpClientConnection.java
mobile/android/base/httpclientandroidlib/impl/AbstractHttpServerConnection.java
mobile/android/base/httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java
mobile/android/base/httpclientandroidlib/impl/DefaultHttpClientConnection.java
mobile/android/base/httpclientandroidlib/impl/DefaultHttpRequestFactory.java
mobile/android/base/httpclientandroidlib/impl/DefaultHttpResponseFactory.java
mobile/android/base/httpclientandroidlib/impl/DefaultHttpServerConnection.java
mobile/android/base/httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java
mobile/android/base/httpclientandroidlib/impl/HttpConnectionMetricsImpl.java
mobile/android/base/httpclientandroidlib/impl/NoConnectionReuseStrategy.java
mobile/android/base/httpclientandroidlib/impl/SocketHttpClientConnection.java
mobile/android/base/httpclientandroidlib/impl/SocketHttpServerConnection.java
mobile/android/base/httpclientandroidlib/impl/auth/AuthSchemeBase.java
mobile/android/base/httpclientandroidlib/impl/auth/BasicScheme.java
mobile/android/base/httpclientandroidlib/impl/auth/BasicSchemeFactory.java
mobile/android/base/httpclientandroidlib/impl/auth/DigestScheme.java
mobile/android/base/httpclientandroidlib/impl/auth/DigestSchemeFactory.java
mobile/android/base/httpclientandroidlib/impl/auth/NTLMEngine.java
mobile/android/base/httpclientandroidlib/impl/auth/NTLMEngineException.java
mobile/android/base/httpclientandroidlib/impl/auth/NTLMEngineImpl.java
mobile/android/base/httpclientandroidlib/impl/auth/NTLMScheme.java
mobile/android/base/httpclientandroidlib/impl/auth/NTLMSchemeFactory.java
mobile/android/base/httpclientandroidlib/impl/auth/RFC2617Scheme.java
mobile/android/base/httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java
mobile/android/base/httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java
mobile/android/base/httpclientandroidlib/impl/auth/package.html
mobile/android/base/httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java
mobile/android/base/httpclientandroidlib/impl/client/AbstractHttpClient.java
mobile/android/base/httpclientandroidlib/impl/client/BasicAuthCache.java
mobile/android/base/httpclientandroidlib/impl/client/BasicCookieStore.java
mobile/android/base/httpclientandroidlib/impl/client/BasicCredentialsProvider.java
mobile/android/base/httpclientandroidlib/impl/client/BasicResponseHandler.java
mobile/android/base/httpclientandroidlib/impl/client/ClientParamsStack.java
mobile/android/base/httpclientandroidlib/impl/client/ContentEncodingHttpClient.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultHttpClient.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultRedirectHandler.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultRedirectStrategy.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultRequestDirector.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java
mobile/android/base/httpclientandroidlib/impl/client/DefaultUserTokenHandler.java
mobile/android/base/httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java
mobile/android/base/httpclientandroidlib/impl/client/RedirectLocations.java
mobile/android/base/httpclientandroidlib/impl/client/RequestWrapper.java
mobile/android/base/httpclientandroidlib/impl/client/RoutedRequest.java
mobile/android/base/httpclientandroidlib/impl/client/TunnelRefusedException.java
mobile/android/base/httpclientandroidlib/impl/client/package.html
mobile/android/base/httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java
mobile/android/base/httpclientandroidlib/impl/conn/AbstractPoolEntry.java
mobile/android/base/httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java
mobile/android/base/httpclientandroidlib/impl/conn/ConnectionShutdownException.java
mobile/android/base/httpclientandroidlib/impl/conn/DefaultClientConnection.java
mobile/android/base/httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java
mobile/android/base/httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java
mobile/android/base/httpclientandroidlib/impl/conn/DefaultResponseParser.java
mobile/android/base/httpclientandroidlib/impl/conn/HttpInetSocketAddress.java
mobile/android/base/httpclientandroidlib/impl/conn/IdleConnectionHandler.java
mobile/android/base/httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java
mobile/android/base/httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java
mobile/android/base/httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java
mobile/android/base/httpclientandroidlib/impl/conn/SchemeRegistryFactory.java
mobile/android/base/httpclientandroidlib/impl/conn/SingleClientConnManager.java
mobile/android/base/httpclientandroidlib/impl/conn/Wire.java
mobile/android/base/httpclientandroidlib/impl/conn/package.html
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/RefQueueHandler.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/RefQueueWorker.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/WaitingThread.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/doc-files/tsccm-structure.png
mobile/android/base/httpclientandroidlib/impl/conn/tsccm/package.html
mobile/android/base/httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/AbstractCookieSpec.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicClientCookie.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicClientCookie2.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicCommentHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicDomainHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicExpiresHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicPathHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BasicSecureHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/BestMatchSpec.java
mobile/android/base/httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/BrowserCompatSpec.java
mobile/android/base/httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/CookieSpecBase.java
mobile/android/base/httpclientandroidlib/impl/cookie/DateParseException.java
mobile/android/base/httpclientandroidlib/impl/cookie/DateUtils.java
mobile/android/base/httpclientandroidlib/impl/cookie/IgnoreSpec.java
mobile/android/base/httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java
mobile/android/base/httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java
mobile/android/base/httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/PublicSuffixFilter.java
mobile/android/base/httpclientandroidlib/impl/cookie/PublicSuffixListParser.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2109Spec.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965Spec.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java
mobile/android/base/httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java
mobile/android/base/httpclientandroidlib/impl/cookie/package.html
mobile/android/base/httpclientandroidlib/impl/entity/EntityDeserializer.java
mobile/android/base/httpclientandroidlib/impl/entity/EntitySerializer.java
mobile/android/base/httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java
mobile/android/base/httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java
mobile/android/base/httpclientandroidlib/impl/entity/package.html
mobile/android/base/httpclientandroidlib/impl/io/AbstractMessageParser.java
mobile/android/base/httpclientandroidlib/impl/io/AbstractMessageWriter.java
mobile/android/base/httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java
mobile/android/base/httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java
mobile/android/base/httpclientandroidlib/impl/io/ChunkedInputStream.java
mobile/android/base/httpclientandroidlib/impl/io/ChunkedOutputStream.java
mobile/android/base/httpclientandroidlib/impl/io/ContentLengthInputStream.java
mobile/android/base/httpclientandroidlib/impl/io/ContentLengthOutputStream.java
mobile/android/base/httpclientandroidlib/impl/io/HttpRequestParser.java
mobile/android/base/httpclientandroidlib/impl/io/HttpRequestWriter.java
mobile/android/base/httpclientandroidlib/impl/io/HttpResponseParser.java
mobile/android/base/httpclientandroidlib/impl/io/HttpResponseWriter.java
mobile/android/base/httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java
mobile/android/base/httpclientandroidlib/impl/io/IdentityInputStream.java
mobile/android/base/httpclientandroidlib/impl/io/IdentityOutputStream.java
mobile/android/base/httpclientandroidlib/impl/io/SocketInputBuffer.java
mobile/android/base/httpclientandroidlib/impl/io/SocketOutputBuffer.java
mobile/android/base/httpclientandroidlib/impl/io/package.html
mobile/android/base/httpclientandroidlib/impl/package.html
mobile/android/base/httpclientandroidlib/io/BufferInfo.java
mobile/android/base/httpclientandroidlib/io/EofSensor.java
mobile/android/base/httpclientandroidlib/io/HttpMessageParser.java
mobile/android/base/httpclientandroidlib/io/HttpMessageWriter.java
mobile/android/base/httpclientandroidlib/io/HttpTransportMetrics.java
mobile/android/base/httpclientandroidlib/io/SessionInputBuffer.java
mobile/android/base/httpclientandroidlib/io/SessionOutputBuffer.java
mobile/android/base/httpclientandroidlib/io/package.html
mobile/android/base/httpclientandroidlib/message/AbstractHttpMessage.java
mobile/android/base/httpclientandroidlib/message/BasicHeader.java
mobile/android/base/httpclientandroidlib/message/BasicHeaderElement.java
mobile/android/base/httpclientandroidlib/message/BasicHeaderElementIterator.java
mobile/android/base/httpclientandroidlib/message/BasicHeaderIterator.java
mobile/android/base/httpclientandroidlib/message/BasicHeaderValueFormatter.java
mobile/android/base/httpclientandroidlib/message/BasicHeaderValueParser.java
mobile/android/base/httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java
mobile/android/base/httpclientandroidlib/message/BasicHttpRequest.java
mobile/android/base/httpclientandroidlib/message/BasicHttpResponse.java
mobile/android/base/httpclientandroidlib/message/BasicLineFormatter.java
mobile/android/base/httpclientandroidlib/message/BasicLineParser.java
mobile/android/base/httpclientandroidlib/message/BasicListHeaderIterator.java
mobile/android/base/httpclientandroidlib/message/BasicNameValuePair.java
mobile/android/base/httpclientandroidlib/message/BasicRequestLine.java
mobile/android/base/httpclientandroidlib/message/BasicStatusLine.java
mobile/android/base/httpclientandroidlib/message/BasicTokenIterator.java
mobile/android/base/httpclientandroidlib/message/BufferedHeader.java
mobile/android/base/httpclientandroidlib/message/HeaderGroup.java
mobile/android/base/httpclientandroidlib/message/HeaderValueFormatter.java
mobile/android/base/httpclientandroidlib/message/HeaderValueParser.java
mobile/android/base/httpclientandroidlib/message/LineFormatter.java
mobile/android/base/httpclientandroidlib/message/LineParser.java
mobile/android/base/httpclientandroidlib/message/ParserCursor.java
mobile/android/base/httpclientandroidlib/message/package.html
mobile/android/base/httpclientandroidlib/package.html
mobile/android/base/httpclientandroidlib/params/AbstractHttpParams.java
mobile/android/base/httpclientandroidlib/params/BasicHttpParams.java
mobile/android/base/httpclientandroidlib/params/CoreConnectionPNames.java
mobile/android/base/httpclientandroidlib/params/CoreProtocolPNames.java
mobile/android/base/httpclientandroidlib/params/DefaultedHttpParams.java
mobile/android/base/httpclientandroidlib/params/HttpAbstractParamBean.java
mobile/android/base/httpclientandroidlib/params/HttpConnectionParamBean.java
mobile/android/base/httpclientandroidlib/params/HttpConnectionParams.java
mobile/android/base/httpclientandroidlib/params/HttpParams.java
mobile/android/base/httpclientandroidlib/params/HttpProtocolParamBean.java
mobile/android/base/httpclientandroidlib/params/HttpProtocolParams.java
mobile/android/base/httpclientandroidlib/params/SyncBasicHttpParams.java
mobile/android/base/httpclientandroidlib/params/package.html
mobile/android/base/httpclientandroidlib/protocol/BasicHttpContext.java
mobile/android/base/httpclientandroidlib/protocol/BasicHttpProcessor.java
mobile/android/base/httpclientandroidlib/protocol/DefaultedHttpContext.java
mobile/android/base/httpclientandroidlib/protocol/ExecutionContext.java
mobile/android/base/httpclientandroidlib/protocol/HTTP.java
mobile/android/base/httpclientandroidlib/protocol/HttpContext.java
mobile/android/base/httpclientandroidlib/protocol/HttpDateGenerator.java
mobile/android/base/httpclientandroidlib/protocol/HttpExpectationVerifier.java
mobile/android/base/httpclientandroidlib/protocol/HttpProcessor.java
mobile/android/base/httpclientandroidlib/protocol/HttpRequestExecutor.java
mobile/android/base/httpclientandroidlib/protocol/HttpRequestHandler.java
mobile/android/base/httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java
mobile/android/base/httpclientandroidlib/protocol/HttpRequestHandlerResolver.java
mobile/android/base/httpclientandroidlib/protocol/HttpRequestInterceptorList.java
mobile/android/base/httpclientandroidlib/protocol/HttpResponseInterceptorList.java
mobile/android/base/httpclientandroidlib/protocol/HttpService.java
mobile/android/base/httpclientandroidlib/protocol/ImmutableHttpProcessor.java
mobile/android/base/httpclientandroidlib/protocol/RequestConnControl.java
mobile/android/base/httpclientandroidlib/protocol/RequestContent.java
mobile/android/base/httpclientandroidlib/protocol/RequestDate.java
mobile/android/base/httpclientandroidlib/protocol/RequestExpectContinue.java
mobile/android/base/httpclientandroidlib/protocol/RequestTargetHost.java
mobile/android/base/httpclientandroidlib/protocol/RequestUserAgent.java
mobile/android/base/httpclientandroidlib/protocol/ResponseConnControl.java
mobile/android/base/httpclientandroidlib/protocol/ResponseContent.java
mobile/android/base/httpclientandroidlib/protocol/ResponseDate.java
mobile/android/base/httpclientandroidlib/protocol/ResponseServer.java
mobile/android/base/httpclientandroidlib/protocol/SyncBasicHttpContext.java
mobile/android/base/httpclientandroidlib/protocol/UriPatternMatcher.java
mobile/android/base/httpclientandroidlib/protocol/package.html
mobile/android/base/httpclientandroidlib/util/ByteArrayBuffer.java
mobile/android/base/httpclientandroidlib/util/CharArrayBuffer.java
mobile/android/base/httpclientandroidlib/util/EncodingUtils.java
mobile/android/base/httpclientandroidlib/util/EntityUtils.java
mobile/android/base/httpclientandroidlib/util/ExceptionUtils.java
mobile/android/base/httpclientandroidlib/util/LangUtils.java
mobile/android/base/httpclientandroidlib/util/VersionInfo.java
mobile/android/base/httpclientandroidlib/util/package.html
mobile/android/base/json-simple/ItemList.java
mobile/android/base/json-simple/JSONArray.java
mobile/android/base/json-simple/JSONAware.java
mobile/android/base/json-simple/JSONObject.java
mobile/android/base/json-simple/JSONStreamAware.java
mobile/android/base/json-simple/JSONValue.java
mobile/android/base/json-simple/LICENSE.txt
mobile/android/base/json-simple/parser/ContainerFactory.java
mobile/android/base/json-simple/parser/ContentHandler.java
mobile/android/base/json-simple/parser/JSONParser.java
mobile/android/base/json-simple/parser/ParseException.java
mobile/android/base/json-simple/parser/Yylex.java
mobile/android/base/json-simple/parser/Yytoken.java
mobile/android/base/resources/drawable-hdpi/grid_icon_bg_activated.png
mobile/android/base/websockets/HybiParser.java
mobile/android/base/websockets/README.md
mobile/android/base/websockets/README_MOZILLA
mobile/android/base/websockets/WebSocketClient.java
mobile/android/chrome/content/HelperApps.js
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1380576907000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1382113575000">
   <emItems>
       <emItem  blockID="i454" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
@@ -430,16 +430,20 @@
       <emItem  blockID="i394" id="{7D4F1959-3F72-49d5-8E59-F02F8AA6815D}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i344" id="lrcsTube@hansanddeta.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i461" id="{8E9E3331-D360-4f87-8803-52DE43566502}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i426" id="addlyrics@addlyrics.net">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i448" id="{0134af61-7a0c-4649-aeca-90d776060cb3}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                   </emItem>
@@ -468,16 +472,20 @@
       <emItem  blockID="i435" id="pluggets@gmail.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i67" id="youtube2@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i460" id="{845cab51-d8d2-472f-8bd9-2b44642d97c2}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
                         <versionRange  minVersion=" " maxVersion="8.5">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i56" id="flash@adobe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -1157,16 +1165,58 @@
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p428">
                   <match name="filename" exp="np[dD]eployJava1\.dll" />                      <versionRange  severity="0" vulnerabilitystatus="2"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p456">
                   <match name="filename" exp="npvlc\.dll" />                      <versionRange  minVersion="0" maxVersion="2.0.5" severity="0" vulnerabilitystatus="1"></versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p457">
+      <match name="name" exp="Java(\(TM\))? Plug-in ((1\.7\.0_(2[5-9]|3\d|4[0-4]))|(10\.4[0-4](\.[0-9]+)?))([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="17.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p458">
+      <match name="name" exp="Java\(TM\) Platform SE 7 U(2[5-9]|3\d|4[0-4])(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="1">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="17.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p459">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 25" maxVersion="Java 7 Update 44" severity="0" vulnerabilitystatus="1">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="17.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p462">
+                  <match name="filename" exp="JavaAppletPlugin\.plugin" />                                    <versionRange  minVersion="Java 7 Update 45" maxVersion="Java 7 Update 45" severity="0" vulnerabilitystatus="2">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="24.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p463">
+      <match name="name" exp="Java\(TM\) Platform SE 7 U45(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="24.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p464">
+      <match name="name" exp="Java(\(TM\))? Plug-in 10\.45(\.[0-9]+)?([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                                    <versionRange  severity="0" vulnerabilitystatus="2">
+                                <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="24.0" maxVersion="*" />
+                          </targetApplication>
+                  </versionRange>
+                  </pluginItem>
     </pluginItems>
 
   <gfxItems>
     <gfxBlacklistEntry  blockID="g35">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
                       <device>0x0a6c</device>
                   </devices>
             <feature>DIRECT2D</feature>      <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>      <driverVersion>8.17.12.5896</driverVersion>      <driverVersionComparator>LESS_THAN_OR_EQUAL</driverVersionComparator>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g36">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -9,20 +9,24 @@ function debug(msg) {
 }
 
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
 
 XPCOMUtils.defineLazyModuleGetter(this, "DocShellCapabilities",
   "resource:///modules/sessionstore/DocShellCapabilities.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PageStyle",
+  "resource:///modules/sessionstore/PageStyle.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionHistory",
   "resource:///modules/sessionstore/SessionHistory.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
   "resource:///modules/sessionstore/SessionStorage.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TextAndScrollData",
+  "resource:///modules/sessionstore/TextAndScrollData.jsm");
 
 /**
  * Listens for and handles content events that we need for the
  * session store service to be notified of state changes in content.
  */
 let EventListener = {
 
   DOM_EVENTS: [
@@ -70,37 +74,50 @@ let EventListener = {
 /**
  * Listens for and handles messages sent by the session store service.
  */
 let MessageListener = {
 
   MESSAGES: [
     "SessionStore:collectSessionHistory",
     "SessionStore:collectSessionStorage",
-    "SessionStore:collectDocShellCapabilities"
+    "SessionStore:collectDocShellCapabilities",
+    "SessionStore:collectPageStyle"
   ],
 
   init: function () {
     this.MESSAGES.forEach(m => addMessageListener(m, this));
   },
 
   receiveMessage: function ({name, data: {id}}) {
     switch (name) {
       case "SessionStore:collectSessionHistory":
         let history = SessionHistory.read(docShell);
+        if ("index" in history) {
+          let tabIndex = history.index - 1;
+          // Don't include private data. It's only needed when duplicating
+          // tabs, which collects data synchronously.
+          TextAndScrollData.updateFrame(history.entries[tabIndex],
+                                        content,
+                                        docShell.isAppTab);
+        }
         sendAsyncMessage(name, {id: id, data: history});
         break;
       case "SessionStore:collectSessionStorage":
         let storage = SessionStorage.serialize(docShell);
         sendAsyncMessage(name, {id: id, data: storage});
         break;
       case "SessionStore:collectDocShellCapabilities":
         let disallow = DocShellCapabilities.collect(docShell);
         sendAsyncMessage(name, {id: id, data: disallow});
         break;
+      case "SessionStore:collectPageStyle":
+        let pageStyle = PageStyle.collect(docShell);
+        sendAsyncMessage(name, {id: id, data: pageStyle});
+        break;
       default:
         debug("received unknown message '" + name + "'");
         break;
     }
   }
 };
 
 let ProgressListener = {
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/src/PageStyle.jsm
@@ -0,0 +1,94 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["PageStyle"];
+
+const Ci = Components.interfaces;
+
+/**
+ * The external API exported by this module.
+ */
+this.PageStyle = Object.freeze({
+  collect: function (docShell) {
+    return PageStyleInternal.collect(docShell);
+  },
+
+  restore: function (docShell, frameList, pageStyle) {
+    PageStyleInternal.restore(docShell, frameList, pageStyle);
+  },
+});
+
+// Signifies that author style level is disabled for the page.
+const NO_STYLE = "_nostyle";
+
+let PageStyleInternal = {
+  /**
+   * Find out the title of the style sheet selected for the given
+   * docshell. Recurse into frames if needed.
+   */
+  collect: function (docShell) {
+    let markupDocumentViewer =
+      docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
+    if (markupDocumentViewer.authorStyleDisabled) {
+      return NO_STYLE;
+    }
+
+    let content = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+
+    return this.collectFrame(content);
+  },
+
+  /**
+   * Determine the title of the currently enabled style sheet (if any);
+   * recurse through the frameset if necessary.
+   * @param   content is a frame reference
+   * @returns the title style sheet determined to be enabled (empty string if none)
+   */
+  collectFrame: function (content) {
+    const forScreen = /(?:^|,)\s*(?:all|screen)\s*(?:,|$)/i;
+
+    let sheets = content.document.styleSheets;
+    for (let i = 0; i < sheets.length; i++) {
+      let ss = sheets[i];
+      let media = ss.media.mediaText;
+      if (!ss.disabled && ss.title && (!media || forScreen.test(media))) {
+        return ss.title;
+      }
+    }
+
+    for (let i = 0; i < content.frames.length; i++) {
+      let selectedPageStyle = this.collectFrame(content.frames[i]);
+      if (selectedPageStyle) {
+        return selectedPageStyle;
+      }
+    }
+
+    return "";
+  },
+
+  /**
+   * Restore the selected style sheet of all the frames in frameList
+   * to match |pageStyle|.
+   * @param docShell the root docshell of all the frames
+   * @param frameList a list of [frame, data] pairs, where frame is a
+   * DOM window and data is the session restore data associated with
+   * it.
+   * @param pageStyle the title of the style sheet to apply
+   */
+  restore: function (docShell, frameList, pageStyle) {
+    let disabled = pageStyle == NO_STYLE;
+
+    let markupDocumentViewer =
+      docShell.contentViewer.QueryInterface(Ci.nsIMarkupDocumentViewer);
+    markupDocumentViewer.authorStyleDisabled = disabled;
+
+    for (let [frame, data] of frameList) {
+      Array.forEach(frame.document.styleSheets, function(aSS) {
+        aSS.disabled = aSS.title && aSS.title != pageStyle;
+      });
+    }
+  },
+};
--- a/browser/components/sessionstore/src/SessionStore.jsm
+++ b/browser/components/sessionstore/src/SessionStore.jsm
@@ -106,26 +106,30 @@ function makeURI(aString) {
 XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
   "resource:///modules/devtools/scratchpad-manager.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DocShellCapabilities",
   "resource:///modules/sessionstore/DocShellCapabilities.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
   "resource:///modules/sessionstore/DocumentUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Messenger",
   "resource:///modules/sessionstore/Messenger.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PageStyle",
+  "resource:///modules/sessionstore/PageStyle.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivacyLevel",
   "resource:///modules/sessionstore/PrivacyLevel.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionSaver",
   "resource:///modules/sessionstore/SessionSaver.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
   "resource:///modules/sessionstore/SessionStorage.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionCookies",
   "resource:///modules/sessionstore/SessionCookies.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SessionHistory",
   "resource:///modules/sessionstore/SessionHistory.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TextAndScrollData",
+  "resource:///modules/sessionstore/TextAndScrollData.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "_SessionFile",
   "resource:///modules/sessionstore/_SessionFile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TabStateCache",
   "resource:///modules/sessionstore/TabStateCache.jsm");
 
 #ifdef MOZ_CRASHREPORTER
 XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
   "@mozilla.org/xre/app-info;1", "nsICrashReporter");
@@ -2935,95 +2939,65 @@ let SessionStoreInternal = {
                                                        childDocIdents), i);
       }
     }
 
     return shEntry;
   },
 
   /**
+   * Accumulates a list of frames that need to be restored for the
+   * given browser element. A frame is only restored if its current
+   * URL matches the one saved in the session data. Each frame to be
+   * restored is returned along with its associated session data.
+   *
+   * @param browser the browser being restored
+   * @return an array of [frame, data] pairs
+   */
+  getFramesToRestore: function (browser) {
+    function hasExpectedURL(aDocument, aURL) {
+      return !aURL || aURL.replace(/#.*/, "") == aDocument.location.href.replace(/#.*/, "");
+    }
+
+    let frameList = [];
+
+    function enumerateFrame(content, data) {
+      // Skip the frame if the user has navigated away before loading
+      // finished.
+      if (!hasExpectedURL(content.document, data.url)) {
+        return;
+      }
+
+      frameList.push([content, data]);
+
+      for (let i = 0; i < content.frames.length; i++) {
+        if (data.children && data.children[i]) {
+          enumerateFrame(content.frames[i], data.children[i]);
+        }
+      }
+    }
+
+    enumerateFrame(browser.contentWindow, browser.__SS_restore_data);
+
+    return frameList;
+  },
+
+  /**
    * Restore properties to a loaded document
    */
   restoreDocument: function ssi_restoreDocument(aWindow, aBrowser, aEvent) {
     // wait for the top frame to be loaded completely
     if (!aEvent || !aEvent.originalTarget || !aEvent.originalTarget.defaultView ||
         aEvent.originalTarget.defaultView != aEvent.originalTarget.defaultView.top) {
       return;
     }
 
-    // always call this before injecting content into a document!
-    function hasExpectedURL(aDocument, aURL)
-      !aURL || aURL.replace(/#.*/, "") == aDocument.location.href.replace(/#.*/, "");
-
-    let selectedPageStyle = aBrowser.__SS_restore_pageStyle;
-    function restoreTextDataAndScrolling(aContent, aData, aPrefix) {
-      if (aData.formdata && hasExpectedURL(aContent.document, aData.url)) {
-        let formdata = aData.formdata;
-
-        // handle backwards compatibility
-        // this is a migration from pre-firefox 15. cf. bug 742051
-        if (!("xpath" in formdata || "id" in formdata)) {
-          formdata = { xpath: {}, id: {} };
-
-          for each (let [key, value] in Iterator(aData.formdata)) {
-            if (key.charAt(0) == "#") {
-              formdata.id[key.slice(1)] = value;
-            } else {
-              formdata.xpath[key] = value;
-            }
-          }
-        }
-
-        // for about:sessionrestore we saved the field as JSON to avoid
-        // nested instances causing humongous sessionstore.js files.
-        // cf. bug 467409
-        if ((aData.url == "about:sessionrestore" || aData.url == "about:welcomeback") &&
-            "sessionData" in formdata.id &&
-            typeof formdata.id["sessionData"] == "object") {
-          formdata.id["sessionData"] =
-            JSON.stringify(formdata.id["sessionData"]);
-        }
-
-        // update the formdata
-        aData.formdata = formdata;
-        // merge the formdata
-        DocumentUtils.mergeFormData(aContent.document, formdata);
-      }
-
-      if (aData.innerHTML) {
-        aWindow.setTimeout(function() {
-          if (aContent.document.designMode == "on" &&
-              hasExpectedURL(aContent.document, aData.url) &&
-              aContent.document.body) {
-            aContent.document.body.innerHTML = aData.innerHTML;
-          }
-        }, 0);
-      }
-      var match;
-      if (aData.scroll && (match = /(\d+),(\d+)/.exec(aData.scroll)) != null) {
-        aContent.scrollTo(match[1], match[2]);
-      }
-      Array.forEach(aContent.document.styleSheets, function(aSS) {
-        aSS.disabled = aSS.title && aSS.title != selectedPageStyle;
-      });
-      for (var i = 0; i < aContent.frames.length; i++) {
-        if (aData.children && aData.children[i] &&
-          hasExpectedURL(aContent.document, aData.url)) {
-          restoreTextDataAndScrolling(aContent.frames[i], aData.children[i], aPrefix + i + "|");
-        }
-      }
-    }
-
-    // don't restore text data and scrolling state if the user has navigated
-    // away before the loading completed (except for in-page navigation)
-    if (hasExpectedURL(aEvent.originalTarget, aBrowser.__SS_restore_data.url)) {
-      var content = aEvent.originalTarget.defaultView;
-      restoreTextDataAndScrolling(content, aBrowser.__SS_restore_data, "");
-      aBrowser.markupDocumentViewer.authorStyleDisabled = selectedPageStyle == "_nostyle";
-    }
+    let frameList = this.getFramesToRestore(aBrowser);
+    PageStyle.restore(aBrowser.docShell, frameList, aBrowser.__SS_restore_pageStyle);
+    TextAndScrollData.restore(frameList);
 
     // notify the tabbrowser that this document has been completely restored
     this._sendTabRestoredNotification(aBrowser.__SS_restore_tab);
 
     delete aBrowser.__SS_restore_data;
     delete aBrowser.__SS_restore_pageStyle;
     delete aBrowser.__SS_restore_tab;
   },
@@ -4237,45 +4211,51 @@ let TabState = {
     // have saved for it.
     let browser = tab.linkedBrowser;
     if (!browser.currentURI || (browser.__SS_data && browser.__SS_tabStillLoading)) {
       let tabData = new TabData(this._collectBaseTabData(tab));
       return Promise.resolve(tabData);
     }
 
     let promise = Task.spawn(function task() {
-      // Collected session history data asynchronously.
+      // Collect session history data asynchronously. Also collects
+      // text and scroll data.
       let history = yield Messenger.send(tab, "SessionStore:collectSessionHistory");
 
       // Collected session storage data asynchronously.
       let storage = yield Messenger.send(tab, "SessionStore:collectSessionStorage");
 
       // Collect docShell capabilities asynchronously.
       let disallow = yield Messenger.send(tab, "SessionStore:collectDocShellCapabilities");
 
+      let pageStyle = yield Messenger.send(tab, "SessionStore:collectPageStyle");
+
       // Collect basic tab data, without session history and storage.
       let options = {omitSessionHistory: true,
                      omitSessionStorage: true,
                      omitDocShellCapabilities: true};
       let tabData = this._collectBaseTabData(tab, options);
 
       // Apply collected data.
       tabData.entries = history.entries;
-      tabData.index = history.index;
+      if ("index" in history) {
+        tabData.index = history.index;
+      }
 
       if (Object.keys(storage).length) {
         tabData.storage = storage;
       }
 
       if (disallow.length > 0) {
         tabData.disallow = disallow.join(",");
       }
 
-      // Save text and scroll data.
-      this._updateTextAndScrollDataForTab(tab, tabData);
+      if (pageStyle) {
+        tabData.pageStyle = pageStyle;
+      }
 
       // If we're still the latest async collection for the given tab and
       // the cache hasn't been filled by collect() in the meantime, let's
       // fill the cache with the data we received.
       if (this._pendingCollections.get(tab) == promise) {
         TabStateCache.set(tab, tabData);
         this._pendingCollections.delete(tab);
       }
@@ -4512,113 +4492,21 @@ let TabState = {
     }
 
     let tabIndex = (tabData.index || tabData.entries.length) - 1;
     // entry data needn't exist for tabs just initialized with an incomplete session state
     if (!tabData.entries[tabIndex]) {
       return false;
     }
 
-    let selectedPageStyle = browser.markupDocumentViewer.authorStyleDisabled ? "_nostyle" :
-                            this._getSelectedPageStyle(browser.contentWindow);
-    if (selectedPageStyle)
+    let selectedPageStyle = PageStyle.collect(browser.docShell);
+    if (selectedPageStyle) {
       tabData.pageStyle = selectedPageStyle;
-    else if (tabData.pageStyle)
-      delete tabData.pageStyle;
-
-    this._updateTextAndScrollDataForFrame(window, browser.contentWindow,
-                                          tabData.entries[tabIndex],
-                                          includePrivateData,
-                                          !!tabData.pinned);
-    if (browser.currentURI.spec == "about:config") {
-      tabData.entries[tabIndex].formdata = {
-        id: {
-          "textbox": browser.contentDocument.getElementById("textbox").value
-        },
-        xpath: {}
-      };
     }
 
+    TextAndScrollData.updateFrame(tabData.entries[tabIndex],
+                                  browser.contentWindow,
+                                  !!tabData.pinned,
+                                  {includePrivateData: includePrivateData});
+
     return true;
   },
-
-  /**
-   * Go through all subframes and store all form data, the current
-   * scroll positions and innerHTML content of WYSIWYG editors.
-   *
-   * @param window
-   *        Window reference
-   * @param content
-   *        frame reference
-   * @param data
-   *        part of a tabData object to add the information to
-   * @param includePrivateData
-   *        always return privacy sensitive data (use with care)
-   * @param isPinned
-   *        the tab is pinned and should be treated differently for privacy
-   */
-  _updateTextAndScrollDataForFrame:
-    function (window, content, data, includePrivateData, isPinned) {
-
-    for (let i = 0; i < content.frames.length; i++) {
-      if (data.children && data.children[i])
-        this._updateTextAndScrollDataForFrame(window, content.frames[i],
-                                              data.children[i],
-                                              includePrivateData, isPinned);
-    }
-    let href = (content.parent || content).document.location.href;
-    let isHttps = makeURI(href).schemeIs("https");
-    let topURL = content.top.document.location.href;
-    let isAboutSR = topURL == "about:sessionrestore" || topURL == "about:welcomeback";
-    if (includePrivateData || isAboutSR ||
-        PrivacyLevel.canSave({isHttps: isHttps, isPinned: isPinned})) {
-      let formData = DocumentUtils.getFormData(content.document);
-
-      // We want to avoid saving data for about:sessionrestore as a string.
-      // Since it's stored in the form as stringified JSON, stringifying further
-      // causes an explosion of escape characters. cf. bug 467409
-      if (formData && isAboutSR) {
-        formData.id["sessionData"] = JSON.parse(formData.id["sessionData"]);
-      }
-
-      if (Object.keys(formData.id).length ||
-          Object.keys(formData.xpath).length) {
-        data.formdata = formData;
-      } else if (data.formdata) {
-        delete data.formdata;
-      }
-
-      // designMode is undefined e.g. for XUL documents (as about:config)
-      if ((content.document.designMode || "") == "on" && content.document.body)
-        data.innerHTML = content.document.body.innerHTML;
-    }
-
-    // get scroll position from nsIDOMWindowUtils, since it allows avoiding a
-    // flush of layout
-    let domWindowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindowUtils);
-    let scrollX = {}, scrollY = {};
-    domWindowUtils.getScrollXY(false, scrollX, scrollY);
-    data.scroll = scrollX.value + "," + scrollY.value;
-  },
-
-  /**
-   * determine the title of the currently enabled style sheet (if any)
-   * and recurse through the frameset if necessary
-   * @param   content is a frame reference
-   * @returns the title style sheet determined to be enabled (empty string if none)
-   */
-  _getSelectedPageStyle: function (content) {
-    const forScreen = /(?:^|,)\s*(?:all|screen)\s*(?:,|$)/i;
-    for (let i = 0; i < content.document.styleSheets.length; i++) {
-      let ss = content.document.styleSheets[i];
-      let media = ss.media.mediaText;
-      if (!ss.disabled && ss.title && (!media || forScreen.test(media)))
-        return ss.title
-    }
-    for (let i = 0; i < content.frames.length; i++) {
-      let selectedPageStyle = this._getSelectedPageStyle(content.frames[i]);
-      if (selectedPageStyle)
-        return selectedPageStyle;
-    }
-    return "";
-  }
 };
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/src/TextAndScrollData.jsm
@@ -0,0 +1,161 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["TextAndScrollData"];
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
+  "resource:///modules/sessionstore/DocumentUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PrivacyLevel",
+  "resource:///modules/sessionstore/PrivacyLevel.jsm");
+
+/**
+ * The external API exported by this module.
+ */
+this.TextAndScrollData = Object.freeze({
+  updateFrame: function (entry, content, isPinned, options) {
+    return TextAndScrollDataInternal.updateFrame(entry, content, isPinned, options);
+  },
+
+  restore: function (frameList) {
+    TextAndScrollDataInternal.restore(frameList);
+  },
+});
+
+let TextAndScrollDataInternal = {
+  /**
+   * Go through all subframes and store all form data, the current
+   * scroll positions and innerHTML content of WYSIWYG editors.
+   *
+   * @param entry
+   *        the object into which to store the collected data
+   * @param content
+   *        frame reference
+   * @param isPinned
+   *        the tab is pinned and should be treated differently for privacy
+   * @param includePrivateData
+   *        {includePrivateData:true} include privacy sensitive data (use with care)
+   */
+  updateFrame: function (entry, content, isPinned, options = null) {
+    let includePrivateData = options && options.includePrivateData;
+
+    for (let i = 0; i < content.frames.length; i++) {
+      if (entry.children && entry.children[i]) {
+        this.updateFrame(entry.children[i], content.frames[i], includePrivateData, isPinned);
+      }
+    }
+
+    let href = (content.parent || content).document.location.href;
+    let isHttps = Services.io.newURI(href, null, null).schemeIs("https");
+    let topURL = content.top.document.location.href;
+    let isAboutSR = this.isAboutSessionRestore(topURL);
+    if (includePrivateData || isAboutSR ||
+        PrivacyLevel.canSave({isHttps: isHttps, isPinned: isPinned})) {
+      let formData = DocumentUtils.getFormData(content.document);
+
+      // We want to avoid saving data for about:sessionrestore as a string.
+      // Since it's stored in the form as stringified JSON, stringifying further
+      // causes an explosion of escape characters. cf. bug 467409
+      if (formData && isAboutSR) {
+        formData.id["sessionData"] = JSON.parse(formData.id["sessionData"]);
+      }
+
+      if (Object.keys(formData.id).length ||
+          Object.keys(formData.xpath).length) {
+        entry.formdata = formData;
+      }
+
+      // designMode is undefined e.g. for XUL documents (as about:config)
+      if ((content.document.designMode || "") == "on" && content.document.body) {
+        entry.innerHTML = content.document.body.innerHTML;
+      }
+    }
+
+    // get scroll position from nsIDOMWindowUtils, since it allows avoiding a
+    // flush of layout
+    let domWindowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
+                                .getInterface(Ci.nsIDOMWindowUtils);
+    let scrollX = {}, scrollY = {};
+    domWindowUtils.getScrollXY(false, scrollX, scrollY);
+    entry.scroll = scrollX.value + "," + scrollY.value;
+
+    if (topURL == "about:config") {
+      entry.formdata = {
+        id: { "textbox": content.top.document.getElementById("textbox").value },
+        xpath: {}
+      };
+    }
+  },
+
+  isAboutSessionRestore: function (url) {
+    return url == "about:sessionrestore" || url == "about:welcomeback";
+  },
+
+  restore: function (frameList) {
+    for (let [frame, data] of frameList) {
+      this.restoreFrame(frame, data);
+    }
+  },
+
+  restoreFrame: function (content, data) {
+    if (data.formdata) {
+      let formdata = data.formdata;
+
+      // handle backwards compatibility
+      // this is a migration from pre-firefox 15. cf. bug 742051
+      if (!("xpath" in formdata || "id" in formdata)) {
+        formdata = { xpath: {}, id: {} };
+
+        for each (let [key, value] in Iterator(data.formdata)) {
+          if (key.charAt(0) == "#") {
+            formdata.id[key.slice(1)] = value;
+          } else {
+            formdata.xpath[key] = value;
+          }
+        }
+      }
+
+      // for about:sessionrestore we saved the field as JSON to avoid
+      // nested instances causing humongous sessionstore.js files.
+      // cf. bug 467409
+      if (this.isAboutSessionRestore(data.url) &&
+          "sessionData" in formdata.id &&
+          typeof formdata.id["sessionData"] == "object") {
+        formdata.id["sessionData"] = JSON.stringify(formdata.id["sessionData"]);
+      }
+
+      // update the formdata
+      data.formdata = formdata;
+      // merge the formdata
+      DocumentUtils.mergeFormData(content.document, formdata);
+    }
+
+    if (data.innerHTML) {
+      // We know that the URL matches data.url right now, but the user
+      // may navigate away before the setTimeout handler runs. We do
+      // a simple comparison against savedURL to check for that.
+      let savedURL = content.document.location.href;
+
+      setTimeout(function() {
+        if (content.document.designMode == "on" &&
+            content.document.location.href == savedURL &&
+            content.document.body) {
+          content.document.body.innerHTML = data.innerHTML;
+        }
+      }, 0);
+    }
+
+    let match;
+    if (data.scroll && (match = /(\d+),(\d+)/.exec(data.scroll)) != null) {
+      content.scrollTo(match[1], match[2]);
+    }
+  },
+};
--- a/browser/components/sessionstore/src/moz.build
+++ b/browser/components/sessionstore/src/moz.build
@@ -11,24 +11,26 @@ EXTRA_COMPONENTS += [
 ]
 
 JS_MODULES_PATH = 'modules/sessionstore'
 
 EXTRA_JS_MODULES = [
     'DocShellCapabilities.jsm',
     'DocumentUtils.jsm',
     'Messenger.jsm',
+    'PageStyle.jsm',
     'PrivacyLevel.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
     'SessionCookies.jsm',
     'SessionHistory.jsm',
     'SessionMigration.jsm',
     'SessionStorage.jsm',
     'SessionWorker.js',
     'TabStateCache.jsm',
+    'TextAndScrollData.jsm',
     'XPathGenerator.jsm',
     '_SessionFile.jsm',
 ]
 
 EXTRA_PP_JS_MODULES += [
     'SessionSaver.jsm',
     'SessionStore.jsm',
 ]
--- a/browser/devtools/app-manager/app-validator.js
+++ b/browser/devtools/app-manager/app-validator.js
@@ -47,16 +47,17 @@ AppValidator.prototype._getPackagedManif
   if (!manifestFile) {
     return null;
   }
   return Services.io.newFileURI(manifestFile).spec;
 };
 
 AppValidator.prototype._fetchManifest = function (manifestURL) {
   let deferred = promise.defer();
+  this.manifestURL = manifestURL;
 
   let req = new XMLHttpRequest();
   try {
     req.open("GET", manifestURL, true);
   } catch(e) {
     this.error(strings.formatStringFromName("validator.invalidManifestURL", [manifestURL], 1));
     deferred.resolve(null);
     return deferred.promise;
@@ -115,16 +116,78 @@ AppValidator.prototype.validateManifest 
 
   if (!manifest.icons || Object.keys(manifest.icons).length == 0) {
     this.warning(strings.GetStringFromName("validator.missIconsManifestProperty"));
   } else if (!manifest.icons["128"]) {
     this.warning(strings.GetStringFromName("validator.missIconMarketplace"));
   }
 }
 
+AppValidator.prototype._getOriginURL = function (manifest) {
+  if (this.project.type == "packaged") {
+    let manifestURL = Services.io.newURI(this.manifestURL, null, null);
+    return Services.io.newURI(".", null, manifestURL).spec;
+  } else if (this.project.type == "hosted") {
+    return Services.io.newURI(this.project.location, null, null).prePath;
+  }
+}
+
+AppValidator.prototype.validateLaunchPath = function (manifest) {
+  let deferred = promise.defer();
+  // The launch_path field has to start with a `/`
+  if (manifest.launch_path && manifest.launch_path[0] !== "/") {
+    this.error(strings.formatStringFromName("validator.nonAbsoluteLaunchPath", [manifest.launch_path], 1));
+    deferred.resolve();
+    return deferred.promise;
+  }
+  let origin = this._getOriginURL();
+  let path;
+  if (this.project.type == "packaged") {
+    path = "." + ( manifest.launch_path || "/index.html" );
+  } else if (this.project.type == "hosted") {
+    path = manifest.launch_path || "/";
+  }
+  let indexURL;
+  try {
+    indexURL = Services.io.newURI(path, null, Services.io.newURI(origin, null, null)).spec;
+  } catch(e) {
+    this.error(strings.formatStringFromName("validator.invalidLaunchPath", [origin + path], 1));
+    deferred.resolve();
+    return deferred.promise;
+  }
+
+  let req = new XMLHttpRequest();
+  try {
+    req.open("HEAD", indexURL, true);
+  } catch(e) {
+    this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
+    deferred.resolve();
+    return deferred.promise;
+  }
+  req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
+  req.onload = () => {
+    if (req.status >= 400)
+      this.error(strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [indexURL, req.status], 2));
+    deferred.resolve();
+  };
+  req.onerror = () => {
+    this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
+    deferred.resolve();
+  };
+
+  try {
+    req.send(null);
+  } catch(e) {
+    this.error(strings.formatStringFromName("validator.invalidLaunchPath", [indexURL], 1));
+    deferred.resolve();
+  }
+
+  return deferred.promise;
+}
+
 AppValidator.prototype.validateType = function (manifest) {
   let appType = manifest.type || "web";
   if (["web", "privileged", "certified"].indexOf(appType) === -1) {
     this.error(strings.formatStringFromName("validator.invalidAppType", [appType], 1));
   } else if (this.project.type == "hosted" &&
              ["certified", "privileged"].indexOf(appType) !== -1) {
     this.error(strings.formatStringFromName("validator.invalidHostedPriviledges", [appType], 1));
   }
@@ -139,14 +202,15 @@ AppValidator.prototype.validate = functi
   this.errors = [];
   this.warnings = [];
   return this._getManifest().
     then((function (manifest) {
       if (manifest) {
         this.manifest = manifest;
         this.validateManifest(manifest);
         this.validateType(manifest);
+        return this.validateLaunchPath(manifest);
       }
     }).bind(this));
 }
 
 exports.AppValidator = AppValidator;
 
--- a/browser/devtools/app-manager/test/chrome.ini
+++ b/browser/devtools/app-manager/test/chrome.ini
@@ -1,8 +1,11 @@
 [DEFAULT]
-support-files = hosted_app.manifest
+support-files =
+  hosted_app.manifest
+  validator/*
 
 [test_connection_store.html]
 [test_device_store.html]
 [test_projects_store.html]
 [test_remain_connected.html]
 [test_template.html]
+[test_app_validator.html]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/app-manager/test/test_app_validator.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+
+<html>
+
+  <head>
+    <meta charset="utf8">
+    <title></title>
+
+    <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
+    <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+  </head>
+
+  <body>
+
+    <script type="application/javascript;version=1.8">
+    const Cu = Components.utils;
+    const Cc = Components.classes;
+    const Ci = Components.interfaces;
+    Cu.import("resource://testing-common/httpd.js");
+    const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
+    const {require} = devtools;
+
+    const {AppValidator} = require("devtools/app-manager/app-validator");
+    const {Services} = Cu.import("resource://gre/modules/Services.jsm");
+    const nsFile = Components.Constructor("@mozilla.org/file/local;1",
+                                           "nsILocalFile", "initWithPath");
+    const cr = Cc["@mozilla.org/chrome/chrome-registry;1"]
+                 .getService(Ci.nsIChromeRegistry);
+    const strings = Services.strings.createBundle("chrome://browser/locale/devtools/app-manager.properties");
+    let httpserver, origin;
+
+    window.onload = function() {
+      SimpleTest.waitForExplicitFinish();
+
+      httpserver = new HttpServer();
+      httpserver.start(-1);
+      origin = "http://localhost:" + httpserver.identity.primaryPort + "/";
+
+      next();
+    }
+
+    function createHosted(path) {
+      let dirPath = getTestFilePath("validator/" + path);
+      httpserver.registerDirectory("/", nsFile(dirPath));
+      return new AppValidator({
+        type: "hosted",
+        location: origin + "/manifest.webapp"
+      });
+    }
+
+    function createPackaged(path) {
+      let dirPath = getTestFilePath("validator/" + path);
+      return new AppValidator({
+        type: "packaged",
+        location: dirPath
+      });
+    }
+
+    function next() {
+      let test = tests.shift();
+      if (test) {
+        try {
+          test();
+        } catch(e) {
+          console.error("exception", String(e), e, e.stack);
+        }
+      } else {
+        httpserver.stop(function() {
+          SimpleTest.finish();
+        });
+      }
+    }
+
+    let tests =  [
+      // Test a 100% valid example
+      function () {
+        let validator = createHosted("valid");
+        validator.validate().then(() => {
+            is(validator.errors.length, 0, "valid app got no error");
+            is(validator.warnings.length, 0, "valid app got no warning");
+
+            next();
+          });
+      },
+
+      function () {
+        let validator = createPackaged("valid");
+        validator.validate().then(() => {
+            is(validator.errors.length, 0, "valid packaged app got no error");
+            is(validator.warnings.length, 0, "valid packaged app got no warning");
+
+            next();
+          });
+      },
+
+      // Test a launch path that returns a 404
+      function () {
+        let validator = createHosted("wrong-launch-path");
+        validator.validate().then(() => {
+            is(validator.errors.length, 1, "app with non-existant launch path got an error");
+            is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPathBadHttpCode", [origin + "wrong-path.html", 404], 2),
+               "with the right error message");
+            is(validator.warnings.length, 0, "but no warning");
+            next();
+          });
+      },
+      function () {
+        let validator = createPackaged("wrong-launch-path");
+        validator.validate().then(() => {
+            is(validator.errors.length, 1, "app with wrong path got an error");
+            let file = nsFile(validator.project.location);
+            file.append("wrong-path.html");
+            let url = Services.io.newFileURI(file);
+            is(validator.errors[0], strings.formatStringFromName("validator.invalidLaunchPath", [url.spec], 1),
+               "with the expected message");
+            is(validator.warnings.length, 0, "but no warning");
+
+            next();
+          });
+      },
+
+      // Test when using a non-absolute path for launch_path
+      function () {
+        let validator = createHosted("non-absolute-path");
+        validator.validate().then(() => {
+            is(validator.errors.length, 1, "app with non absolute path got an error");
+            is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"], 1),
+               "with expected message");
+            is(validator.warnings.length, 0, "but no warning");
+            next();
+          });
+      },
+      function () {
+        let validator = createPackaged("non-absolute-path");
+        validator.validate().then(() => {
+            is(validator.errors.length, 1, "app with non absolute path got an error");
+            is(validator.errors[0], strings.formatStringFromName("validator.nonAbsoluteLaunchPath", ["non-absolute.html"], 1),
+               "with expected message");
+            is(validator.warnings.length, 0, "but no warning");
+            next();
+          });
+      },
+    ];
+
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/app-manager/test/validator/non-absolute-path/manifest.webapp
@@ -0,0 +1,7 @@
+{
+  "name": "non-absolute path",
+  "icons": {
+    "128": "/icon.png"
+  },
+  "launch_path": "non-absolute.html"
+}
new file mode 100644
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/browser/devtools/app-manager/test/validator/valid/manifest.webapp
@@ -0,0 +1,7 @@
+{
+  "name": "valid",
+  "launch_path": "/home.html",
+  "icons": {
+    "128": "/icon.png"
+  }
+}
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/browser/devtools/app-manager/test/validator/wrong-launch-path/manifest.webapp
@@ -0,0 +1,7 @@
+{
+  "name": "valid",
+  "launch_path": "/wrong-path.html",
+  "icons": {
+    "128": "/icon.png"
+  }
+}
--- a/browser/devtools/app-manager/webapps-store.js
+++ b/browser/devtools/app-manager/webapps-store.js
@@ -253,16 +253,20 @@ WebappsStore.prototype = {
       }
 
       request.type = "getIconAsDataURL";
       client.request(request, (res) => {
         if (res.url) {
           proxifiedApp.iconURL = res.url;
         }
       });
+
+      // This app may have been running while being installed, so check the list
+      // of running apps again to get the right answer.
+      this._getRunningApps();
     });
   },
 
   _onAppUninstall: function(manifest) {
     this.object.all = this.object.all.filter((app) => {
       return (app.manifestURL != manifest);
     });
   },
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -65,16 +65,19 @@ const EVENTS = {
   GLOBAL_SEARCH_MATCH_NOT_FOUND: "Debugger:GlobalSearch:MatchNotFound",
 
   // After the stackframes are cleared and debugger won't pause anymore.
   AFTER_FRAMES_CLEARED: "Debugger:AfterFramesCleared",
 
   // When the options popup is showing or hiding.
   OPTIONS_POPUP_SHOWING: "Debugger:OptionsPopupShowing",
   OPTIONS_POPUP_HIDDEN: "Debugger:OptionsPopupHidden",
+
+  // When the widgets layout has been changed.
+  LAYOUT_CHANGED: "Debugger:LayoutChanged"
 };
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
 let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
 Cu.import("resource:///modules/devtools/shared/event-emitter.js");
 Cu.import("resource:///modules/devtools/sourceeditor/source-editor.jsm");
@@ -272,35 +275,35 @@ let DebuggerController = {
    *        Packet type.
    * @param object aPacket
    *        Packet received from the server.
    */
   _onTabNavigated: function(aType, aPacket) {
     switch (aType) {
       case "will-navigate": {
         // Reset UI.
-        DebuggerView._handleTabNavigation();
+        DebuggerView.handleTabNavigation();
 
         // Discard all the cached sources *before* the target starts navigating.
         // Sources may be fetched during navigation, in which case we don't
         // want to hang on to the old source contents.
         DebuggerController.SourceScripts.clearCache();
         DebuggerController.Parser.clearCache();
         SourceUtils.clearCache();
 
         // Prevent performing any actions that were scheduled before navigation.
         clearNamedTimeout("new-source");
         clearNamedTimeout("event-breakpoints-update");
         clearNamedTimeout("event-listeners-fetch");
         break;
       }
       case "navigate": {
-        this.ThreadState._handleTabNavigation();
-        this.StackFrames._handleTabNavigation();
-        this.SourceScripts._handleTabNavigation();
+        this.ThreadState.handleTabNavigation();
+        this.StackFrames.handleTabNavigation();
+        this.SourceScripts.handleTabNavigation();
         break;
       }
     }
   },
 
   /**
    * Called when the debugged tab is closed.
    */
@@ -396,18 +399,18 @@ let DebuggerController = {
       if (aResponse.error) {
         let msg = "Couldn't reconfigure thread: " + aResponse.message;
         Cu.reportError(msg);
         dumpn(msg);
         return;
       }
 
       // Reset the view and fetch all the sources again.
-      DebuggerView._handleTabNavigation();
-      this.SourceScripts._handleTabNavigation();
+      DebuggerView.handleTabNavigation();
+      this.SourceScripts.handleTabNavigation();
 
       // Update the stack frame list.
       this.activeThread._clearFrames();
       this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
     });
   },
 
   /**
@@ -459,17 +462,17 @@ ThreadState.prototype = {
    * Connect to the current thread client.
    */
   connect: function() {
     dumpn("ThreadState is connecting...");
     this.activeThread.addListener("paused", this._update);
     this.activeThread.addListener("resumed", this._update);
     this.activeThread.pauseOnExceptions(Prefs.pauseOnExceptions,
                                         Prefs.ignoreCaughtExceptions);
-    this._handleTabNavigation();
+    this.handleTabNavigation();
   },
 
   /**
    * Disconnect from the client.
    */
   disconnect: function() {
     if (!this.activeThread) {
       return;
@@ -477,17 +480,17 @@ ThreadState.prototype = {
     dumpn("ThreadState is disconnecting...");
     this.activeThread.removeListener("paused", this._update);
     this.activeThread.removeListener("resumed", this._update);
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
-  _handleTabNavigation: function() {
+  handleTabNavigation: function() {
     if (!this.activeThread) {
       return;
     }
     dumpn("Handling tab navigation in the ThreadState");
     this._update();
   },
 
   /**
@@ -533,17 +536,17 @@ StackFrames.prototype = {
    */
   connect: function() {
     dumpn("StackFrames is connecting...");
     this.activeThread.addListener("paused", this._onPaused);
     this.activeThread.addListener("resumed", this._onResumed);
     this.activeThread.addListener("framesadded", this._onFrames);
     this.activeThread.addListener("framescleared", this._onFramesCleared);
     this.activeThread.addListener("blackboxchange", this._onBlackBoxChange);
-    this._handleTabNavigation();
+    this.handleTabNavigation();
   },
 
   /**
    * Disconnect from the client.
    */
   disconnect: function() {
     if (!this.activeThread) {
       return;
@@ -554,17 +557,17 @@ StackFrames.prototype = {
     this.activeThread.removeListener("framesadded", this._onFrames);
     this.activeThread.removeListener("framescleared", this._onFramesCleared);
     this.activeThread.removeListener("blackboxchange", this._onBlackBoxChange);
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
-  _handleTabNavigation: function() {
+  handleTabNavigation: function() {
     dumpn("Handling tab navigation in the StackFrames");
     // Nothing to do here yet.
   },
 
   /**
    * Handler for the thread client's paused notification.
    *
    * @param string aEvent
@@ -1002,17 +1005,17 @@ SourceScripts.prototype = {
   /**
    * Connect to the current thread client.
    */
   connect: function() {
     dumpn("SourceScripts is connecting...");
     this.debuggerClient.addListener("newGlobal", this._onNewGlobal);
     this.debuggerClient.addListener("newSource", this._onNewSource);
     this.activeThread.addListener("blackboxchange", this._onBlackBoxChange);
-    this._handleTabNavigation();
+    this.handleTabNavigation();
   },
 
   /**
    * Disconnect from the client.
    */
   disconnect: function() {
     if (!this.activeThread) {
       return;
@@ -1028,17 +1031,17 @@ SourceScripts.prototype = {
    */
   clearCache: function() {
     this._cache.clear();
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
-  _handleTabNavigation: function() {
+  handleTabNavigation: function() {
     if (!this.activeThread) {
       return;
     }
     dumpn("Handling tab navigation in the SourceScripts");
 
     // Retrieve the list of script sources known to the server from before
     // the client was ready to handle "newSource" notifications.
     this.activeThread.getSources(this._onSourcesAdded);
@@ -1897,16 +1900,19 @@ DebuggerController.Breakpoints.DOM = new
 
 /**
  * Export some properties to the global scope for easier access.
  */
 Object.defineProperties(window, {
   "gTarget": {
     get: function() DebuggerController._target
   },
+  "gHostType": {
+    get: function() DebuggerView._hostType
+  },
   "gClient": {
     get: function() DebuggerController.client
   },
   "gThreadClient": {
     get: function() DebuggerController.activeThread
   },
   "gCallStackPageSize": {
     get: function() CALL_STACK_PAGE_SIZE
--- a/browser/devtools/debugger/debugger-panel.js
+++ b/browser/devtools/debugger/debugger-panel.js
@@ -11,18 +11,20 @@ const EventEmitter = require("devtools/s
 
 function DebuggerPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
   this._destroyer = null;
 
   this._view = this.panelWin.DebuggerView;
   this._controller = this.panelWin.DebuggerController;
+  this._view._hostType = this._toolbox.hostType;
   this._controller._target = this.target;
 
+  this.handleHostChanged = this.handleHostChanged.bind(this);
   this.highlightWhenPaused = this.highlightWhenPaused.bind(this);
   this.unhighlightWhenResumed = this.unhighlightWhenResumed.bind(this);
 
   EventEmitter.decorate(this);
 };
 
 exports.DebuggerPanel = DebuggerPanel;
 
@@ -42,16 +44,17 @@ DebuggerPanel.prototype = {
     } else {
       targetPromise = promise.resolve(this.target);
     }
 
     return targetPromise
       .then(() => this._controller.startupDebugger())
       .then(() => this._controller.connect())
       .then(() => {
+        this._toolbox.on("host-changed", this.handleHostChanged);
         this.target.on("thread-paused", this.highlightWhenPaused);
         this.target.on("thread-resumed", this.unhighlightWhenResumed);
         this.isReady = true;
         this.emit("ready");
         return this;
       })
       .then(null, function onError(aReason) {
         Cu.reportError("DebuggerPanel open failed. " +
@@ -82,16 +85,20 @@ DebuggerPanel.prototype = {
   addBreakpoint: function(aLocation, aOptions) {
     return this._controller.Breakpoints.addBreakpoint(aLocation, aOptions);
   },
 
   removeBreakpoint: function(aLocation) {
     return this._controller.Breakpoints.removeBreakpoint(aLocation);
   },
 
+  handleHostChanged: function() {
+    this._view.handleHostChanged(this._toolbox.hostType);
+  },
+
   highlightWhenPaused: function() {
     this._toolbox.highlightTool("jsdebugger");
 
     // Also raise the toolbox window if it is undocked or select the
     // corresponding tab when toolbox is docked.
     this._toolbox.raise();
   },
 
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -105,47 +105,53 @@ let DebuggerView = {
   },
 
   /**
    * Initializes the UI for all the displayed panes.
    */
   _initializePanes: function() {
     dumpn("Initializing the DebuggerView panes");
 
+    this._body = document.getElementById("body");
+    this._editorDeck = document.getElementById("editor-deck");
     this._sourcesPane = document.getElementById("sources-pane");
     this._instrumentsPane = document.getElementById("instruments-pane");
     this._instrumentsPaneToggleButton = document.getElementById("instruments-pane-toggle");
 
     this.showEditor = this.showEditor.bind(this);
     this.showBlackBoxMessage = this.showBlackBoxMessage.bind(this);
     this.showProgressBar = this.showProgressBar.bind(this);
     this.maybeShowBlackBoxMessage = this.maybeShowBlackBoxMessage.bind(this);
-    this._editorDeck = document.getElementById("editor-deck");
 
     this._onTabSelect = this._onInstrumentsPaneTabSelect.bind(this);
     this._instrumentsPane.tabpanels.addEventListener("select", this._onTabSelect);
 
     this._collapsePaneString = L10N.getStr("collapsePanes");
     this._expandPaneString = L10N.getStr("expandPanes");
 
     this._sourcesPane.setAttribute("width", Prefs.sourcesWidth);
     this._instrumentsPane.setAttribute("width", Prefs.instrumentsWidth);
     this.toggleInstrumentsPane({ visible: Prefs.panesVisibleOnStartup });
+
+    // Side hosts requires a different arrangement of the debugger widgets.
+    if (gHostType == "side") {
+      this.handleHostChanged(gHostType);
+    }
   },
 
   /**
    * Destroys the UI for all the displayed panes.
    */
   _destroyPanes: function() {
     dumpn("Destroying the DebuggerView panes");
 
-    Prefs.sourcesWidth = this._sourcesPane.getAttribute("width");
-    Prefs.instrumentsWidth = this._instrumentsPane.getAttribute("width");
-
-    this._instrumentsPane.tabpanels.removeEventListener("select", this._onTabSelect);
+    if (gHostType != "side") {
+      Prefs.sourcesWidth = this._sourcesPane.getAttribute("width");
+      Prefs.instrumentsWidth = this._instrumentsPane.getAttribute("width");
+    }
 
     this._sourcesPane = null;
     this._instrumentsPane = null;
     this._instrumentsPaneToggleButton = null;
   },
 
   /**
    * Initializes the VariablesView instance and attaches a controller.
@@ -512,19 +518,78 @@ let DebuggerView = {
    */
   _onInstrumentsPaneTabSelect: function() {
     if (this._instrumentsPane.selectedTab.id == "events-tab") {
       DebuggerController.Breakpoints.DOM.scheduleEventListenersFetch();
     }
   },
 
   /**
+   * Handles a host change event issued by the parent toolbox.
+   *
+   * @param string aType
+   *        The host type, either "bottom", "side" or "window".
+   */
+  handleHostChanged: function(aType) {
+    let newLayout = "";
+
+    if (aType == "side") {
+      newLayout = "vertical";
+      this._enterVerticalLayout();
+    } else {
+      newLayout = "horizontal";
+      this._enterHorizontalLayout();
+    }
+
+    this._hostType = aType;
+    this._body.setAttribute("layout", newLayout);
+    window.emit(EVENTS.LAYOUT_CHANGED, newLayout);
+  },
+
+  /**
+   * Switches the debugger widgets to a horizontal layout.
+   */
+  _enterVerticalLayout: function() {
+    let normContainer = document.getElementById("debugger-widgets");
+    let vertContainer = document.getElementById("vertical-layout-panes-container");
+
+    // Move the soruces and instruments panes in a different container.
+    let splitter = document.getElementById("sources-and-instruments-splitter");
+    vertContainer.insertBefore(this._sourcesPane, splitter);
+    vertContainer.appendChild(this._instrumentsPane);
+
+    // Make sure the vertical layout container's height doesn't repeatedly
+    // grow or shrink based on the displayed sources, variables etc.
+    vertContainer.setAttribute("height",
+      vertContainer.getBoundingClientRect().height);
+  },
+
+  /**
+   * Switches the debugger widgets to a vertical layout.
+   */
+  _enterHorizontalLayout: function() {
+    let normContainer = document.getElementById("debugger-widgets");
+    let vertContainer = document.getElementById("vertical-layout-panes-container");
+
+    // The sources and instruments pane need to be inserted at their
+    // previous locations in their normal container.
+    let splitter = document.getElementById("sources-and-editor-splitter");
+    normContainer.insertBefore(this._sourcesPane, splitter);
+    normContainer.appendChild(this._instrumentsPane);
+
+    // Revert to the preferred sources and instruments widths, because
+    // they flexed in the vertical layout.
+    this._sourcesPane.setAttribute("width", Prefs.sourcesWidth);
+    this._instrumentsPane.setAttribute("width", Prefs.instrumentsWidth);
+  },
+
+  /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
-  _handleTabNavigation: function() {
+  handleTabNavigation: function() {
     dumpn("Handling tab navigation in the DebuggerView");
 
     this.Filtering.clearSearch();
     this.FilteredSources.clearView();
     this.FilteredFunctions.clearView();
     this.GlobalSearch.clearView();
     this.ChromeGlobals.empty();
     this.StackFrames.empty();
@@ -552,22 +617,23 @@ let DebuggerView = {
   StackFrames: null,
   Sources: null,
   Variables: null,
   WatchExpressions: null,
   EventListeners: null,
   editor: null,
   _editorSource: {},
   _loadingText: "",
+  _body: null,
+  _editorDeck: null,
   _sourcesPane: null,
   _instrumentsPane: null,
   _instrumentsPaneToggleButton: null,
   _collapsePaneString: "",
-  _expandPaneString: "",
-  _editorDeck: null,
+  _expandPaneString: ""
 };
 
 /**
  * A stacked list of items, compatible with WidgetMethods instances, used for
  * displaying views like the watch expressions, filtering or search results etc.
  *
  * You should never need to access these methods directly, use the wrapped
  * WidgetMethods instead.
--- a/browser/devtools/debugger/debugger.css
+++ b/browser/devtools/debugger/debugger.css
@@ -21,8 +21,36 @@
   overflow-y: auto;
 }
 
 /* Toolbar controls */
 
 .devtools-toolbarbutton:not([label]) > .toolbarbutton-text {
   display: none;
 }
+
+/* Horizontal vs. vertical layout */
+
+#body[layout=vertical] #debugger-widgets {
+  -moz-box-orient: vertical;
+}
+
+#body[layout=vertical] #sources-pane {
+  -moz-box-flex: 1;
+}
+
+#body[layout=vertical] #instruments-pane {
+  -moz-box-flex: 2;
+}
+
+#body[layout=vertical] #instruments-pane-toggle {
+  display: none;
+}
+
+#body[layout=vertical] #sources-and-editor-splitter,
+#body[layout=vertical] #editor-and-instruments-splitter {
+  display: none;
+}
+
+#body[layout=horizontal] #vertical-layout-splitter,
+#body[layout=horizontal] #vertical-layout-panes-container {
+  display: none;
+}
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -278,18 +278,19 @@
          modifiers="accel shift"
          command="addWatchExpressionCommand"/>
     <key id="removeAllWatchExpressionsKey"
          key="&debuggerUI.removeAllWatch.key;"
          modifiers="accel alt"
          command="removeAllWatchExpressionsCommand"/>
   </keyset>
 
-  <vbox id="body" flex="1">
-    <toolbar class="devtools-toolbar">
+  <vbox id="body" layout="horizontal" flex="1">
+    <toolbar id="debugger-toolbar"
+             class="devtools-toolbar">
       <hbox id="debugger-controls">
         <toolbarbutton id="resume"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-over"
                        class="devtools-toolbarbutton"
                        tabindex="0"/>
         <toolbarbutton id="step-in"
@@ -310,72 +311,78 @@
                      tooltiptext="&debuggerUI.panesButton.tooltip;"
                      tabindex="0"/>
       <toolbarbutton id="debugger-options"
                      class="devtools-option-toolbarbutton"
                      tooltiptext="&debuggerUI.optsButton.tooltip;"
                      popup="debuggerPrefsContextMenu"
                      tabindex="0"/>
     </toolbar>
-    <vbox flex="1">
-      <scrollbox id="globalsearch" orient="vertical" hidden="true"/>
-      <splitter class="devtools-horizontal-splitter" hidden="true"/>
-      <hbox flex="1">
-        <vbox id="sources-container">
-          <vbox id="sources-pane" flex="1">
-            <vbox id="sources" flex="1"/>
-          </vbox>
-          <toolbar id="sources-toolbar" class="devtools-toolbar">
-            <toolbarbutton id="pretty-print"
-                           label="{}"
-                           tooltiptext="&debuggerUI.sources.prettyPrint;"
-                           class="devtools-toolbarbutton devtools-monospace"
-                           command="prettyPrintCommand"
-                           hidden="true"/>
-          </toolbar>
+    <scrollbox id="globalsearch" orient="vertical" hidden="true"/>
+    <splitter class="devtools-horizontal-splitter" hidden="true"/>
+    <hbox id="debugger-widgets" flex="1">
+      <vbox id="sources-pane">
+        <vbox id="sources" flex="1"/>
+        <toolbar id="sources-toolbar" class="devtools-toolbar">
+          <toolbarbutton id="pretty-print"
+                         label="{}"
+                         tooltiptext="&debuggerUI.sources.prettyPrint;"
+                         class="devtools-toolbarbutton devtools-monospace"
+                         command="prettyPrintCommand"
+                         hidden="true"/>
+        </toolbar>
+      </vbox>
+      <splitter id="sources-and-editor-splitter"
+                class="devtools-side-splitter"/>
+      <deck id="editor-deck" flex="4">
+        <vbox id="editor"/>
+        <vbox id="black-boxed-message" align="center" pack="center">
+          <label id="black-boxed-message-label">
+            &debuggerUI.blackBoxMessage.label;
+          </label>
+          <button id="black-boxed-message-button"
+                  class="devtools-toolbarbutton"
+                  label="&debuggerUI.blackBoxMessage.unBlackBoxButton;"
+                  image="chrome://browser/skin/devtools/blackBoxMessageEye.png"
+                  command="unBlackBoxCommand"/>
         </vbox>
-        <splitter class="devtools-side-splitter"/>
-        <deck id="editor-deck" flex="1" selectedIndex="0">
-          <vbox id="editor"/>
-          <vbox id="black-boxed-message" align="center">
-            <label id="black-boxed-message-label">
-              &debuggerUI.blackBoxMessage.label;
-            </label>
-            <button id="black-boxed-message-button"
-                    class="devtools-toolbarbutton"
-                    label="&debuggerUI.blackBoxMessage.unBlackBoxButton;"
-                    image="chrome://browser/skin/devtools/blackBoxMessageEye.png"
-                    command="unBlackBoxCommand"/>
-          </vbox>
-          <vbox id="source-progress-container" align="center" pack="center">
-            <progressmeter id="source-progress"
-                           mode="undetermined"/>
-          </vbox>
-        </deck>
-        <splitter class="devtools-side-splitter"/>
-        <tabbox id="instruments-pane"
-                class="devtools-sidebar-tabs"
-                hidden="true">
-          <tabs>
-            <tab id="variables-tab" label="&debuggerUI.tabs.variables;"/>
-            <tab id="events-tab" label="&debuggerUI.tabs.events;"/>
-          </tabs>
-          <tabpanels flex="1">
-            <tabpanel id="variables-tabpanel">
-              <vbox id="expressions"/>
-              <splitter class="devtools-horizontal-splitter"/>
-              <vbox id="variables" flex="1"/>
-            </tabpanel>
-            <tabpanel id="events-tabpanel">
-              <vbox id="event-listeners" flex="1"/>
-            </tabpanel>
-          </tabpanels>
-        </tabbox>
+        <vbox id="source-progress-container" align="center" pack="center">
+          <progressmeter id="source-progress"
+                         mode="undetermined"/>
+        </vbox>
+      </deck>
+      <splitter id="editor-and-instruments-splitter"
+                class="devtools-side-splitter"/>
+      <tabbox id="instruments-pane"
+              class="devtools-sidebar-tabs"
+              hidden="true">
+        <tabs>
+          <tab id="variables-tab" label="&debuggerUI.tabs.variables;"/>
+          <tab id="events-tab" label="&debuggerUI.tabs.events;"/>
+        </tabs>
+        <tabpanels flex="1">
+          <tabpanel id="variables-tabpanel">
+            <vbox id="expressions"/>
+            <splitter class="devtools-horizontal-splitter"/>
+            <vbox id="variables" flex="1"/>
+          </tabpanel>
+          <tabpanel id="events-tabpanel">
+            <vbox id="event-listeners" flex="1"/>
+          </tabpanel>
+        </tabpanels>
+      </tabbox>
+      <splitter id="vertical-layout-splitter"
+                class="devtools-horizontal-splitter"/>
+      <hbox id="vertical-layout-panes-container">
+        <splitter id="sources-and-instruments-splitter"
+                  class="devtools-side-splitter"/>
+        <!-- The sources-pane and instruments-pane will be moved in this
+             container if the toolbox's host requires it. -->
       </hbox>
-    </vbox>
+    </hbox>
   </vbox>
 
   <panel id="searchbox-help-panel"
          level="top"
          type="arrow"
          position="before_start"
          noautofocus="true"
          consumeoutsideclicks="false">
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -91,16 +91,17 @@ support-files =
 [browser_dbg_cmd-dbg.js]
 [browser_dbg_conditional-breakpoints-01.js]
 [browser_dbg_conditional-breakpoints-02.js]
 [browser_dbg_debugger-statement.js]
 [browser_dbg_editor-contextmenu.js]
 [browser_dbg_editor-mode.js]
 [browser_dbg_function-display-name.js]
 [browser_dbg_globalactor.js]
+[browser_dbg_host-layout.js]
 [browser_dbg_iframes.js]
 [browser_dbg_instruments-pane-collapse.js]
 [browser_dbg_listaddons.js]
 [browser_dbg_listtabs-01.js]
 [browser_dbg_listtabs-02.js]
 [browser_dbg_location-changes-01-simple.js]
 [browser_dbg_location-changes-02-blank.js]
 [browser_dbg_location-changes-03-new.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_host-layout.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * This if the debugger's layout is correctly modified when the toolbox's
+ * host changes.
+ */
+
+let gDefaultHostType = Services.prefs.getCharPref("devtools.toolbox.host");
+
+function test() {
+  Task.spawn(function() {
+    yield testHosts(["bottom", "side", "window"], ["horizontal", "vertical", "horizontal"]);
+    yield testHosts(["side", "bottom", "side"], ["vertical", "horizontal", "vertical"]);
+    yield testHosts(["bottom", "side", "bottom"], ["horizontal", "vertical", "horizontal"]);
+    yield testHosts(["side", "window", "side"], ["vertical", "horizontal", "vertical"]);
+    yield testHosts(["window", "side", "window"], ["horizontal", "vertical", "horizontal"]);
+    finish();
+  });
+}
+
+function testHosts(aHostTypes, aLayoutTypes) {
+  let [firstHost, secondHost, thirdHost] = aHostTypes;
+  let [firstLayout, secondLayout, thirdLayout] = aLayoutTypes;
+
+  Services.prefs.setCharPref("devtools.toolbox.host", firstHost);
+
+  return Task.spawn(function() {
+    let [tab, debuggee, panel] = yield initDebugger("about:blank");
+    yield testHost(tab, debuggee, panel, firstHost, firstLayout);
+    yield switchAndTestHost(tab, debuggee, panel, secondHost, secondLayout);
+    yield switchAndTestHost(tab, debuggee, panel, thirdHost, thirdLayout);
+    yield teardown(panel);
+  });
+}
+
+function switchAndTestHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType) {
+  let gToolbox = aPanel._toolbox;
+  let gDebugger = aPanel.panelWin;
+
+  return Task.spawn(function() {
+    let layoutChanged = once(gDebugger, gDebugger.EVENTS.LAYOUT_CHANGED);
+    let hostChanged = gToolbox.switchHost(aHostType);
+
+    yield hostChanged;
+    ok(true, "The toolbox's host has changed.");
+
+    yield layoutChanged;
+    ok(true, "The debugger's layout has changed.");
+
+    yield testHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType);
+  });
+
+  function once(aTarget, aEvent) {
+    let deferred = promise.defer();
+    aTarget.once(aEvent, deferred.resolve);
+    return deferred.promise;
+  }
+}
+
+function testHost(aTab, aDebuggee, aPanel, aHostType, aLayoutType) {
+  let gDebugger = aPanel.panelWin;
+  let gView = gDebugger.DebuggerView;
+
+  is(gView._hostType, aHostType,
+    "The default host type should've been set on the panel window (1).");
+  is(gDebugger.gHostType, aHostType,
+    "The default host type should've been set on the panel window (2).");
+
+  is(gView._body.getAttribute("layout"), aLayoutType,
+    "The default host type is present as an attribute on the panel's body.");
+
+  if (aLayoutType == "horizontal") {
+    is(gView._sourcesPane.parentNode.id, "debugger-widgets",
+      "The sources pane's parent is correct for the horizontal layout.");
+    is(gView._instrumentsPane.parentNode.id, "debugger-widgets",
+      "The instruments pane's parent is correct for the horizontal layout.");
+  } else {
+    is(gView._sourcesPane.parentNode.id, "vertical-layout-panes-container",
+      "The sources pane's parent is correct for the vertical layout.");
+    is(gView._instrumentsPane.parentNode.id, "vertical-layout-panes-container",
+      "The instruments pane's parent is correct for the vertical layout.");
+  }
+
+  let widgets = gDebugger.document.getElementById("debugger-widgets").childNodes;
+  let panes = gDebugger.document.getElementById("vertical-layout-panes-container").childNodes;
+
+  if (aLayoutType == "horizontal") {
+    is(widgets.length, 7, // 2 panes, 1 editor, 3 splitters and a phantom box.
+      "Found the correct number of debugger widgets.");
+    is(panes.length, 1, // 1 lonely splitter in the phantom box.
+      "Found the correct number of debugger panes.");
+  } else {
+    is(widgets.length, 5, // 1 editor, 3 splitters and a phantom box.
+      "Found the correct number of debugger widgets.");
+    is(panes.length, 3, // 2 panes and 1 splitter in the phantom box.
+      "Found the correct number of debugger panes.");
+  }
+}
+
+registerCleanupFunction(function() {
+  Services.prefs.setCharPref("devtools.toolbox.host", gDefaultHostType);
+  gDefaultHostType = null;
+});
--- a/browser/devtools/framework/connect/connect.xhtml
+++ b/browser/devtools/framework/connect/connect.xhtml
@@ -40,11 +40,11 @@
       <p>&availableTabs;</p>
       <ul class="actors" id="tabActors"></ul>
       <p>&availableProcesses;</p>
       <ul class="actors" id="globalActors"></ul>
     </section>
     <section id="connecting">
       <p><img src="chrome://browser/skin/tabbrowser/loading.png"></img> &connecting;</p>
     </section>
-    <footer>&help2;</footer>
+    <footer>&remoteHelp;<a target='_' href='https://developer.mozilla.org/docs/Tools/Remote_Debugging'>&remoteDocumentation;</a>&remoteHelpSuffix;</footer>
   </body>
 </html>
--- a/browser/devtools/inspector/test/browser_inspector_changes.js
+++ b/browser/devtools/inspector/test/browser_inspector_changes.js
@@ -11,28 +11,16 @@ function test() {
 
   function createDocument()
   {
     doc.body.innerHTML = '<div id="testdiv">Test div!</div>';
     doc.title = "Inspector Change Test";
     openInspector(runInspectorTests);
   }
 
-
-  function getInspectorComputedProp(aName)
-  {
-    let computedview = inspector.sidebar.getWindowForTab("computedview").computedview.view;
-    for each (let view in computedview.propertyViews) {
-      if (view.name == aName) {
-        return view;
-      }
-    }
-    return null;
-  }
-
   function getInspectorRuleProp(aName)
   {
     let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
     let inlineStyles = ruleview._elementStyle.rules[0];
 
     for each (let prop in inlineStyles.textProps) {
       if (prop.name == aName) {
         return prop;
@@ -59,34 +47,34 @@ function test() {
     });
   }
 
   function computedStylePanelTests()
   {
     let computedview = inspector.sidebar.getWindowForTab("computedview").computedview;
     ok(computedview, "Style Panel has a cssHtmlTree");
 
-    let propView = getInspectorComputedProp("font-size");
-    is(propView.value, "10px", "Style inspector should be showing the correct font size.");
+    let fontSize = getComputedPropertyValue("font-size");
+    is(fontSize, "10px", "Style inspector should be showing the correct font size.");
 
     testDiv.style.cssText = "font-size: 15px; color: red;";
 
     // Wait until layout-change fires from mutation to skip earlier refresh event
     inspector.once("layout-change", () => {
       inspector.once("computed-view-refreshed", computedStylePanelAfterChange);
     });
   }
 
   function computedStylePanelAfterChange()
   {
-    let propView = getInspectorComputedProp("font-size");
-    is(propView.value, "15px", "Style inspector should be showing the new font size.");
+    let fontSize = getComputedPropertyValue("font-size");
+    is(fontSize, "15px", "Style inspector should be showing the new font size.");
 
-    let propView = getInspectorComputedProp("color");
-    is(propView.value, "#F00", "Style inspector should be showing the new color.");
+    let color = getComputedPropertyValue("color");
+    is(color, "#F00", "Style inspector should be showing the new color.");
 
     computedStylePanelNotActive();
   }
 
   function computedStylePanelNotActive()
   {
     // Tests changes made while the style panel is not active.
     inspector.sidebar.select("ruleview");
@@ -96,24 +84,24 @@ function test() {
     testDiv.style.textAlign = "center";
 
     inspector.once("computed-view-refreshed", computedStylePanelAfterSwitch);
     inspector.sidebar.select("computedview");
   }
 
   function computedStylePanelAfterSwitch()
   {
-    let propView = getInspectorComputedProp("font-size");
-    is(propView.value, "20px", "Style inspector should be showing the new font size.");
+    let fontSize = getComputedPropertyValue("font-size");
+    is(fontSize, "20px", "Style inspector should be showing the new font size.");
 
-    let propView = getInspectorComputedProp("color");
-    is(propView.value, "#00F", "Style inspector should be showing the new color.");
+    let color = getComputedPropertyValue("color");
+    is(color, "#00F", "Style inspector should be showing the new color.");
 
-    let propView = getInspectorComputedProp("text-align");
-    is(propView.value, "center", "Style inspector should be showing the new text align.");
+    let textAlign = getComputedPropertyValue("text-align");
+    is(textAlign, "center", "Style inspector should be showing the new text align.");
 
     rulePanelTests();
   }
 
   function rulePanelTests()
   {
     inspector.sidebar.select("ruleview");
     let ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview;
@@ -132,17 +120,17 @@ function test() {
   }
 
   function rulePanelAfterChange()
   {
     let propView = getInspectorRuleProp("text-align");
     is(propView.value, "right", "Style inspector should be showing the new text align.");
 
     let propView = getInspectorRuleProp("color");
-    is(propView.value, "#FAFAD2", "Style inspector should be showing the new color.")
+    is(propView.value, "lightgoldenrodyellow", "Style inspector should be showing the new color.")
 
     let propView = getInspectorRuleProp("font-size");
     is(propView.value, "3em", "Style inspector should be showing the new font size.");
 
     let propView = getInspectorRuleProp("text-transform");
     is(propView.value, "uppercase", "Style inspector should be showing the new text transform.");
 
     finishTest();
--- a/browser/devtools/inspector/test/head.js
+++ b/browser/devtools/inspector/test/head.js
@@ -105,16 +105,21 @@ function computedViewTree()
 
 function ruleView()
 {
   let sidebar = getActiveInspector().sidebar;
   let iframe = sidebar.tabbox.querySelector(".iframe-ruleview");
   return iframe.contentWindow.ruleView;
 }
 
+function getComputedView() {
+  let inspector = getActiveInspector();
+  return inspector.sidebar.getWindowForTab("computedview").computedview.view;
+}
+
 function synthesizeKeyFromKeyTag(aKeyId) {
   let key = document.getElementById(aKeyId);
   isnot(key, null, "Successfully retrieved the <key> node");
 
   let modifiersAttr = key.getAttribute("modifiers");
 
   let name = null;
 
@@ -164,8 +169,22 @@ function focusSearchBoxUsingShortcut(pan
   let searchBox = panelWin.document.getElementById("inspector-searchbox");
   searchBox.addEventListener("focus", function onFocus() {
     searchBox.removeEventListener("focus", onFocus, false);
     callback && callback();
   }, false);
   EventUtils.synthesizeKey(name, modifiers);
 }
 
+function getComputedPropertyValue(aName)
+{
+  let computedview = getComputedView();
+  let props = computedview.styleDocument.querySelectorAll(".property-view");
+
+  for (let prop of props) {
+    let name = prop.querySelector(".property-name");
+
+    if (name.textContent === aName) {
+      let value = prop.querySelector(".property-value");
+      return value.textContent;
+    }
+  }
+}
--- a/browser/devtools/markupview/markup-view.js
+++ b/browser/devtools/markupview/markup-view.js
@@ -13,16 +13,17 @@ const DEFAULT_MAX_CHILDREN = 100;
 const COLLAPSE_ATTRIBUTE_LENGTH = 120;
 const COLLAPSE_DATA_URL_REGEX = /^data.+base64/;
 const COLLAPSE_DATA_URL_LENGTH = 60;
 const CONTAINER_FLASHING_DURATION = 500;
 
 const {UndoStack} = require("devtools/shared/undo");
 const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
 const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
+const {OutputParser} = require("devtools/output-parser");
 const promise = require("sdk/core/promise");
 
 Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
 Cu.import("resource://gre/modules/devtools/Templater.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 loader.lazyGetter(this, "DOMParser", function() {
  return Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
@@ -50,16 +51,17 @@ loader.lazyGetter(this, "AutocompletePop
  *        An iframe in which the caller has kindly loaded markup-view.xhtml.
  */
 function MarkupView(aInspector, aFrame, aControllerWindow) {
   this._inspector = aInspector;
   this.walker = this._inspector.walker;
   this._frame = aFrame;
   this.doc = this._frame.contentDocument;
   this._elt = this.doc.querySelector("#root");
+  this._outputParser = new OutputParser();
 
   this.layoutHelpers = new LayoutHelpers(this.doc.defaultView);
 
   try {
     this.maxChildren = Services.prefs.getIntPref("devtools.markup.pagesize");
   } catch(ex) {
     this.maxChildren = DEFAULT_MAX_CHILDREN;
   }
@@ -781,16 +783,18 @@ MarkupView.prototype = {
     delete this.undo;
 
     this.popup.destroy();
     delete this.popup;
 
     this._frame.removeEventListener("focus", this._boundFocus, false);
     delete this._boundFocus;
 
+    delete this._outputParser;
+
     if (this._boundUpdatePreview) {
       this._frame.contentWindow.removeEventListener("scroll",
         this._boundUpdatePreview, true);
       delete this._boundUpdatePreview;
     }
 
     if (this._boundResizePreview) {
       this._frame.contentWindow.removeEventListener("resize",
@@ -1532,28 +1536,98 @@ ElementEditor.prototype = {
     // Remove the old version of this attribute from the DOM.
     let oldAttr = this.attrs[aAttr.name];
     if (oldAttr && oldAttr.parentNode) {
       oldAttr.parentNode.removeChild(oldAttr);
     }
 
     this.attrs[aAttr.name] = attr;
 
-    let collapsedValue;
-    if (aAttr.value.match(COLLAPSE_DATA_URL_REGEX)) {
-      collapsedValue = truncateString(aAttr.value, COLLAPSE_DATA_URL_LENGTH);
+    name.textContent = aAttr.name;
+
+    if (typeof aAttr.value !== "undefined") {
+      let outputParser = this.markup._outputParser;
+      let frag = outputParser.parseHTMLAttribute(aAttr.value);
+      frag = this._truncateFrag(frag);
+      val.appendChild(frag);
     }
-    else {
-      collapsedValue = truncateString(aAttr.value, COLLAPSE_ATTRIBUTE_LENGTH);
+
+    return attr;
+  },
+
+  /**
+   * We truncate HTML attributes to a text length defined by
+   * COLLAPSE_DATA_URL_LENGTH and COLLAPSE_ATTRIBUTE_LENGTH. Because we parse
+   * text into document fragments we need to process each fragment and truncate
+   * according to the fragment's textContent length.
+   *
+   * @param  {DocumentFragment} frag
+   *         The fragment to truncate.
+   * @return {[DocumentFragment]}
+   *         Truncated fragment.
+   */
+  _truncateFrag: function(frag) {
+    let chars = 0;
+    let text = frag.textContent;
+    let maxWidth = text.match(COLLAPSE_DATA_URL_REGEX) ?
+                            COLLAPSE_DATA_URL_LENGTH : COLLAPSE_ATTRIBUTE_LENGTH;
+    let overBy = text.length - maxWidth;
+    let children = frag.childNodes;
+    let croppedNode = null;
+
+    if (overBy <= 0) {
+      return frag;
     }
 
-    name.textContent = aAttr.name;
-    val.textContent = collapsedValue;
+    // For fragments containing only one single node we just need to truncate
+    // frag.textContent.
+    if (children.length === 1) {
+      let length = text.length;
+      let start = text.substr(0, maxWidth / 2);
+      let end = text.substr(length - maxWidth / 2, length - 1);
+
+      frag.textContent = start + "…" + end;
+      return frag;
+    }
+
+    // First maxWidth / 2 chars plus &hellip;
+    for (let i = 0; i < children.length; i++) {
+      let node = children[i];
+      let text = node.textContent;
 
-    return attr;
+      let numChars = text.length;
+      if (chars + numChars > maxWidth / 2) {
+        node.textContent = text.substr(0, chars + numChars - maxWidth / 2) + "…";
+        croppedNode = node;
+        break;
+      } else {
+        chars += numChars;
+      }
+    }
+
+    // Last maxWidth / two chars.
+    chars = 0;
+    for (let i = children.length - 1; i >= 0; i--) {
+      let node = children[i];
+      let text = node.textContent;
+
+      let numChars = text.length;
+      if (chars + numChars > maxWidth / 2) {
+        if (node !== croppedNode) {
+          node.parentNode.removeChild(node);
+          chars += numChars;
+        } else {
+          break;
+        }
+      } else {
+        chars += numChars;
+      }
+    }
+
+    return frag;
   },
 
   /**
    * Parse a user-entered attribute string and apply the resulting
    * attributes to the node.  This operation is undoable.
    *
    * @param string aValue the user-entered value.
    * @param Element aAttrNode the attribute editor that created this
--- a/browser/devtools/shared/test/browser_css_color.js
+++ b/browser/devtools/shared/test/browser_css_color.js
@@ -134,17 +134,17 @@ function testProcessCSSString() {
                  "background-color: transparent; " +
                  "border-top-color: rgba(0, 0, 255, 0.5);";
   let after = colorUtils.processCSSString(before);
 
   is(after, expected, "CSS string processed correctly");
 }
 
 function finishUp() {
-  Services = colorUtils.CssColor = Loader = null;
+  Services = colorUtils = Loader = null;
   gBrowser.removeCurrentTab();
   finish();
 }
 
 function getTestData() {
   return [
     {authored: "aliceblue", name: "aliceblue", hex: "#F0F8FF", hsl: "hsl(208, 100%, 97%)", rgb: "rgb(240, 248, 255)"},
     {authored: "antiquewhite", name: "antiquewhite", hex: "#FAEBD7", hsl: "hsl(34.286, 78%, 91%)", rgb: "rgb(250, 235, 215)"},
--- a/browser/devtools/shared/widgets/SideMenuWidget.jsm
+++ b/browser/devtools/shared/widgets/SideMenuWidget.jsm
@@ -56,17 +56,16 @@ this.SideMenuWidget = function SideMenuW
   this._list.setAttribute("theme", this._theme);
   this._list.setAttribute("with-arrows", this._showArrows);
   this._list.setAttribute("with-item-checkboxes", this._showItemCheckboxes);
   this._list.setAttribute("with-group-checkboxes", this._showGroupCheckboxes);
   this._list.setAttribute("tabindex", "0");
   this._list.addEventListener("keypress", e => this.emit("keyPress", e), false);
   this._list.addEventListener("mousedown", e => this.emit("mousePress", e), false);
   this._parent.appendChild(this._list);
-  this._boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
 
   // Menu items can optionally be grouped.
   this._groupsByName = new Map(); // Can't use a WeakMap because keys are strings.
   this._orderedGroupElementsArray = [];
   this._orderedMenuElementsArray = [];
   this._itemsByElement = new Map();
 
   // This widget emits events that can be handled in a MenuContainer.
@@ -240,18 +239,19 @@ SideMenuWidget.prototype = {
    *        The element to make visible.
    */
   ensureElementIsVisible: function(aElement) {
     if (!aElement) {
       return;
     }
 
     // Ensure the element is visible but not scrolled horizontally.
-    this._boxObject.ensureElementIsVisible(aElement);
-    this._boxObject.scrollBy(-aElement.clientWidth, 0);
+    let boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+    boxObject.ensureElementIsVisible(aElement);
+    boxObject.scrollBy(-aElement.clientWidth, 0);
   },
 
   /**
    * Shows all the groups, even the ones with no visible children.
    */
   showEmptyGroups: function() {
     for (let group of this._orderedGroupElementsArray) {
       group.hidden = false;
@@ -427,17 +427,16 @@ SideMenuWidget.prototype = {
   window: null,
   document: null,
   _theme: "",
   _showArrows: false,
   _showItemCheckboxes: false,
   _showGroupCheckboxes: false,
   _parent: null,
   _list: null,
-  _boxObject: null,
   _selectedItem: null,
   _groupsByName: null,
   _orderedGroupElementsArray: null,
   _orderedMenuElementsArray: null,
   _itemsByElement: null,
   _ensureVisibleTimeout: null,
   _noticeTextContainer: null,
   _noticeTextNode: null,
--- a/browser/devtools/styleinspector/computed-view.js
+++ b/browser/devtools/styleinspector/computed-view.js
@@ -6,17 +6,18 @@
 
 const {Cc, Ci, Cu} = require("chrome");
 
 let ToolDefinitions = require("main").Tools;
 let {CssLogic} = require("devtools/styleinspector/css-logic");
 let {ELEMENT_STYLE} = require("devtools/server/actors/styles");
 let promise = require("sdk/core/promise");
 let {EventEmitter} = require("devtools/shared/event-emitter");
-let {colorUtils} = require("devtools/css-color");
+
+const {OutputParser} = require("devtools/output-parser");
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PluralForm.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/devtools/Templater.jsm");
 
 let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 
@@ -129,16 +130,18 @@ UpdateProcess.prototype = {
 function CssHtmlTree(aStyleInspector, aPageStyle)
 {
   this.styleWindow = aStyleInspector.window;
   this.styleDocument = aStyleInspector.window.document;
   this.styleInspector = aStyleInspector;
   this.pageStyle = aPageStyle;
   this.propertyViews = [];
 
+  this._outputParser = new OutputParser();
+
   let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
     getService(Ci.nsIXULChromeRegistry);
   this.getRTLAttr = chromeReg.isLocaleRTL("global") ? "rtl" : "ltr";
 
   // Create bound methods.
   this.focusWindow = this.focusWindow.bind(this);
   this._onContextMenu = this._onContextMenu.bind(this);
   this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
@@ -608,16 +611,18 @@ CssHtmlTree.prototype = {
 
   /**
    * Destructor for CssHtmlTree.
    */
   destroy: function CssHtmlTree_destroy()
   {
     delete this.viewedElement;
 
+    delete this._outputParser;
+
     // Remove event listeners
     this.includeBrowserStylesCheckbox.removeEventListener("command",
       this.includeBrowserStylesChanged);
     this.searchField.removeEventListener("command", this.filterChanged);
     gDevTools.off("pref-changed", this._handlePrefChange);
 
     // Cancel tree construction
     if (this._createViewsProcess) {
@@ -671,17 +676,17 @@ CssHtmlTree.prototype = {
 function PropertyInfo(aTree, aName) {
   this.tree = aTree;
   this.name = aName;
 }
 PropertyInfo.prototype = {
   get value() {
     if (this.tree._computed) {
       let value = this.tree._computed[this.name].value;
-      return colorUtils.processCSSString(value);
+      return value;
     }
   }
 };
 
 function createMenuItem(aMenu, aAttributes)
 {
   let item = aMenu.ownerDocument.createElementNS(XUL_NS, "menuitem");
 
@@ -867,17 +872,16 @@ PropertyView.prototype = {
 
     // Build the style value element
     this.valueNode = doc.createElementNS(HTML_NS, "div");
     this.valueNode.setAttribute("class", "property-value theme-fg-color1");
     // Reset its tabindex attribute otherwise, if an ellipsis is applied
     // it will be reachable via TABing
     this.valueNode.setAttribute("tabindex", "");
     this.valueNode.setAttribute("dir", "ltr");
-    this.valueNode.textContent = this.valueNode.title = this.value;
     // Make it hand over the focus to the container
     this.valueNode.addEventListener("click", this.onFocus, false);
     this.element.appendChild(this.valueNode);
 
     return this.element;
   },
 
   buildSelectorContainer: function PropertyView_buildSelectorContainer()
@@ -909,17 +913,26 @@ PropertyView.prototype = {
       this.valueNode.textContent = this.valueNode.title = "";
       this.matchedSelectorsContainer.parentNode.hidden = true;
       this.matchedSelectorsContainer.textContent = "";
       this.matchedExpander.removeAttribute("open");
       return;
     }
 
     this.tree.numVisibleProperties++;
-    this.valueNode.textContent = this.valueNode.title = this.propertyInfo.value;
+
+    let outputParser = this.tree._outputParser;
+    let frag = outputParser.parseCssProperty(this.propertyInfo.name,
+      this.propertyInfo.value,
+      {
+        colorSwatchClass: "computedview-colorswatch"
+      });
+    this.valueNode.innerHTML = "";
+    this.valueNode.appendChild(frag);
+
     this.refreshMatchedSelectors();
   },
 
   /**
    * Refresh the panel matched rules.
    */
   refreshMatchedSelectors: function PropertyView_refreshMatchedSelectors()
   {
@@ -1109,18 +1122,28 @@ SelectorView.prototype = {
   get sourceText()
   {
     return this.selectorInfo.sourceText;
   },
 
 
   get value()
   {
-    let val = this.selectorInfo.value;
-    return colorUtils.processCSSString(val);
+    return this.selectorInfo.value;
+  },
+
+  get outputFragment()
+  {
+    let outputParser = this.tree._outputParser;
+    let frag = outputParser.parseCssProperty(
+      this.selectorInfo.name,
+      this.selectorInfo.value, {
+      colorSwatchClass: "computedview-colorswatch"
+    });
+    return frag;
   },
 
   maybeOpenStyleEditor: function(aEvent)
   {
     let keyEvent = Ci.nsIDOMKeyEvent;
     if (aEvent.keyCode == keyEvent.DOM_VK_RETURN) {
       this.openStyleEditor();
     }
--- a/browser/devtools/styleinspector/computedview.xhtml
+++ b/browser/devtools/styleinspector/computedview.xhtml
@@ -98,17 +98,17 @@
               <a target="_blank" class="link theme-link"
                   onclick="${selector.openStyleEditor}"
                   onkeydown="${selector.maybeOpenStyleEditor}"
                   title="${selector.href}"
                   tabindex="0">${selector.source}</a>
             </span>
             <span dir="ltr" class="rule-text ${selector.statusClass} theme-fg-color3" title="${selector.statusText}">
               ${selector.sourceText}
-              <span class="other-property-value theme-fg-color1">${selector.value}</span>
+              <span class="other-property-value theme-fg-color1">${selector.outputFragment}</span>
             </span>
           </p>
         </loop>
       </div>
     </div>
 
   </body>
 </html>
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -7,19 +7,20 @@
 "use strict";
 
 const {Cc, Ci, Cu} = require("chrome");
 const promise = require("sdk/core/promise");
 
 let {CssLogic} = require("devtools/styleinspector/css-logic");
 let {InplaceEditor, editableField, editableItem} = require("devtools/shared/inplace-editor");
 let {ELEMENT_STYLE, PSEUDO_ELEMENTS} = require("devtools/server/actors/styles");
-let {colorUtils} = require("devtools/css-color");
 let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 
+const {OutputParser} = require("devtools/output-parser");
+
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /**
  * These regular expressions are adapted from firebug's css.js, and are
@@ -907,17 +908,17 @@ Rule.prototype = {
  * @param {string} aPriority
  *        The property's priority (either "important" or an empty string).
  *
  */
 function TextProperty(aRule, aName, aValue, aPriority)
 {
   this.rule = aRule;
   this.name = aName;
-  this.value = colorUtils.processCSSString(aValue);
+  this.value = aValue;
   this.priority = aPriority;
   this.enabled = true;
   this.updateComputed();
 }
 
 TextProperty.prototype = {
   /**
    * Update the editor associated with this text property,
@@ -1042,16 +1043,18 @@ function CssRuleView(aDoc, aStore, aPage
 {
   this.doc = aDoc;
   this.store = aStore || {};
   this.pageStyle = aPageStyle;
   this.element = this.doc.createElementNS(HTML_NS, "div");
   this.element.className = "ruleview devtools-monospace";
   this.element.flex = 1;
 
+  this._outputParser = new OutputParser();
+
   this._buildContextMenu = this._buildContextMenu.bind(this);
   this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
   this._onSelectAll = this._onSelectAll.bind(this);
   this._onCopy = this._onCopy.bind(this);
 
   this.element.addEventListener("copy", this._onCopy);
 
   this._handlePrefChange = this._handlePrefChange.bind(this);
@@ -1163,17 +1166,19 @@ CssRuleView.prototype = {
 
       if (target.nodeName == "input") {
         let start = Math.min(target.selectionStart, target.selectionEnd);
         let end = Math.max(target.selectionStart, target.selectionEnd);
         let count = end - start;
         text = target.value.substr(start, count);
       } else {
         let win = this.doc.defaultView;
-        text = win.getSelection().toString();
+        let selection = win.getSelection();
+        debugger;
+        text = selection.toString();
 
         // Remove any double newlines.
         text = text.replace(/(\r?\n)\r?\n/g, "$1");
 
         // Remove "inline"
         let inline = _strings.GetStringFromName("rule.sourceInline");
         let rx = new RegExp("^" + inline + "\\r?\\n?", "g");
         text = text.replace(rx, "");
@@ -1209,16 +1214,18 @@ CssRuleView.prototype = {
   {
     this.clear();
 
     gDevTools.off("pref-changed", this._handlePrefChange);
 
     this.element.removeEventListener("copy", this._onCopy);
     delete this._onCopy;
 
+    delete this._outputParser;
+
     // Remove context menu
     if (this._contextmenu) {
       // Destroy the Select All menuitem.
       this.menuitemSelectAll.removeEventListener("command", this._onSelectAll);
       this.menuitemSelectAll = null;
 
       // Destroy the Copy menuitem.
       this.menuitemCopy.removeEventListener("command", this._onCopy);
@@ -1934,16 +1941,25 @@ TextPropertyEditor.prototype = {
     this.nameSpan.textContent = name;
 
     // Combine the property's value and priority into one string for
     // the value.
     let val = this.prop.value;
     if (this.prop.priority) {
       val += " !" + this.prop.priority;
     }
+
+    let store = this.prop.rule.elementStyle.store;
+    let propDirty = store.userProperties.contains(this.prop.rule.style, name);
+    if (propDirty) {
+      this.element.setAttribute("dirty", "");
+    } else {
+      this.element.removeAttribute("dirty");
+    }
+
     // Treat URLs differently than other properties.
     // Allow the user to click a link to the resource and open it.
     let resourceURI = this.getResourceURI();
     if (resourceURI) {
       this.valueSpan.textContent = "";
 
       appendText(this.valueSpan, val.split(resourceURI)[0]);
 
@@ -1961,25 +1977,23 @@ TextPropertyEditor.prototype = {
         aEvent.preventDefault();
 
         this.browserWindow.openUILinkIn(aEvent.target.href, "tab");
 
       }, false);
 
       appendText(this.valueSpan, val.split(resourceURI)[1]);
     } else {
-      this.valueSpan.textContent = val;
-    }
-
-    let store = this.prop.rule.elementStyle.store;
-    let propDirty = store.userProperties.contains(this.prop.rule.style, name);
-    if (propDirty) {
-      this.element.setAttribute("dirty", "");
-    } else {
-      this.element.removeAttribute("dirty");
+      let outputParser = this.ruleEditor.ruleView._outputParser;
+      let frag = outputParser.parseCssProperty(name, val, {
+        colorSwatchClass: "ruleview-colorswatch",
+        defaultColorType: !propDirty
+      });
+      this.valueSpan.innerHTML = "";
+      this.valueSpan.appendChild(frag);
     }
 
     // Populate the computed styles.
     this._updateComputed();
   },
 
   _onStartEditing: function TextPropertyEditor_onStartEditing()
   {
@@ -2016,20 +2030,28 @@ TextPropertyEditor.prototype = {
       }
 
       createChild(li, "span", {
         class: "ruleview-propertyname theme-fg-color5",
         textContent: computed.name
       });
       appendText(li, ": ");
 
+      let outputParser = this.ruleEditor.ruleView._outputParser;
+      let frag = outputParser.parseCssProperty(
+        computed.name, computed.value, {
+          colorSwatchClass: "ruleview-colorswatch"
+        }
+      );
+
       createChild(li, "span", {
         class: "ruleview-propertyvalue theme-fg-color1",
-        textContent: computed.value
+        child: frag
       });
+
       appendText(li, ";");
     }
 
     // Show or hide the expander as needed.
     if (showExpander) {
       this.expander.style.visibility = "visible";
     } else {
       this.expander.style.visibility = "hidden";
@@ -2296,16 +2318,18 @@ UserProperties.prototype = {
  */
 function createChild(aParent, aTag, aAttributes)
 {
   let elt = aParent.ownerDocument.createElementNS(HTML_NS, aTag);
   for (let attr in aAttributes) {
     if (aAttributes.hasOwnProperty(attr)) {
       if (attr === "textContent") {
         elt.textContent = aAttributes[attr];
+      } else if(attr === "child") {
+        elt.appendChild(aAttributes[attr]);
       } else {
         elt.setAttribute(attr, aAttributes[attr]);
       }
     }
   }
   aParent.appendChild(elt);
   return elt;
 }
--- a/browser/devtools/styleinspector/ruleview.css
+++ b/browser/devtools/styleinspector/ruleview.css
@@ -53,8 +53,12 @@
   vertical-align: middle;
   height: 1.5em;
   line-height: 1.5em;
 }
 
 .ruleview-header.ruleview-expandable-header {
   cursor: pointer;
 }
+
+.ruleview-colorswatch {
+  display: inline-block;
+}
--- a/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
+++ b/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
@@ -28,17 +28,17 @@ function openComputedView(aInspector)
   Services.obs.addObserver(runTests, "StyleInspector-populated", false);
 
   inspector.sidebar.select("computedview");
 }
 
 function runTests()
 {
   Services.obs.removeObserver(runTests, "StyleInspector-populated");
-  computedView = getComputedView(inspector);
+  computedView = getComputedView();
 
   var span = doc.querySelector(".matches");
   ok(span, "captain, we have the matches span");
 
   inspector.selection.setNode(span);
 
   is(span, computedView.viewedElement,
     "style inspector node matches the selected node");
--- a/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js
@@ -15,18 +15,18 @@ let originalValue = "#00F";
 // {
 //  value: what char sequence to type,
 //  commitKey: what key to type to "commit" the change,
 //  modifiers: commitKey modifiers,
 //  expected: what value is expected as a result
 // }
 let testData = [
   {value: "red", commitKey: "VK_ESCAPE", modifiers: {}, expected: originalValue},
-  {value: "red", commitKey: "VK_RETURN", modifiers: {}, expected: "red"},
-  {value: "blue", commitKey: "VK_TAB", modifiers: {shiftKey: true}, expected: "blue"}
+  {value: "red", commitKey: "VK_RETURN", modifiers: {}, expected: "#F00"},
+  {value: "blue", commitKey: "VK_TAB", modifiers: {shiftKey: true}, expected: "#00F"}
 ];
 
 function startTests()
 {
   let style = '' +
     '#testid {' +
     '  color: ' + originalValue + ';' +
     '}';
@@ -56,17 +56,17 @@ function runTestData(index)
   waitForEditorFocus(propEditor.element, function(aEditor) {
     is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value span.");
 
     for (let ch of testData[index].value) {
       EventUtils.sendChar(ch, ruleWindow);
     }
     EventUtils.synthesizeKey(testData[index].commitKey, testData[index].modifiers);
 
-    is(propEditor.valueSpan.innerHTML, testData[index].expected);
+    is(propEditor.valueSpan.textContent, testData[index].expected);
 
     runTestData(index + 1);
   });
 
   EventUtils.synthesizeMouse(propEditor.valueSpan, 1, 1, {}, ruleWindow);
 }
 
 function finishTest()
--- a/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
@@ -15,57 +15,57 @@ function simpleOverride(aInspector, aRul
 
     let elementRule = elementStyle.rules[0];
     let firstProp = elementRule.createProperty("background-color", "green", "");
     let secondProp = elementRule.createProperty("background-color", "blue", "");
     is(elementRule.textProps[0], firstProp, "Rules should be in addition order.");
     is(elementRule.textProps[1], secondProp, "Rules should be in addition order.");
 
     promiseDone(elementRule._applyingModifications.then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Second property should have been used.");
+      is(element.style.getPropertyValue("background-color"), "blue", "Second property should have been used.");
 
       secondProp.remove();
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 128, 0)", "After deleting second property, first should be used.");
+      is(element.style.getPropertyValue("background-color"), "green", "After deleting second property, first should be used.");
 
       secondProp = elementRule.createProperty("background-color", "blue", "");
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "New property should be used.");
+      is(element.style.getPropertyValue("background-color"), "blue", "New property should be used.");
 
       is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
       is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
 
       secondProp.setEnabled(false);
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 128, 0)", "After disabling second property, first value should be used");
+      is(element.style.getPropertyValue("background-color"), "green", "After disabling second property, first value should be used");
 
       firstProp.setEnabled(false);
       return elementRule._applyingModifications;
     }).then(() => {
       is(element.style.getPropertyValue("background-color"), "", "After disabling both properties, value should be empty.");
 
       secondProp.setEnabled(true);
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Value should be set correctly after re-enabling");
+      is(element.style.getPropertyValue("background-color"), "blue", "Value should be set correctly after re-enabling");
 
       firstProp.setEnabled(true);
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Re-enabling an earlier property shouldn't make it override a later property.");
+      is(element.style.getPropertyValue("background-color"), "blue", "Re-enabling an earlier property shouldn't make it override a later property.");
       is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
       is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
 
       firstProp.setValue("purple", "");
       return elementRule._applyingModifications;
     }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Modifying an earlier property shouldn't override a later property.");
+      is(element.style.getPropertyValue("background-color"), "blue", "Modifying an earlier property shouldn't override a later property.");
       finishTest();
     }));
   });
 }
 
 function finishTest()
 {
   doc = null;
--- a/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js
@@ -62,17 +62,17 @@ function testTopLeft()
     let elementAfterRule = afterRules[0];
     let elementAfterRuleView = [].filter.call(view.element.children, (e) => {
       return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
     })[0]._ruleEditor;
 
     is
     (
       convertTextPropsToString(elementAfterRule.textProps),
-      "background: none repeat scroll 0% 0% #F00; content: \" \"; position: absolute; " +
+      "background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " +
       "border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px",
       "TopLeft after properties are correct"
     );
 
     let elementBeforeRule = beforeRules[0];
     let elementBeforeRuleView = [].filter.call(view.element.children, (e) => {
       return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
     })[0]._ruleEditor;
@@ -237,41 +237,41 @@ function testParagraph()
     let elementFirstLineRule = firstLineRules[0];
     let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => {
       return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
     })[0]._ruleEditor;
 
     is
     (
       convertTextPropsToString(elementFirstLineRule.textProps),
-      "background: none repeat scroll 0% 0% #00F",
+      "background: none repeat scroll 0% 0% blue",
       "Paragraph first-line properties are correct"
     );
 
     let elementFirstLetterRule = firstLetterRules[0];
     let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => {
       return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule;
     })[0]._ruleEditor;
 
     is
     (
       convertTextPropsToString(elementFirstLetterRule.textProps),
-      "color: #F00; font-size: 130%",
+      "color: red; font-size: 130%",
       "Paragraph first-letter properties are correct"
     );
 
     let elementSelectionRule = selectionRules[0];
     let elementSelectionRuleView = [].filter.call(view.element.children, (e) => {
       return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule;
     })[0]._ruleEditor;
 
     is
     (
       convertTextPropsToString(elementSelectionRule.textProps),
-      "color: #FFF; background: none repeat scroll 0% 0% #000",
+      "color: white; background: none repeat scroll 0% 0% black",
       "Paragraph first-letter properties are correct"
     );
 
     testBody();
   });
 }
 
 function testBody() {
--- a/browser/devtools/styleinspector/test/head.js
+++ b/browser/devtools/styleinspector/test/head.js
@@ -43,16 +43,22 @@ function addTab(aURL)
 function openInspector(callback)
 {
   let target = TargetFactory.forTab(gBrowser.selectedTab);
   gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
     callback(toolbox.getCurrentPanel());
   });
 }
 
+function getActiveInspector()
+{
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  return gDevTools.getToolbox(target).getPanel("inspector");
+}
+
 function openRuleView(callback)
 {
   openInspector(inspector => {
     inspector.sidebar.once("ruleview-ready", () => {
       inspector.sidebar.select("ruleview");
       let ruleView = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
       callback(inspector, ruleView);
     })
@@ -94,22 +100,24 @@ function tearDown()
     dump(ex);
   }
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
   browser = hudId = hud = filterBox = outputNode = cs = null;
 }
 
-function getComputedView(inspector) {
+function getComputedView() {
+  let inspector = getActiveInspector();
   return inspector.sidebar.getWindowForTab("computedview").computedview.view;
 }
 
 function ruleView()
 {
+  let inspector = getActiveInspector();
   return inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
 }
 
 function waitForEditorFocus(aParent, aCallback)
 {
   aParent.addEventListener("focus", function onFocus(evt) {
     if (inplaceEditor(evt.target) && evt.target.tagName == "input") {
       aParent.removeEventListener("focus", onFocus, true);
@@ -159,13 +167,27 @@ function promiseDone(promise) {
     ok(false, "Promise failed: " + err);
     if (err.stack) {
       dump(err.stack);
     }
     SimpleTest.finish();
   });
 }
 
+function getComputedPropertyValue(aName)
+{
+  let computedview = getComputedView();
+  let props = computedview.styleDocument.querySelectorAll(".property-view");
+
+  for (let prop of props) {
+    let name = prop.querySelector(".property-name");
+
+    if (name.textContent === aName) {
+      let value = prop.querySelector(".property-value");
+      return value.textContent;
+    }
+  }
+}
 
 registerCleanupFunction(tearDown);
 
 waitForExplicitFinish();
 
--- a/browser/extensions/shumway/chrome.manifest
+++ b/browser/extensions/shumway/chrome.manifest
@@ -1,2 +1,1 @@
 resource shumway content/
-resource shumway.components components/
rename from browser/extensions/shumway/components/FlashStreamConverter.js
rename to browser/extensions/shumway/content/ShumwayStreamConverter.jsm
--- a/browser/extensions/shumway/components/FlashStreamConverter.js
+++ b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm
@@ -13,24 +13,23 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 'use strict';
 
-var EXPORTED_SYMBOLS = ['FlashStreamConverter1', 'FlashStreamConverter2'];
+var EXPORTED_SYMBOLS = ['ShumwayStreamConverter', 'ShumwayStreamOverlayConverter'];
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
-// True only if this is the version of pdf.js that is included with firefox.
 const SHUMWAY_CONTENT_TYPE = 'application/x-shockwave-flash';
 const EXPECTED_PLAYPREVIEW_URI_PREFIX = 'data:application/x-moz-playpreview;,' +
                                         SHUMWAY_CONTENT_TYPE;
 
 const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
 const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
 
 const MAX_CLIPBOARD_DATA_SIZE = 8000;
@@ -61,17 +60,17 @@ function getStringPref(pref, def) {
   try {
     return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
   } catch (ex) {
     return def;
   }
 }
 
 function log(aMsg) {
-  let msg = 'FlashStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
+  let msg = 'ShumwayStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
   Services.console.logStringMessage(msg);
   dump(msg + '\n');
 }
 
 function getDOMWindow(aChannel) {
   var requestor = aChannel.notificationCallbacks;
   var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
   return win;
@@ -631,20 +630,20 @@ function initExternalCom(wrappedWindow, 
     };
   };
   wrappedObject.__flash__unregisterCallback = function (functionName) {
     wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
     delete this[functionName];
   };
 }
 
-function FlashStreamConverterBase() {
+function ShumwayStreamConverterBase() {
 }
 
-FlashStreamConverterBase.prototype = {
+ShumwayStreamConverterBase.prototype = {
   QueryInterface: XPCOMUtils.generateQI([
       Ci.nsISupports,
       Ci.nsIStreamConverter,
       Ci.nsIStreamListener,
       Ci.nsIRequestObserver
   ]),
 
   /*
@@ -847,40 +846,37 @@ FlashStreamConverterBase.prototype = {
 
 // properties required for XPCOM registration:
 function copyProperties(obj, template) {
   for (var prop in template) {
     obj[prop] = template[prop];
   }
 }
 
-function FlashStreamConverter1() {}
-FlashStreamConverter1.prototype = new FlashStreamConverterBase();
-copyProperties(FlashStreamConverter1.prototype, {
+function ShumwayStreamConverter() {}
+ShumwayStreamConverter.prototype = new ShumwayStreamConverterBase();
+copyProperties(ShumwayStreamConverter.prototype, {
   classID: Components.ID('{4c6030f7-e20a-264f-5b0e-ada3a9e97384}'),
   classDescription: 'Shumway Content Converter Component',
   contractID: '@mozilla.org/streamconv;1?from=application/x-shockwave-flash&to=*/*'
 });
 
-function FlashStreamConverter2() {}
-FlashStreamConverter2.prototype = new FlashStreamConverterBase();
-copyProperties(FlashStreamConverter2.prototype, {
+function ShumwayStreamOverlayConverter() {}
+ShumwayStreamOverlayConverter.prototype = new ShumwayStreamConverterBase();
+copyProperties(ShumwayStreamOverlayConverter.prototype, {
   classID: Components.ID('{4c6030f7-e20a-264f-5f9b-ada3a9e97384}'),
   classDescription: 'Shumway PlayPreview Component',
   contractID: '@mozilla.org/streamconv;1?from=application/x-moz-playpreview&to=*/*'
 });
-FlashStreamConverter2.prototype.isValidRequest =
+ShumwayStreamOverlayConverter.prototype.isValidRequest =
   (function(aCtxt) {
     try {
       var request = aCtxt;
       request.QueryInterface(Ci.nsIChannel);
       var spec = request.URI.spec;
       return spec.indexOf(EXPECTED_PLAYPREVIEW_URI_PREFIX) === 0;
     } catch (e) {
       return false;
     }
   });
-FlashStreamConverter2.prototype.getUrlHint = function (requestUrl) {
+ShumwayStreamOverlayConverter.prototype.getUrlHint = function (requestUrl) {
   return '';
 };
-
-var NSGetFactory1 = XPCOMUtils.generateNSGetFactory([FlashStreamConverter1]);
-var NSGetFactory2 = XPCOMUtils.generateNSGetFactory([FlashStreamConverter2]);
--- a/browser/extensions/shumway/content/ShumwayUtils.jsm
+++ b/browser/extensions/shumway/content/ShumwayUtils.jsm
@@ -24,17 +24,17 @@ const PREF_IGNORE_CTP = PREF_PREFIX + 'i
 
 let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cm = Components.manager;
 let Cu = Components.utils;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://shumway.components/FlashStreamConverter.js');
+Cu.import('resource://shumway/ShumwayStreamConverter.jsm');
 
 let Svc = {};
 XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
                                    '@mozilla.org/mime;1',
                                    'nsIMIMEService');
 XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
                                    '@mozilla.org/plugin/host;1',
                                    'nsIPluginHost');
@@ -46,54 +46,40 @@ function getBoolPref(pref, def) {
     return def;
   }
 }
 
 function log(str) {
   dump(str + '\n');
 }
 
-// Register/unregister a constructor as a component.
+// Register/unregister a constructor as a factory.
 function Factory() {}
-
 Factory.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
-  _targetConstructor: null,
+  register: function register(targetConstructor) {
+    var proto = targetConstructor.prototype;
+    this._classID = proto.classID;
 
-  register: function register(targetConstructor) {
-    this._targetConstructor = targetConstructor;
-    var proto = targetConstructor.prototype;
+    var factory = XPCOMUtils._getFactory(targetConstructor);
+    this._factory = factory;
+
     var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
     registrar.registerFactory(proto.classID, proto.classDescription,
-                              proto.contractID, this);
+                              proto.contractID, factory);
   },
 
   unregister: function unregister() {
-    var proto = this._targetConstructor.prototype;
     var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
-    registrar.unregisterFactory(proto.classID, this);
-    this._targetConstructor = null;
-  },
-
-  // nsIFactory
-  createInstance: function createInstance(aOuter, iid) {
-    if (aOuter !== null)
-      throw Cr.NS_ERROR_NO_AGGREGATION;
-    return (new (this._targetConstructor)).QueryInterface(iid);
-  },
-
-  // nsIFactory
-  lockFactory: function lockFactory(lock) {
-    // No longer used as of gecko 1.7.
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+    registrar.unregisterFactory(this._classID, this._factory);
+    this._factory = null;
   }
 };
 
-let factory1 = new Factory();
-let factory2 = new Factory();
+let converterFactory = new Factory();
+let overlayConverterFactory = new Factory();
 
 let ShumwayUtils = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
   _registered: false,
 
   init: function init() {
     if (this.enabled)
       this._ensureRegistered();
@@ -108,48 +94,47 @@ let ShumwayUtils = {
   observe: function observe(aSubject, aTopic, aData) {
     if (this.enabled)
       this._ensureRegistered();
     else
       this._ensureUnregistered();
   },
   
   /**
-   * shumway is only enabled if it is both selected as the pdf viewer and if the 
-   * global switch enabling it is true.
+   * shumway is only enabled if the global switch enabling is true.
    * @return {boolean} Wether or not it's enabled.
    */
   get enabled() {
     return !getBoolPref(PREF_DISABLED, true);
   },
 
   _ensureRegistered: function _ensureRegistered() {
     if (this._registered)
       return;
 
     // Load the component and register it.
-    factory1.register(FlashStreamConverter1);
-    factory2.register(FlashStreamConverter2);
+    converterFactory.register(ShumwayStreamConverter);
+    overlayConverterFactory.register(ShumwayStreamOverlayConverter);
 
     var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
 
     Svc.pluginHost.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP);
 
     this._registered = true;
 
     log('Shumway is registered');
   },
 
   _ensureUnregistered: function _ensureUnregistered() {
     if (!this._registered)
       return;
 
     // Remove the contract/component.
-    factory1.unregister();
-    factory2.unregister();
+    converterFactory.unregister();
+    overlayConverterFactory.unregister();
 
     Svc.pluginHost.unregisterPlayPreviewMimeType(SWF_CONTENT_TYPE);
 
     this._registered = false;
 
     log('Shumway is unregistered');
   }
 };
--- a/browser/extensions/shumway/content/version.txt
+++ b/browser/extensions/shumway/content/version.txt
@@ -1,1 +1,1 @@
-0.7.351
+0.7.352
--- a/browser/extensions/shumway/content/web/avm-sandbox.js
+++ b/browser/extensions/shumway/content/web/avm-sandbox.js
@@ -11,17 +11,17 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-// Extension communication object... as it used in pdf.js
+// Extension communication object
 var FirefoxCom = (function FirefoxComClosure() {
   return {
     /**
      * Creates an event that the extension is listening for and will
      * synchronously respond to.
      * NOTE: It is reccomended to use request() instead since one day we may not
      * be able to synchronously reply.
      * @param {String} action The action to trigger.
--- a/browser/extensions/shumway/content/web/preview.js
+++ b/browser/extensions/shumway/content/web/preview.js
@@ -12,17 +12,17 @@
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 
-// Extenstion communication object... as it used in pdf.js
+// Extenstion communication object
 var FirefoxCom = (function FirefoxComClosure() {
   return {
     /**
      * Creates an event that the extension is listening for and will
      * synchronously respond to.
      * NOTE: It is reccomended to use request() instead since one day we may not
      * be able to synchronously reply.
      * @param {String} action The action to trigger.
--- a/browser/locales/en-US/chrome/browser/devtools/app-manager.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/app-manager.properties
@@ -28,8 +28,14 @@ validator.invalidProjectType=Unknown pro
 # LOCALIZATION NOTE (validator.missNameManifestProperty, validator.missIconsManifestProperty):
 # don't translate 'icons' and 'name'.
 validator.missNameManifestProperty=Missing mandatory 'name' in Manifest.
 validator.missIconsManifestProperty=Missing 'icons' in Manifest.
 validator.missIconMarketplace=app submission to the Marketplace needs at least a 128px icon
 validator.invalidAppType=Unknown app type: '%S'.
 validator.invalidHostedPriviledges=Hosted App can't be type '%S'.
 validator.noCertifiedSupport='certified' apps are not fully supported on the App manager.
+validator.nonAbsoluteLaunchPath=Launch path has to be an absolute path starting with '/': '%S'
+validator.invalidLaunchPath=Unable to access to app starting document '%S'
+# LOCALIZATION NOTE (validator.invalidLaunchPathBadHttpCode): %1$S is the URI of
+# the launch document, %2$S is the http error code.
+validator.invalidLaunchPathBadHttpCode=Unable to access to app starting document '%1$S', got HTTP code %2$S
+
--- a/browser/locales/en-US/chrome/browser/devtools/connection-screen.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/connection-screen.dtd
@@ -14,9 +14,16 @@
 <!ENTITY connect    "Connect">
 <!ENTITY connecting "Connecting…">
 <!ENTITY availableTabs "Available remote tabs:">
 <!ENTITY availableProcesses "Available remote processes:">
 <!ENTITY connectionError "Error:">
 <!ENTITY errorTimeout "Error: connection timeout.">
 <!ENTITY errorRefused "Error: connection refused.">
 <!ENTITY errorUnexpected "Unexpected error.">
-<!ENTITY help2 "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the 'Remote debugging' option in the remote device. See the <a target='_' href='https://developer.mozilla.org/docs/Tools/Remote_Debugging'>documentation</a> for more.">
+
+<!-- LOCALIZATION NOTE (remoteHelp, remoteDocumentation, remoteHelpSuffix):
+these strings will be concatenated in a single label, remoteDocumentation will
+be used as text for a link to MDN. -->
+<!ENTITY remoteHelp "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the 'Remote debugging' option in the remote device. For more, see the">
+<!ENTITY remoteDocumentation "documentation">
+<!ENTITY remoteHelpSuffix ".">
+
--- a/browser/themes/linux/devtools/computedview.css
+++ b/browser/themes/linux/devtools/computedview.css
@@ -142,8 +142,17 @@ body {
   width: 100%;
 }
 
 .link {
   padding: 0 3px;
   cursor: pointer;
   float: right;
 }
+
+.computedview-colorswatch {
+  display: inline-block;
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
--- a/browser/themes/linux/devtools/debugger.css
+++ b/browser/themes/linux/devtools/debugger.css
@@ -8,17 +8,17 @@
 }
 
 /* Sources and breakpoints pane */
 
 #sources-pane {
   min-width: 50px;
 }
 
-#sources-container + .devtools-side-splitter {
+#sources-and-editor-splitter {
   -moz-border-start-color: transparent;
 }
 
 #pretty-print {
   min-width: 0;
   font-weight: bold;
 }
 
@@ -78,17 +78,16 @@
 
 /* Black box message and source progress meter */
 
 #black-boxed-message,
 #source-progress-container {
   background: url(background-noise-toolbar.png) rgb(61,69,76);
   /* Prevent the container deck from aquiring the height from this message. */
   min-height: 1px;
-  padding: 25vh 0;
   color: white;
 }
 
 #source-progress {
   min-height: 2em;
   min-width: 40em;
 }
 
@@ -165,17 +164,17 @@
   width: 16px;
   height: 16px;
   margin: 2px;
 }
 
 /* Instruments pane (watch expressions, variables, event listeners...) */
 
 #instruments-pane > tabs > tab {
-  min-height: 2em !important;
+  min-height: 25px !important;
   padding: 0 !important;
 }
 
 #instruments-pane > tabpanels > tabpanel {
   background: #fff;
 }
 
 /* Watch expressions view */
@@ -435,8 +434,28 @@
 
 #instruments-pane-toggle[pane-collapsed] {
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
 }
 
 #instruments-pane-toggle:active {
   -moz-image-region: rect(0px,32px,16px,16px);
 }
+
+/* Horizontal vs. vertical layout */
+
+#vertical-layout-panes-container {
+  min-height: 35vh;
+  max-height: 80vh;
+}
+
+#body[layout=vertical] #instruments-pane {
+  margin: 0 !important;
+  /* To prevent all the margin hacks to hide the sidebar. */
+}
+
+#body[layout=vertical] .side-menu-widget-container {
+  box-shadow: none !important;
+}
+
+#body[layout=vertical] .side-menu-widget-item-arrow {
+  background-image: none !important;
+}
--- a/browser/themes/linux/devtools/ruleview.css
+++ b/browser/themes/linux/devtools/ruleview.css
@@ -91,16 +91,24 @@
   list-style: none;
   padding: 0;
 }
 
 .ruleview-computed {
   -moz-margin-start: 35px;
 }
 
+.ruleview-colorswatch {
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
+
 .ruleview-overridden {
   text-decoration: line-through;
 }
 
 .styleinspector-propertyeditor {
   border: 1px solid #CCC;
   padding: 0;
 }
--- a/browser/themes/osx/devtools/computedview.css
+++ b/browser/themes/osx/devtools/computedview.css
@@ -160,8 +160,17 @@ body {
   width: 100%;
 }
 
 .link {
   padding: 0 3px;
   cursor: pointer;
   float: right;
 }
+
+.computedview-colorswatch {
+  display: inline-block;
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
--- a/browser/themes/osx/devtools/debugger.css
+++ b/browser/themes/osx/devtools/debugger.css
@@ -10,17 +10,17 @@
 }
 
 /* Sources and breakpoints pane */
 
 #sources-pane {
   min-width: 50px;
 }
 
-#sources-container + .devtools-side-splitter {
+#sources-and-editor-splitter {
   -moz-border-start-color: transparent;
 }
 
 #pretty-print {
   min-width: 0;
   font-weight: bold;
 }
 
@@ -76,17 +76,16 @@
 
 /* Black box message and source progress meter */
 
 #black-boxed-message,
 #source-progress-container {
   background: url(background-noise-toolbar.png) rgb(61,69,76);
   /* Prevent the container deck from aquiring the height from this message. */
   min-height: 1px;
-  padding: 25vh 0;
   color: white;
 }
 
 #source-progress {
   min-height: 2em;
   min-width: 40em;
 }
 
@@ -163,17 +162,17 @@
   width: 16px;
   height: 16px;
   margin: 2px;
 }
 
 /* Instruments pane (watch expressions, variables, event listeners...) */
 
 #instruments-pane > tabs > tab {
-  min-height: 2em !important;
+  min-height: 1em !important;
   padding: 0 !important;
 }
 
 #instruments-pane > tabpanels > tabpanel {
   background: #fff;
 }
 
 /* Watch expressions view */
@@ -433,8 +432,28 @@
 
 #instruments-pane-toggle[pane-collapsed] {
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
 }
 
 #instruments-pane-toggle:active {
   -moz-image-region: rect(0px,32px,16px,16px);
 }
+
+/* Horizontal vs. vertical layout */
+
+#vertical-layout-panes-container {
+  min-height: 35vh;
+  max-height: 80vh;
+}
+
+#body[layout=vertical] #instruments-pane {
+  margin: 0 !important;
+  /* To prevent all the margin hacks to hide the sidebar. */
+}
+
+#body[layout=vertical] .side-menu-widget-container {
+  box-shadow: none !important;
+}
+
+#body[layout=vertical] .side-menu-widget-item-arrow {
+  background-image: none !important;
+}
--- a/browser/themes/osx/devtools/ruleview.css
+++ b/browser/themes/osx/devtools/ruleview.css
@@ -95,16 +95,24 @@
   list-style: none;
   padding: 0;
 }
 
 .ruleview-computed {
   -moz-margin-start: 35px;
 }
 
+.ruleview-colorswatch {
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
+
 .ruleview-overridden {
   text-decoration: line-through;
 }
 
 .styleinspector-propertyeditor {
   border: 1px solid #CCC;
   padding: 0;
 }
--- a/browser/themes/shared/devtools/dark-theme.css
+++ b/browser/themes/shared/devtools/dark-theme.css
@@ -99,8 +99,14 @@
 
 .theme-fg-color7 { /* Red */
   color: #bf5656;
 }
 
 .theme-fg-contrast { /* To be used for text on theme-bg-contrast */
   color: black;
 }
+
+.ruleview-colorswatch,
+.computedview-colorswatch,
+.markupview-colorswatch {
+  box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
+}
--- a/browser/themes/shared/devtools/light-theme.css
+++ b/browser/themes/shared/devtools/light-theme.css
@@ -99,8 +99,14 @@
 
 .theme-fg-color7 { /* Red */
   color: #bf5656;
 }
 
 .theme-fg-contrast { /* To be used for text on theme-bg-contrast */
   color: black;
 }
+
+.ruleview-colorswatch,
+.computedview-colorswatch,
+.markupview-colorswatch {
+  box-shadow: 0 0 0 1px #EFEFEF;
+}
--- a/browser/themes/windows/devtools/computedview.css
+++ b/browser/themes/windows/devtools/computedview.css
@@ -160,8 +160,17 @@ body {
   width: 100%;
 }
 
 .link {
   padding: 0 3px;
   cursor: pointer;
   float: right;
 }
+
+.computedview-colorswatch {
+  display: inline-block;
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
--- a/browser/themes/windows/devtools/debugger.css
+++ b/browser/themes/windows/devtools/debugger.css
@@ -8,17 +8,17 @@
 }
 
 /* Sources and breakpoints pane */
 
 #sources-pane {
   min-width: 50px;
 }
 
-#sources-container + .devtools-side-splitter {
+#sources-and-editor-splitter {
   -moz-border-start-color: transparent;
 }
 
 #pretty-print {
   min-width: 0;
   font-weight: bold;
 }
 
@@ -76,17 +76,16 @@
 
 /* Black box message and source progress meter */
 
 #black-boxed-message,
 #source-progress-container {
   background: url(background-noise-toolbar.png) rgb(61,69,76);
   /* Prevent the container deck from aquiring the height from this message. */
   min-height: 1px;
-  padding: 25vh 0;
   color: white;
 }
 
 #source-progress {
   min-height: 2em;
   min-width: 40em;
 }
 
@@ -163,17 +162,17 @@
   width: 16px;
   height: 16px;
   margin: 2px;
 }
 
 /* Instruments pane (watch expressions, variables, event listeners...) */
 
 #instruments-pane > tabs > tab {
-  min-height: 2em !important;
+  min-height: 25px !important;
   padding: 0 !important;
 }
 
 #instruments-pane > tabpanels > tabpanel {
   background: #fff;
 }
 
 /* Watch expressions view */
@@ -438,8 +437,28 @@
 
 #instruments-pane-toggle:hover {
   -moz-image-region: rect(0px,32px,16px,16px);
 }
 
 #instruments-pane-toggle:hover:active {
   -moz-image-region: rect(0px,48px,16px,32px);
 }
+
+/* Horizontal vs. vertical layout */
+
+#vertical-layout-panes-container {
+  min-height: 35vh;
+  max-height: 80vh;
+}
+
+#body[layout=vertical] #instruments-pane {
+  margin: 0 !important;
+  /* To prevent all the margin hacks to hide the sidebar. */
+}
+
+#body[layout=vertical] .side-menu-widget-container {
+  box-shadow: none !important;
+}
+
+#body[layout=vertical] .side-menu-widget-item-arrow {
+  background-image: none !important;
+}
--- a/browser/themes/windows/devtools/ruleview.css
+++ b/browser/themes/windows/devtools/ruleview.css
@@ -91,16 +91,24 @@
   list-style: none;
   padding: 0;
 }
 
 .ruleview-computed {
   -moz-margin-start: 35px;
 }
 
+.ruleview-colorswatch {
+  border-radius: 50%;
+  width: 1em;
+  height: 1em;
+  vertical-align: text-top;
+  -moz-margin-end: 5px;
+}
+
 .ruleview-overridden {
   text-decoration: line-through;
 }
 
 .styleinspector-propertyeditor {
   border: 1px solid #CCC;
   padding: 0;
 }
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -1,16 +1,28 @@
 dnl This Source Code Form is subject to the terms of the Mozilla Public
 dnl License, v. 2.0. If a copy of the MPL was not distributed with this
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 dnl Add compiler specific options
 
 AC_DEFUN([MOZ_DEFAULT_COMPILER],
 [
+dnl set DEVELOPER_OPTIONS early; MOZ_DEFAULT_COMPILER is usually the first non-setup directive
+  if test -z "$MOZILLA_OFFICIAL"; then
+    DEVELOPER_OPTIONS=1
+  fi
+  MOZ_ARG_ENABLE_BOOL(release,
+  [  --enable-release        Build with more conservative, release engineering-oriented options.
+                          This may slow down builds.],
+      DEVELOPER_OPTIONS=,
+      DEVELOPER_OPTIONS=1)
+
+  AC_SUBST(DEVELOPER_OPTIONS)
+
 dnl Default to MSVC for win32 and gcc-4.2 for darwin
 dnl ==============================================================
 if test -z "$CROSS_COMPILE"; then
 case "$target" in
 *-mingw*)
     if test -z "$CC"; then CC=cl; fi
     if test -z "$CXX"; then CXX=cl; fi
     if test -z "$CPP"; then CPP="cl -E -nologo"; fi
@@ -155,27 +167,16 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBU
     export MOZ_DEBUG_SYMBOLS
 fi
 
 ])
 
 dnl A high level macro for selecting compiler options.
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
-  if test -z "$MOZILLA_OFFICIAL"; then
-    DEVELOPER_OPTIONS=1
-  fi
-  MOZ_ARG_ENABLE_BOOL(release,
-  [  --enable-release        Build with more conservative, release engineering-oriented options.
-                          This may slow down builds.],
-      DEVELOPER_OPTIONS=,
-      DEVELOPER_OPTIONS=1)
-
-  AC_SUBST(DEVELOPER_OPTIONS)
-
   if test "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
     dnl Don't enable on pymake, because of bug 918652. Bug 912979 is an annoyance
     dnl with pymake, too.
     MOZ_PSEUDO_DERECURSE=no-pymake,no-skip
   fi
 
   MOZ_DEBUGGING_OPTS
   MOZ_RTTI
--- a/content/html/content/src/HTMLFieldSetElement.cpp
+++ b/content/html/content/src/HTMLFieldSetElement.cpp
@@ -212,35 +212,104 @@ HTMLFieldSetElement::RemoveChildAt(uint3
   }
 }
 
 void
 HTMLFieldSetElement::AddElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.AppendElement(aElement);
 
+  // If the element that we are adding aElement is a fieldset, then all the
+  // invalid elements in aElement are also invalid elements of this.
+  HTMLFieldSetElement* fieldSet = FromContent(aElement);
+  if (fieldSet) {
+    if (fieldSet->mInvalidElementsCount > 0) {
+      // The order we call UpdateValidity and adjust mInvalidElementsCount is
+      // important. We need to first call UpdateValidity in case
+      // mInvalidElementsCount was 0 before the call and will be incremented to
+      // 1 and so we need to change state to invalid. After that is done, we
+      // are free to increment mInvalidElementsCount to the correct amount.
+      UpdateValidity(false);
+      mInvalidElementsCount += fieldSet->mInvalidElementsCount - 1;
+    }
+    return;
+  }
+
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
       cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
     UpdateValidity(false);
   }
+
+#if DEBUG
+  int32_t debugInvalidElementsCount = 0;
+  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
+    HTMLFieldSetElement* fieldSet = FromContent(mDependentElements[i]);
+    if (fieldSet) {
+      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
+      continue;
+    }
+    nsCOMPtr<nsIConstraintValidation>
+      cvElmt = do_QueryObject(mDependentElements[i]);
+    if (cvElmt &&
+        cvElmt->IsCandidateForConstraintValidation() &&
+        !(cvElmt->IsValid())) {
+      debugInvalidElementsCount += 1;
+    }
+  }
+  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
+#endif
 }
 
 void
 HTMLFieldSetElement::RemoveElement(nsGenericHTMLFormElement* aElement)
 {
   mDependentElements.RemoveElement(aElement);
 
+  // If the element that we are removing aElement is a fieldset, then all the
+  // invalid elements in aElement are also removed from this.
+  HTMLFieldSetElement* fieldSet = FromContent(aElement);
+  if (fieldSet) {
+    if (fieldSet->mInvalidElementsCount > 0) {
+      // The order we update mInvalidElementsCount and call UpdateValidity is
+      // important. We need to first decrement mInvalidElementsCount and then
+      // call UpdateValidity, in case mInvalidElementsCount hits 0 in the call
+      // of UpdateValidity and we have to change state to valid.
+      mInvalidElementsCount -= fieldSet->mInvalidElementsCount - 1;
+      UpdateValidity(true);
+    }
+    return;
+  }
+
   // We need to update the validity of the fieldset.
   nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
   if (cvElmt &&
       cvElmt->IsCandidateForConstraintValidation() && !cvElmt->IsValid()) {
     UpdateValidity(true);
   }
+
+#if DEBUG
+  int32_t debugInvalidElementsCount = 0;
+  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
+    HTMLFieldSetElement* fieldSet = FromContent(mDependentElements[i]);
+    if (fieldSet) {
+      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
+      continue;
+    }
+    nsCOMPtr<nsIConstraintValidation>
+      cvElmt = do_QueryObject(mDependentElements[i]);
+    if (cvElmt &&
+        cvElmt->IsCandidateForConstraintValidation() &&
+        !(cvElmt->IsValid())) {
+      debugInvalidElementsCount += 1;
+    }
+  }
+  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
+#endif
 }
 
 void
 HTMLFieldSetElement::NotifyElementsForFirstLegendChange(bool aNotify)
 {
   /**
    * NOTE: this could be optimized if only call when the fieldset is currently
    * disabled.
--- a/content/html/content/test/mochitest.ini
+++ b/content/html/content/test/mochitest.ini
@@ -393,16 +393,17 @@ support-files =
 [test_img_attributes_reflection.html]
 [test_li_attributes_reflection.html]
 [test_link_attributes_reflection.html]
 [test_map_attributes_reflection.html]
 [test_meta_attributes_reflection.html]
 [test_mod_attributes_reflection.html]
 [test_mozaudiochannel.html]
 [test_named_options.html]
+[test_nested_invalid_fieldsets.html]
 [test_object_attributes_reflection.html]
 [test_object_plugin_nav.html]
 [test_ol_attributes_reflection.html]
 [test_param_attributes_reflection.html]
 [test_q_attributes_reflection.html]
 [test_restore_from_parser_fragment.html]
 [test_rowscollection.html]
 [test_srcdoc-2.html]
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_nested_invalid_fieldsets.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=914029
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 914029</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 914029 **/
+
+  var innerFieldset = document.createElement("fieldset");
+  var outerFieldset = document.createElement("fieldset");
+  var textarea = document.createElement("textarea");
+  textarea.setAttribute("required", "");
+  innerFieldset.appendChild(textarea);
+  outerFieldset.appendChild(innerFieldset);
+  SpecialPowers.forceGC();
+  ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+           " work correctly.");
+  var innerFieldset = document.createElement("fieldset");
+  var outerFieldset = document.createElement("fieldset");
+  var textarea = document.createElement("textarea");
+  var textarea2 = document.createElement("textarea");
+  textarea.setAttribute("required", "");
+  innerFieldset.appendChild(textarea);
+  innerFieldset.appendChild(textarea2);
+  outerFieldset.appendChild(innerFieldset);
+  SpecialPowers.forceGC();
+  ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+           " work correctly.");
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=914029">Mozilla Bug 914029</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -88,17 +88,17 @@ using mozilla::PluginPRLibrary;
 using mozilla::plugins::PluginModuleParent;
 
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 #endif
 
 #ifdef XP_WIN
 #include <windows.h>
-#include "nsWindowsHelpers.h"
+#include "mozilla/WindowsVersion.h"
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/Compatibility.h"
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include <android/log.h>
 #include "android_npapi.h"
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -588,31 +588,32 @@ DrawTargetCairo::DrawSurfaceWithShadow(S
 
   cairo_restore(mContext);
 }
 
 void
 DrawTargetCairo::DrawPattern(const Pattern& aPattern,
                              const StrokeOptions& aStrokeOptions,
                              const DrawOptions& aOptions,
-                             DrawPatternType aDrawType)
+                             DrawPatternType aDrawType,
+                             bool aPathBoundsClip)
 {
   if (!PatternIsCompatible(aPattern)) {
     return;
   }
   
   AutoClearDeviceOffset clear(aPattern);
 
   cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
   cairo_set_source(mContext, pat);
 
   cairo_set_antialias(mContext, GfxAntialiasToCairoAntialias(aOptions.mAntialiasMode));
 
   if (NeedIntermediateSurface(aPattern, aOptions) ||
-      !IsOperatorBoundByMask(aOptions.mCompositionOp)) {
+      (!IsOperatorBoundByMask(aOptions.mCompositionOp) && !aPathBoundsClip)) {
     cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
 
     ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
 
     // Don't want operators to be applied twice
     cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
 
     if (aDrawType == DRAW_STROKE) {
@@ -647,17 +648,29 @@ DrawTargetCairo::FillRect(const Rect &aR
                           const Pattern &aPattern,
                           const DrawOptions &aOptions)
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   cairo_new_path(mContext);
   cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
 
-  DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
+  bool pathBoundsClip = false;
+
+  double cexts[4];
+  cairo_clip_extents(mContext, &cexts[0], &cexts[1], &cexts[2], &cexts[3]);
+  Rect clipRect(cexts[0], cexts[1], cexts[2] - cexts[0], cexts[3] - cexts[1]);
+  double pexts[4];
+  cairo_path_extents(mContext, &pexts[0], &pexts[1], &pexts[2], &pexts[3]);
+  Rect pathRect(pexts[0], pexts[1], pexts[2] - pexts[0], pexts[3] - pexts[1]);
+  if (pathRect.Contains(clipRect)) {
+    pathBoundsClip = true;
+  }
+
+  DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL, pathBoundsClip);
 }
 
 void
 DrawTargetCairo::CopySurfaceInternal(cairo_surface_t* aSurface,
                                      const IntRect &aSource,
                                      const IntPoint &aDest)
 {
   cairo_identity_matrix(mContext);
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -156,17 +156,18 @@ public:
 private: // methods
   // Init cairo surface without doing a cairo_surface_reference() call.
   bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize);
 
   enum DrawPatternType { DRAW_FILL, DRAW_STROKE };
   void DrawPattern(const Pattern& aPattern,
                    const StrokeOptions& aStrokeOptions,
                    const DrawOptions& aOptions,
-                   DrawPatternType aDrawType);
+                   DrawPatternType aDrawType,
+                   bool aPathBoundsClip = false);
 
   void CopySurfaceInternal(cairo_surface_t* aSurface,
                            const IntRect& aSource,
                            const IntPoint& aDest);
 
   // Call before you make any changes to the backing surface with which this
   // context is associated. Pass the path you're going to be using if you have
   // one.
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -63,19 +63,17 @@ WGLLibrary::CreateDummyWindow(HDC *aWind
     HDC dc = GetDC(win);
     NS_ENSURE_TRUE(dc, nullptr);
 
     if (mWindowPixelFormat == 0) {
         PIXELFORMATDESCRIPTOR pfd;
         ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
         pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
         pfd.nVersion = 1;
-        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
-        if (mUseDoubleBufferedWindows)
-            pfd.dwFlags |= PFD_DOUBLEBUFFER;
+        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
         pfd.iPixelType = PFD_TYPE_RGBA;
         pfd.cColorBits = 24;
         pfd.cRedBits = 8;
         pfd.cGreenBits = 8;
         pfd.cBlueBits = 8;
         pfd.cAlphaBits = 8;
         pfd.cDepthBits = 0;
         pfd.iLayerType = PFD_MAIN_PLANE;
@@ -119,18 +117,16 @@ WGLLibrary::EnsureInitialized(bool aUseM
     if (!mOGLLibrary) {
         mOGLLibrary = PR_LoadLibrary(libGLFilename);
         if (!mOGLLibrary) {
             NS_WARNING("Couldn't load OpenGL library.");
             return false;
         }
     }
 
-    mUseDoubleBufferedWindows = PR_GetEnv("MOZ_WGL_DB") != nullptr;
-
     GLLibraryLoader::SymLoadStruct earlySymbols[] = {
         { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", nullptr } },
         { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", nullptr } },
         { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", nullptr } },
         { (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", nullptr } },
         { (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", nullptr } },
         { (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", nullptr } },
         { (PRFuncPtr*) &fShareLists, { "wglShareLists", nullptr } },
@@ -507,17 +503,17 @@ GLContextProviderWGL::CreateForWindow(ns
                                                         false,
                                                         dc,
                                                         context,
                                                         libToUse);
     if (!glContext->Init()) {
         return nullptr;
     }
 
-    glContext->SetIsDoubleBuffered(sWGLLib[libToUse].UseDoubleBufferedWindows());
+    glContext->SetIsDoubleBuffered(true);
 
     return glContext.forget();
 }
 
 static already_AddRefed<GLContextWGL>
 CreatePBufferOffscreenContext(const gfxIntSize& aSize,
                               LibType aLibToUse)
 {
--- a/gfx/gl/WGLLibrary.h
+++ b/gfx/gl/WGLLibrary.h
@@ -15,17 +15,16 @@ public:
     WGLLibrary() 
       : mInitialized(false), 
         mOGLLibrary(nullptr),
         mHasRobustness(false), 
         mWindow (0),
         mWindowDC(0),
         mWindowGLContext(0),
         mWindowPixelFormat (0),
-        mUseDoubleBufferedWindows(false),
         mLibType(OPENGL_LIB)     
     {}
 
     enum LibraryType
     {
       OPENGL_LIB = 0,
       MESA_LLVMPIPE_LIB = 1,
       LIBS_MAX
@@ -73,30 +72,28 @@ public:
     HWND CreateDummyWindow(HDC *aWindowDC = nullptr);
 
     bool HasRobustness() const { return mHasRobustness; }
     bool IsInitialized() const { return mInitialized; }
     HWND GetWindow() const { return mWindow; }
     HDC GetWindowDC() const {return mWindowDC; }
     HGLRC GetWindowGLContext() const {return mWindowGLContext; }
     int GetWindowPixelFormat() const { return mWindowPixelFormat; }
-    bool UseDoubleBufferedWindows() const { return mUseDoubleBufferedWindows; }
     LibraryType GetLibraryType() const { return mLibType; }
     static LibraryType SelectLibrary(const ContextFlags& aFlags);
     
 private:
     bool mInitialized;
     PRLibrary *mOGLLibrary;
     bool mHasRobustness;
 
     HWND mWindow;
     HDC mWindowDC;
     HGLRC mWindowGLContext;
     int mWindowPixelFormat;
-    bool mUseDoubleBufferedWindows;
     LibraryType mLibType;
 
 };
 
 // a global WGLLibrary instance
 extern WGLLibrary sWGLLibrary[WGLLibrary::LIBS_MAX];
 
 } /* namespace gl */
--- a/hal/windows/WindowsBattery.cpp
+++ b/hal/windows/WindowsBattery.cpp
@@ -6,17 +6,17 @@
 #include "Hal.h"
 #include "HalImpl.h"
 #include "nsITimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/battery/Constants.h"
 #include "nsComponentManagerUtils.h"
 
 #include <windows.h>
-#include "nsWindowsHelpers.h"
+#include "mozilla/WindowsVersion.h"
 
 using namespace mozilla::dom::battery;
 
 namespace mozilla {
 namespace hal_impl {
 
 static nsCOMPtr<nsITimer> sUpdateTimer;
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -659,21 +659,22 @@ selfhosting:: selfhosted.out.h
 
 selfhosting_srcs := \
   $(srcdir)/builtin/Utilities.js \
   $(srcdir)/builtin/Array.js \
   $(srcdir)/builtin/Date.js \
   $(srcdir)/builtin/Intl.js \
   $(srcdir)/builtin/IntlData.js \
   $(srcdir)/builtin/Iterator.js \
+  $(srcdir)/builtin/Map.js \
   $(srcdir)/builtin/Number.js \
   $(srcdir)/builtin/ParallelArray.js \
   $(srcdir)/builtin/String.js \
   $(srcdir)/builtin/Set.js \
-  $(srcdir)/builtin/Map.js \
+  $(srcdir)/builtin/TypedObject.js \
   $(NULL)
 
 selfhosted_out_h_deps := \
   $(selfhosting_srcs) \
   $(srcdir)/js.msg \
   $(srcdir)/builtin/embedjs.py \
   $(NULL)
 
--- a/js/src/build/autoconf/compiler-opts.m4
+++ b/js/src/build/autoconf/compiler-opts.m4
@@ -1,16 +1,28 @@
 dnl This Source Code Form is subject to the terms of the Mozilla Public
 dnl License, v. 2.0. If a copy of the MPL was not distributed with this
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 dnl Add compiler specific options
 
 AC_DEFUN([MOZ_DEFAULT_COMPILER],
 [
+dnl set DEVELOPER_OPTIONS early; MOZ_DEFAULT_COMPILER is usually the first non-setup directive
+  if test -z "$MOZILLA_OFFICIAL"; then
+    DEVELOPER_OPTIONS=1
+  fi
+  MOZ_ARG_ENABLE_BOOL(release,
+  [  --enable-release        Build with more conservative, release engineering-oriented options.
+                          This may slow down builds.],
+      DEVELOPER_OPTIONS=,
+      DEVELOPER_OPTIONS=1)
+
+  AC_SUBST(DEVELOPER_OPTIONS)
+
 dnl Default to MSVC for win32 and gcc-4.2 for darwin
 dnl ==============================================================
 if test -z "$CROSS_COMPILE"; then
 case "$target" in
 *-mingw*)
     if test -z "$CC"; then CC=cl; fi
     if test -z "$CXX"; then CXX=cl; fi
     if test -z "$CPP"; then CPP="cl -E -nologo"; fi
@@ -155,27 +167,16 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBU
     export MOZ_DEBUG_SYMBOLS
 fi
 
 ])
 
 dnl A high level macro for selecting compiler options.
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
-  if test -z "$MOZILLA_OFFICIAL"; then
-    DEVELOPER_OPTIONS=1
-  fi
-  MOZ_ARG_ENABLE_BOOL(release,
-  [  --enable-release        Build with more conservative, release engineering-oriented options.
-                          This may slow down builds.],
-      DEVELOPER_OPTIONS=,
-      DEVELOPER_OPTIONS=1)
-
-  AC_SUBST(DEVELOPER_OPTIONS)
-
   if test "${MOZ_PSEUDO_DERECURSE-unset}" = unset; then
     dnl Don't enable on pymake, because of bug 918652. Bug 912979 is an annoyance
     dnl with pymake, too.
     MOZ_PSEUDO_DERECURSE=no-pymake,no-skip
   fi
 
   MOZ_DEBUGGING_OPTS
   MOZ_RTTI
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1077,16 +1077,25 @@ SetJitCompilerOption(JSContext *cx, unsi
         number = -1;
 
     JS_SetGlobalJitCompilerOption(cx, opt, uint32_t(number));
 
     args.rval().setBoolean(true);
     return true;
 }
 
+static bool
+SetIonAssertGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    jit::js_IonOptions.assertGraphConsistency = ToBoolean(args.get(0));
+    args.rval().setUndefined();
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment')",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc."),
 
     JS_FN_HELP("minorgc", ::MinorGC, 0, 0,
@@ -1241,16 +1250,22 @@ static const JSFunctionSpecWithHelp Test
 "  Returns whether asm.js compilation is currently available or whether it is disabled\n"
 "  (e.g., by the debugger)."),
 
     JS_FN_HELP("isAsmJSModule", IsAsmJSModule, 1, 0,
 "isAsmJSModule(fn)",
 "  Returns whether the given value is a function containing \"use asm\" that has been\n"
 "  validated according to the asm.js spec."),
 
+    JS_FN_HELP("isAsmJSModuleLoadedFromCache", IsAsmJSModuleLoadedFromCache, 1, 0,
+"isAsmJSModule(fn)",
+"  Return whether the given asm.js module function has been loaded directly\n"
+"  from the cache. This function throws an error if fn is not a validated asm.js\n"
+"  module."),
+
     JS_FN_HELP("isAsmJSFunction", IsAsmJSFunction, 1, 0,
 "isAsmJSFunction(fn)",
 "  Returns whether the given value is a nested function in an asm.js module that has been\n"
 "  both compile- and link-time validated."),
 
     JS_FN_HELP("inParallelSection", testingFunc_inParallelSection, 0, 0,
 "inParallelSection()",
 "  True if this code is executing within a parallel section."),
@@ -1270,16 +1285,22 @@ static const JSFunctionSpecWithHelp Test
     JS_FN_HELP("bailout", testingFunc_bailout, 0, 0,
 "bailout()",
 "  Force a bailout out of ionmonkey (if running in ionmonkey)."),
 
     JS_FN_HELP("setJitCompilerOption", SetJitCompilerOption, 2, 0,
 "setCompilerOption(<option>, <number>)",
 "  Set a compiler option indexed in JSCompileOption enum to a number.\n"),
 
+    JS_FN_HELP("setIonAssertGraphCoherency", SetIonAssertGraphCoherency, 1, 0,
+"setIonAssertGraphCoherency(bool)",
+"  Set whether Ion should perform graph consistency (DEBUG-only) assertions. These assertions\n"
+"  are valuable and should be generally enabled, however they can be very expensive for large\n"
+"  (asm.js) programs."),
+
     JS_FS_HELP_END
 };
 
 bool
 js::DefineTestingFunctions(JSContext *cx, HandleObject obj)
 {
     return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
 }
--- a/js/src/builtin/TypeRepresentation.cpp
+++ b/js/src/builtin/TypeRepresentation.cpp
@@ -23,17 +23,18 @@ using namespace js;
 using namespace mozilla;
 
 ///////////////////////////////////////////////////////////////////////////
 // Class def'n for the owner object
 
 const Class TypeRepresentation::class_ = {
     "TypeRepresentation",
     JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_PRIVATE,
+    JSCLASS_HAS_PRIVATE |
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEREPR_SLOTS),
     JS_PropertyStub,         /* addProperty */
     JS_DeletePropertyStub,   /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     obj_finalize,
@@ -280,17 +281,39 @@ TypeRepresentation::addToTableOrFree(JSC
         NewBuiltinClassInstance(cx,
                                 &class_,
                                 gc::GetGCObjectKind(&class_)));
     if (!ownerObject) {
         comp->typeReprs.remove(this);
         js_free(this);
         return nullptr;
     }
+
     ownerObject->setPrivate(this);
+
+    // Assign the various reserved slots:
+    ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_KIND, Int32Value(kind()));
+    ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_SIZE, Int32Value(size()));
+    ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_ALIGNMENT, Int32Value(alignment()));
+
+    switch (kind()) {
+      case Array:
+        ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_LENGTH,
+                                      Int32Value(asArray()->length()));
+        break;
+
+      case Scalar:
+        ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_TYPE,
+                                      Int32Value(asScalar()->type()));
+        break;
+
+      case Struct:
+        break;
+    }
+
     ownerObject_.init(ownerObject);
     return &*ownerObject;
 }
 
 /*static*/
 JSObject *
 ScalarTypeRepresentation::Create(JSContext *cx,
                                  ScalarTypeRepresentation::Type type)
--- a/js/src/builtin/TypeRepresentation.h
+++ b/js/src/builtin/TypeRepresentation.h
@@ -46,16 +46,17 @@
   it describes.
 
  */
 
 #include "jsalloc.h"
 #include "jscntxt.h"
 #include "jspubtd.h"
 
+#include "builtin/TypedObjectConstants.h"
 #include "gc/Barrier.h"
 #include "js/HashTable.h"
 
 namespace js {
 
 class TypeRepresentation;
 class ScalarTypeRepresentation;
 class ArrayTypeRepresentation;
@@ -85,36 +86,36 @@ struct TypeRepresentationHasher
 
 typedef js::HashSet<TypeRepresentation *,
                     TypeRepresentationHasher,
                     RuntimeAllocPolicy> TypeRepresentationHash;
 
 class TypeRepresentation {
   public:
     enum Kind {
-        Scalar,
-        Struct,
-        Array
+        Scalar = JS_TYPEREPR_SCALAR_KIND,
+        Struct = JS_TYPEREPR_STRUCT_KIND,
+        Array = JS_TYPEREPR_ARRAY_KIND
     };
 
   protected:
     TypeRepresentation(Kind kind, size_t size, size_t align);
 
     size_t size_;
     size_t alignment_;
     Kind kind_;
 
     JSObject *addToTableOrFree(JSContext *cx, TypeRepresentationHash::AddPtr &p);
 
   private:
     static const Class class_;
     static void obj_trace(JSTracer *trace, JSObject *object);
     static void obj_finalize(js::FreeOp *fop, JSObject *object);
 
-    js::HeapPtrObject ownerObject_;
+    HeapPtrObject ownerObject_;
     void traceFields(JSTracer *tracer);
 
   public:
     size_t size() const { return size_; }
     size_t alignment() const { return alignment_; }
     Kind kind() const { return kind_; }
     JSObject *ownerObject() const { return ownerObject_.get(); }
 
@@ -154,30 +155,30 @@ class TypeRepresentation {
 
     void mark(JSTracer *tracer);
 };
 
 class ScalarTypeRepresentation : public TypeRepresentation {
   public:
     // Must match order of JS_FOR_EACH_SCALAR_TYPE_REPR below
     enum Type {
-        TYPE_INT8 = 0,
-        TYPE_UINT8,
-        TYPE_INT16,
-        TYPE_UINT16,
-        TYPE_INT32,
-        TYPE_UINT32,
-        TYPE_FLOAT32,
-        TYPE_FLOAT64,
+        TYPE_INT8 = JS_SCALARTYPEREPR_INT8,
+        TYPE_UINT8 = JS_SCALARTYPEREPR_UINT8,
+        TYPE_INT16 = JS_SCALARTYPEREPR_INT16,
+        TYPE_UINT16 = JS_SCALARTYPEREPR_UINT16,
+        TYPE_INT32 = JS_SCALARTYPEREPR_INT32,
+        TYPE_UINT32 = JS_SCALARTYPEREPR_UINT32,
+        TYPE_FLOAT32 = JS_SCALARTYPEREPR_FLOAT32,
+        TYPE_FLOAT64 = JS_SCALARTYPEREPR_FLOAT64,
 
         /*
          * Special type that's a uint8_t, but assignments are clamped to 0 .. 255.
          * Treat the raw data type as a uint8_t.
          */
-        TYPE_UINT8_CLAMPED,
+        TYPE_UINT8_CLAMPED = JS_SCALARTYPEREPR_UINT8_CLAMPED,
     };
     static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
 
   private:
     // so TypeRepresentation can call appendStringScalar() etc
     friend class TypeRepresentation;
 
     Type type_;
@@ -193,26 +194,32 @@ class ScalarTypeRepresentation : public 
     }
 
     bool convertValue(JSContext *cx, HandleValue value, MutableHandleValue vp);
 
     static const char *typeName(Type type);
     static JSObject *Create(JSContext *cx, Type type);
 };
 
-// Must be in same order as the enum:
+// Enumerates the cases of ScalarTypeRepresentation::Type which have
+// unique C representation. In particular, omits Uint8Clamped since it
+// is just a Uint8.
+#define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)                     \
+    macro_(ScalarTypeRepresentation::TYPE_INT8,    int8_t,   int8)            \
+    macro_(ScalarTypeRepresentation::TYPE_UINT8,   uint8_t,  uint8)           \
+    macro_(ScalarTypeRepresentation::TYPE_INT16,   int16_t,  int16)           \
+    macro_(ScalarTypeRepresentation::TYPE_UINT16,  uint16_t, uint16)          \
+    macro_(ScalarTypeRepresentation::TYPE_INT32,   int32_t,  int32)           \
+    macro_(ScalarTypeRepresentation::TYPE_UINT32,  uint32_t, uint32)          \
+    macro_(ScalarTypeRepresentation::TYPE_FLOAT32, float,    float32)         \
+    macro_(ScalarTypeRepresentation::TYPE_FLOAT64, double,   float64)
+
+// Must be in same order as the enum ScalarTypeRepresentation::Type:
 #define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_)                                    \
-    macro_(ScalarTypeRepresentation::TYPE_INT8,    int8_t,   int8)              \
-    macro_(ScalarTypeRepresentation::TYPE_UINT8,   uint8_t,  uint8)             \
-    macro_(ScalarTypeRepresentation::TYPE_INT16,   int16_t,  int16)             \
-    macro_(ScalarTypeRepresentation::TYPE_UINT16,  uint16_t, uint16)            \
-    macro_(ScalarTypeRepresentation::TYPE_INT32,   int32_t,  int32)             \
-    macro_(ScalarTypeRepresentation::TYPE_UINT32,  uint32_t, uint32)            \
-    macro_(ScalarTypeRepresentation::TYPE_FLOAT32, float,    float32)           \
-    macro_(ScalarTypeRepresentation::TYPE_FLOAT64, double,   float64)           \
+    JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)                           \
     macro_(ScalarTypeRepresentation::TYPE_UINT8_CLAMPED, uint8_t, uint8Clamped)
 
 class ArrayTypeRepresentation : public TypeRepresentation {
   private:
     // so TypeRepresentation can call appendStringArray() etc
     friend class TypeRepresentation;
 
     TypeRepresentation *element_;
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -52,24 +52,16 @@ const Class js::TypedObjectClass = {
  * The value is located at the offset `offset` in the binary block
  * associated with `owner`, which must be a BinaryBlock object.
  *
  * Upon success, the result is stored in `vp`.
  */
 static bool Reify(JSContext *cx, TypeRepresentation *typeRepr, HandleObject type,
                   HandleObject owner, size_t offset, MutableHandleValue vp);
 
-/*
- * ConvertAndCopyTo() converts `from` to type `type` and stores the result in
- * `mem`, which MUST be pre-allocated to the appropriate size for instances of
- * `type`.
- */
-static bool ConvertAndCopyTo(JSContext *cx, TypeRepresentation *typeRepr,
-                             HandleValue from, uint8_t *mem);
-
 static void
 ReportCannotConvertTo(JSContext *cx, HandleValue fromValue, const char *toType)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
                          InformalValueTypeName(fromValue), toType);
 }
 
 static void
@@ -119,173 +111,195 @@ ToObjectIfObject(HandleValue value)
 {
     if (!value.isObject())
         return nullptr;
 
     return &value.toObject();
 }
 
 static inline bool
-IsNumericType(HandleObject type)
+IsNumericTypeObject(JSObject &type)
 {
-    return type &&
-           &NumericTypeClasses[0] <= type->getClass() &&
-           type->getClass() < &NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX];
+    return &NumericTypeClasses[0] <= type.getClass() &&
+           type.getClass() < &NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX];
 }
 
 static inline bool
-IsArrayType(HandleObject type)
+IsArrayTypeObject(JSObject &type)
 {
-    return type && type->hasClass(&ArrayType::class_);
+    return type.hasClass(&ArrayType::class_);
 }
 
 static inline bool
-IsStructType(HandleObject type)
+IsStructTypeObject(JSObject &type)
 {
-    return type && type->hasClass(&StructType::class_);
+    return type.hasClass(&StructType::class_);
 }
 
 static inline bool
-IsComplexType(HandleObject type)
+IsComplexTypeObject(JSObject &type)
 {
-    return IsArrayType(type) || IsStructType(type);
+    return IsArrayTypeObject(type) || IsStructTypeObject(type);
 }
 
 static inline bool
-IsBinaryType(HandleObject type)
+IsTypeObject(JSObject &type)
 {
-    return IsNumericType(type) || IsComplexType(type);
+    return IsNumericTypeObject(type) || IsComplexTypeObject(type);
 }
 
 static inline bool
-IsBlock(HandleObject obj)
+IsBlock(JSObject &obj)
 {
-    return obj && obj->hasClass(&BinaryBlock::class_);
+    return obj.hasClass(&BinaryBlock::class_);
 }
 
 static inline uint8_t *
-BlockMem(HandleObject val)
+BlockMem(JSObject &val)
 {
     JS_ASSERT(IsBlock(val));
-    return (uint8_t*) val->getPrivate();
+    return (uint8_t*) val.getPrivate();
 }
 
 /*
  * Given a user-visible type descriptor object, returns the
  * owner object for the TypeRepresentation* that we use internally.
  */
 static JSObject *
-typeRepresentationOwnerObj(HandleObject typeObj)
+typeRepresentationOwnerObj(JSObject &typeObj)
 {
-    JS_ASSERT(IsBinaryType(typeObj));
-    return &typeObj->getFixedSlot(SLOT_TYPE_REPR).toObject();
+    JS_ASSERT(IsTypeObject(typeObj));
+    return &typeObj.getReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR).toObject();
 }
 
 /*
  * Given a user-visible type descriptor object, returns the
  * TypeRepresentation* that we use internally.
  *
  * Note: this pointer is valid only so long as `typeObj` remains rooted.
  */
 static TypeRepresentation *
-typeRepresentation(HandleObject typeObj)
+typeRepresentation(JSObject &typeObj)
 {
     return TypeRepresentation::fromOwnerObject(typeRepresentationOwnerObj(typeObj));
 }
 
 static inline JSObject *
-GetType(HandleObject block)
+GetType(JSObject &block)
 {
     JS_ASSERT(IsBlock(block));
-    return &block->getFixedSlot(SLOT_DATATYPE).toObject();
+    return &block.getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_OBJ).toObject();
 }
 
 /*
- * Overwrites the contents of `block` with the converted form of `val`
+ * Overwrites the contents of `block` at offset `offset` with `val`
+ * converted to the type `typeObj`
  */
 static bool
-ConvertAndCopyTo(JSContext *cx, HandleValue val, HandleObject block)
+ConvertAndCopyTo(JSContext *cx,
+                 HandleObject typeObj,
+                 HandleObject block,
+                 int32_t offset,
+                 HandleValue val)
 {
-    uint8_t *memory = BlockMem(block);
-    RootedObject type(cx, GetType(block));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
-    return ConvertAndCopyTo(cx, typeRepr, val, memory);
+    RootedFunction func(
+        cx, SelfHostedFunction(cx, cx->names().ConvertAndCopyTo));
+    if (!func)
+        return false;
+
+    InvokeArgs args(cx);
+    if (!args.init(5))
+        return false;
+
+    args.setCallee(ObjectValue(*func));
+    args[0].setObject(*typeRepresentationOwnerObj(*typeObj));
+    args[1].setObject(*typeObj);
+    args[2].setObject(*block);
+    args[3].setInt32(offset);
+    args[4].set(val);
+
+    return Invoke(cx, args);
+}
+
+static bool
+ConvertAndCopyTo(JSContext *cx, HandleObject block, HandleValue val)
+{
+    RootedObject type(cx, GetType(*block));
+    return ConvertAndCopyTo(cx, type, block, 0, val);
 }
 
 static inline size_t
-TypeSize(HandleObject type)
+TypeSize(JSObject &type)
 {
     return typeRepresentation(type)->size();
 }
 
 static inline size_t
-BlockSize(JSContext *cx, HandleObject val)
+BlockSize(JSObject &val)
 {
-    RootedObject type(cx, GetType(val));
-    return TypeSize(type);
+    return TypeSize(*GetType(val));
 }
 
 static inline bool
-IsBlockOfKind(JSContext *cx, HandleObject obj, TypeRepresentation::Kind kind)
+IsBlockOfKind(JSObject &obj, TypeRepresentation::Kind kind)
 {
     if (!IsBlock(obj))
         return false;
-    RootedObject objType(cx, GetType(obj));
-    TypeRepresentation *repr = typeRepresentation(objType);
+    TypeRepresentation *repr = typeRepresentation(*GetType(obj));
     return repr->kind() == kind;
 }
 
 static inline bool
-IsBinaryArray(JSContext *cx, HandleObject obj)
+IsBinaryArray(JSObject &obj)
 {
-    return IsBlockOfKind(cx, obj, TypeRepresentation::Array);
+    return IsBlockOfKind(obj, TypeRepresentation::Array);
 }
 
 static inline bool
-IsBinaryStruct(JSContext *cx, HandleObject obj)
+IsBinaryStruct(JSObject &obj)
 {
-    return IsBlockOfKind(cx, obj, TypeRepresentation::Struct);
+    return IsBlockOfKind(obj, TypeRepresentation::Struct);
 }
 
 static bool
 TypeEquivalent(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsBinaryType(thisObj)) {
+    if (!thisObj || !IsTypeObject(*thisObj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_INCOMPATIBLE_PROTO,
                              "Type", "equivalent",
                              InformalValueTypeName(args.thisv()));
         return false;
     }
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "Type.equivalent", "1", "s");
         return false;
     }
 
     RootedObject otherObj(cx, ToObjectIfObject(args[0]));
-    if (!otherObj || !IsBinaryType(otherObj)) {
+    if (!otherObj || !IsTypeObject(*otherObj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPEDOBJECT_NOT_TYPE_OBJECT);
         return false;
     }
 
-    TypeRepresentation *thisRepr = typeRepresentation(thisObj);
-    TypeRepresentation *otherRepr = typeRepresentation(otherObj);
+    TypeRepresentation *thisRepr = typeRepresentation(*thisObj);
+    TypeRepresentation *otherRepr = typeRepresentation(*otherObj);
     args.rval().setBoolean(thisRepr == otherRepr);
     return true;
 }
 
 #define BINARYDATA_NUMERIC_CLASSES(constant_, type_, name_)                   \
 {                                                                             \
     #name_,                                                                   \
-    JSCLASS_HAS_RESERVED_SLOTS(TYPE_RESERVED_SLOTS),                          \
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEOBJ_SCALAR_SLOTS),                      \
     JS_PropertyStub,       /* addProperty */                                  \
     JS_DeletePropertyStub, /* delProperty */                                  \
     JS_PropertyStub,       /* getProperty */                                  \
     JS_StrictPropertyStub, /* setProperty */                                  \
     JS_EnumerateStub,                                                         \
     JS_ResolveStub,                                                           \
     JS_ConvertStub,                                                           \
     nullptr,                                                                  \
@@ -303,120 +317,74 @@ const Class js::NumericTypeClasses[Scala
 #define BINARYDATA_TYPE_TO_CLASS(constant_, type_, name_)                     \
     template <>                                                               \
     const Class *                                                             \
     NumericType<constant_, type_>::typeToClass()                              \
     {                                                                         \
         return &NumericTypeClasses[constant_];                                \
     }
 
+template <typename T>
+static T ConvertScalar(double d)
+{
+    if (TypeIsFloatingPoint<T>()) {
+        return T(d);
+    } else if (TypeIsUnsigned<T>()) {
+        uint32_t n = ToUint32(d);
+        return T(n);
+    } else {
+        int32_t n = ToInt32(d);
+        return T(n);
+    }
+}
+
+
 /**
  * This namespace declaration is required because of a weird 'specialization in
  * different namespace' error that happens in gcc, only on type specialized
  * template functions.
  */
 namespace js {
 JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_TYPE_TO_CLASS);
 
 template <ScalarTypeRepresentation::Type type, typename T>
 JS_ALWAYS_INLINE
 bool NumericType<type, T>::reify(JSContext *cx, void *mem, MutableHandleValue vp)
 {
     vp.setNumber((double)*((T*)mem) );
     return true;
 }
 
-template <ScalarTypeRepresentation::Type type, typename T>
-bool
-NumericType<type, T>::convert(JSContext *cx, HandleValue val, T* converted)
-{
-    if (val.isInt32()) {
-        *converted = T(val.toInt32());
-        return true;
-    }
-
-    double d;
-    if (!ToDoubleForTypedArray(cx, val, &d))
-        return false;
-
-    if (TypeIsFloatingPoint<T>()) {
-        *converted = T(d);
-    } else if (TypeIsUnsigned<T>()) {
-        uint32_t n = ToUint32(d);
-        *converted = T(n);
-    } else {
-        int32_t n = ToInt32(d);
-        *converted = T(n);
-    }
-
-    return true;
-}
-
-template <>
-bool
-NumericType<ScalarTypeRepresentation::TYPE_UINT8_CLAMPED, uint8_t>::convert(
-    JSContext *cx, HandleValue val, uint8_t* converted)
-{
-    double d;
-    if (val.isInt32()) {
-        d = val.toInt32();
-    } else {
-        if (!ToDoubleForTypedArray(cx, val, &d))
-            return false;
-    }
-    *converted = ClampDoubleToUint8(d);
-    return true;
-}
-
 } // namespace js
 
 template<ScalarTypeRepresentation::Type N>
 static bool
 NumericTypeToString(JSContext *cx, unsigned int argc, Value *vp)
 {
     static_assert(N < ScalarTypeRepresentation::TYPE_MAX, "bad numeric type");
     CallArgs args = CallArgsFromVp(argc, vp);
     JSString *s = JS_NewStringCopyZ(cx, ScalarTypeRepresentation::typeName(N));
     if (!s)
         return false;
     args.rval().setString(s);
     return true;
 }
 
 static bool
-ConvertAndCopyScalarTo(JSContext *cx, ScalarTypeRepresentation *typeRepr,
-                       HandleValue from, uint8_t *mem)
-{
-#define CONVERT_CASES(constant_, type_, name_)                                \
-    case constant_: {                                                         \
-        type_ temp;                                                           \
-        if (!NumericType<constant_, type_>::convert(cx, from, &temp))         \
-            return false;                                                     \
-        memcpy(mem, &temp, sizeof(type_));                                    \
-        return true; }
-
-    switch (typeRepr->type()) {
-        JS_FOR_EACH_SCALAR_TYPE_REPR(CONVERT_CASES)
-    }
-#undef CONVERT_CASES
-    return false;
-}
-
-static bool
 ReifyScalar(JSContext *cx, ScalarTypeRepresentation *typeRepr, HandleObject type,
             HandleObject owner, size_t offset, MutableHandleValue to)
 {
     JS_ASSERT(&NumericTypeClasses[0] <= type->getClass() &&
               type->getClass() <= &NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX]);
 
     switch (typeRepr->type()) {
 #define REIFY_CASES(constant_, type_, name_)                                  \
         case constant_:                                                       \
           return NumericType<constant_, type_>::reify(                        \
-                cx, BlockMem(owner) + offset, to);
+                cx, BlockMem(*owner) + offset, to);
         JS_FOR_EACH_SCALAR_TYPE_REPR(REIFY_CASES)
     }
 #undef REIFY_CASES
 
     MOZ_ASSUME_UNREACHABLE("Invalid type");
     return false;
 }
 
@@ -426,27 +394,25 @@ NumericType<type, T>::call(JSContext *cx
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                              args.callee().getClass()->name, "0", "s");
         return false;
     }
 
-    RootedValue arg(cx, args[0]);
-    T answer;
-    if (!convert(cx, arg, &answer))
-        return false; // convert() raises TypeError.
+    double number;
+    if (!ToNumber(cx, args[0], &number))
+        return false;
 
-    RootedValue reified(cx);
-    if (!NumericType<type, T>::reify(cx, &answer, &reified)) {
-        return false;
-    }
+    if (type == ScalarTypeRepresentation::TYPE_UINT8_CLAMPED)
+        number = ClampDoubleToUint8(number);
 
-    args.rval().set(reified);
+    T converted = ConvertScalar<T>(number);
+    args.rval().setNumber((double) converted);
     return true;
 }
 
 /*
  * For code like:
  *
  *   var A = new TypedObject.ArrayType(uint8, 10);
  *   var S = new TypedObject.StructType({...});
@@ -564,17 +530,17 @@ CreateMetaTypeObject(JSContext *cx,
         return nullptr;
     }
 
     return ctor;
 }
 
 const Class ArrayType::class_ = {
     "ArrayType",
-    JSCLASS_HAS_RESERVED_SLOTS(ARRAY_TYPE_RESERVED_SLOTS),
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEOBJ_ARRAY_SLOTS),
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     nullptr,
@@ -603,151 +569,89 @@ const JSFunctionSpec ArrayType::typedObj
     JS_FN("subarray", ArrayType::subarray, 2, 0),
     {"forEach", {nullptr, nullptr}, 1, 0, "ArrayForEach"},
     JS_FS_END
 };
 
 static JSObject *
 ArrayElementType(HandleObject array)
 {
-    JS_ASSERT(IsArrayType(array));
-    return &array->getFixedSlot(SLOT_ARRAY_ELEM_TYPE).toObject();
+    JS_ASSERT(IsArrayTypeObject(*array));
+    return &array->getReservedSlot(JS_TYPEOBJ_SLOT_ARRAY_ELEM_TYPE).toObject();
 }
 
 static bool
-ConvertAndCopyArrayTo(JSContext *cx, ArrayTypeRepresentation *typeRepr,
-                      HandleValue from, uint8_t *mem)
+FillTypedArrayWithValue(JSContext *cx, HandleObject array, HandleValue val)
 {
-    if (!from.isObject()) {
-        ReportCannotConvertTo(cx, from, typeRepr);
-        return false;
-    }
+    JS_ASSERT(IsBinaryArray(*array));
 
-    // Check for the fast case, where we can just memcpy:
-    RootedObject fromObject(cx, &from.toObject());
-    if (IsBlock(fromObject)) {
-        RootedObject fromType(cx, GetType(fromObject));
-        TypeRepresentation *fromTypeRepr = typeRepresentation(fromType);
-        if (typeRepr == fromTypeRepr) {
-            memcpy(mem, BlockMem(fromObject), typeRepr->size());
-            return true;
-        }
-    }
-
-    // Otherwise, use a structural comparison:
-    RootedValue fromLenVal(cx);
-    if (!JSObject::getProperty(cx, fromObject, fromObject,
-                               cx->names().length, &fromLenVal))
+    RootedFunction func(
+        cx, SelfHostedFunction(cx, cx->names().FillTypedArrayWithValue));
+    if (!func)
         return false;
 
-    if (!fromLenVal.isInt32()) {
-        ReportCannotConvertTo(cx, from, typeRepr);
-        return false;
-    }
-
-    int32_t fromLenInt32 = fromLenVal.toInt32();
-    if (fromLenInt32 < 0) {
-        ReportCannotConvertTo(cx, from, typeRepr);
-        return false;
-    }
-
-    size_t fromLen = (size_t) fromLenInt32;
-    if (typeRepr->length() != fromLen) {
-        ReportCannotConvertTo(cx, from, typeRepr);
-        return false;
-    }
-
-    TypeRepresentation *elementType = typeRepr->element();
-    uint8_t *p = mem;
-
-    RootedValue fromElem(cx);
-    for (size_t i = 0; i < fromLen; i++) {
-        if (!JSObject::getElement(cx, fromObject, fromObject, i, &fromElem))
-            return false;
-
-        if (!ConvertAndCopyTo(cx, elementType, fromElem, p))
-            return false;
-
-        p += elementType->size();
-    }
-
-    return true;
-}
-
-static bool
-FillBinaryArrayWithValue(JSContext *cx, HandleObject array, HandleValue val)
-{
-    JS_ASSERT(IsBinaryArray(cx, array));
-
-    // set array[0] = [[Convert]](val)
-    RootedObject type(cx, GetType(array));
-    ArrayTypeRepresentation *typeRepr = typeRepresentation(type)->asArray();
-    uint8_t *base = BlockMem(array);
-    if (!ConvertAndCopyTo(cx, typeRepr->element(), val, base))
+    InvokeArgs args(cx);
+    if (!args.init(2))
         return false;
 
-    // copy a[0] into remaining indices.
-    size_t elementSize = typeRepr->element()->size();
-    for (size_t i = 1; i < typeRepr->length(); i++) {
-        uint8_t *dest = base + elementSize * i;
-        memcpy(dest, base, elementSize);
-    }
-
-    return true;
+    args.setCallee(ObjectValue(*func));
+    args[0].setObject(*array);
+    args[1].set(val);
+    return Invoke(cx, args);
 }
 
 bool
 ArrayType::repeat(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "repeat()", "0", "s");
         return false;
     }
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsArrayType(thisObj)) {
+    if (!thisObj || !IsArrayTypeObject(*thisObj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_INCOMPATIBLE_PROTO,
                              "ArrayType", "repeat",
                              InformalValueTypeName(args.thisv()));
         return false;
     }
 
     RootedObject binaryArray(cx, BinaryBlock::createZeroed(cx, thisObj));
     if (!binaryArray)
         return false;
 
     RootedValue val(cx, args[0]);
-    if (!FillBinaryArrayWithValue(cx, binaryArray, val))
+    if (!FillTypedArrayWithValue(cx, binaryArray, val))
         return false;
 
     args.rval().setObject(*binaryArray);
     return true;
 }
 
 bool
 ArrayType::toSource(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsArrayType(thisObj)) {
+    if (!thisObj || !IsArrayTypeObject(*thisObj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_INCOMPATIBLE_PROTO,
                              "ArrayType", "toSource",
                              InformalValueTypeName(args.thisv()));
         return false;
     }
 
     StringBuffer contents(cx);
-    if (!typeRepresentation(thisObj)->appendString(cx, contents))
+    if (!typeRepresentation(*thisObj)->appendString(cx, contents))
         return false;
 
     RootedString result(cx, contents.finishString());
     if (!result)
         return false;
 
     args.rval().setString(result);
     return true;
@@ -787,23 +691,23 @@ ArrayType::subarray(JSContext *cx, unsig
 
     if (!args[0].isInt32()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_TYPEDOBJECT_SUBARRAY_INTEGER_ARG, "1");
         return false;
     }
 
     RootedObject thisObj(cx, &args.thisv().toObject());
-    if (!IsBinaryArray(cx, thisObj)) {
+    if (!IsBinaryArray(*thisObj)) {
         ReportCannotConvertTo(cx, thisObj, "binary array");
         return false;
     }
 
-    RootedObject type(cx, GetType(thisObj));
-    ArrayTypeRepresentation *typeRepr = typeRepresentation(type)->asArray();
+    RootedObject type(cx, GetType(*thisObj));
+    ArrayTypeRepresentation *typeRepr = typeRepresentation(*type)->asArray();
     size_t length = typeRepr->length();
 
     int32_t begin = args[0].toInt32();
     int32_t end = length;
 
     if (args.length() >= 2) {
         if (!args[1].isInt32()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
@@ -855,40 +759,40 @@ ArrayFillSubarray(JSContext *cx, unsigne
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "fill()", "0", "s");
         return false;
     }
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsBinaryArray(cx, thisObj)) {
+    if (!thisObj || !IsBinaryArray(*thisObj)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_INCOMPATIBLE_PROTO,
                              "ArrayType", "fill",
                              InformalValueTypeName(args.thisv()));
         return false;
     }
 
     Value funArrayTypeVal = GetFunctionNativeReserved(&args.callee(), 0);
     JS_ASSERT(funArrayTypeVal.isObject());
 
-    RootedObject type(cx, GetType(thisObj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*thisObj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
     RootedObject funArrayType(cx, &funArrayTypeVal.toObject());
-    TypeRepresentation *funArrayTypeRepr = typeRepresentation(funArrayType);
+    TypeRepresentation *funArrayTypeRepr = typeRepresentation(*funArrayType);
     if (typeRepr != funArrayTypeRepr) {
         RootedValue thisObjValue(cx, ObjectValue(*thisObj));
         ReportCannotConvertTo(cx, thisObjValue, funArrayTypeRepr);
         return false;
     }
 
     args.rval().setUndefined();
     RootedValue val(cx, args[0]);
-    return FillBinaryArrayWithValue(cx, thisObj, val);
+    return FillTypedArrayWithValue(cx, thisObj, val);
 }
 
 static bool
 InitializeCommonTypeDescriptorProperties(JSContext *cx,
                                          HandleObject obj,
                                          HandleObject typeReprOwnerObj)
 {
     TypeRepresentation *typeRepr =
@@ -936,19 +840,19 @@ InitializeCommonTypeDescriptorProperties
 
 JSObject *
 ArrayType::create(JSContext *cx,
                   HandleObject metaTypeObject,
                   HandleObject elementType,
                   size_t length)
 {
     JS_ASSERT(elementType);
-    JS_ASSERT(IsBinaryType(elementType));
+    JS_ASSERT(IsTypeObject(*elementType));
 
-    TypeRepresentation *elementTypeRepr = typeRepresentation(elementType);
+    TypeRepresentation *elementTypeRepr = typeRepresentation(*elementType);
     RootedObject typeReprObj(
         cx, ArrayTypeRepresentation::Create(cx, elementTypeRepr, length));
     if (!typeReprObj)
         return nullptr;
 
     RootedValue prototypeVal(cx);
     if (!JSObject::getProperty(cx, metaTypeObject, metaTypeObject,
                                cx->names().prototype,
@@ -958,25 +862,27 @@ ArrayType::create(JSContext *cx,
     }
     JS_ASSERT(prototypeVal.isObject()); // immutable binding
 
     RootedObject obj(
         cx, NewObjectWithClassProto(cx, &ArrayType::class_,
                                     &prototypeVal.toObject(), cx->global()));
     if (!obj)
         return nullptr;
-    obj->initFixedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
+    obj->initReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR,
+                          ObjectValue(*typeReprObj));
 
     RootedValue elementTypeVal(cx, ObjectValue(*elementType));
     if (!JSObject::defineProperty(cx, obj, cx->names().elementType,
                                   elementTypeVal, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
-    obj->initFixedSlot(SLOT_ARRAY_ELEM_TYPE, elementTypeVal);
+    obj->initReservedSlot(JS_TYPEOBJ_SLOT_ARRAY_ELEM_TYPE,
+                          elementTypeVal);
 
     RootedValue lengthVal(cx, Int32Value(length));
     if (!JSObject::defineProperty(cx, obj, cx->names().length,
                                   lengthVal, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
     if (!InitializeCommonTypeDescriptorProperties(cx, obj, typeReprObj))
@@ -1021,17 +927,17 @@ ArrayType::construct(JSContext *cx, unsi
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
         return false;
     }
 
     RootedObject arrayTypeGlobal(cx, &args.callee());
     RootedObject elementType(cx, &args[0].toObject());
 
-    if (!IsBinaryType(elementType)) {
+    if (!IsTypeObject(*elementType)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
         return false;
     }
 
     if (!args[1].isInt32()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
@@ -1053,17 +959,17 @@ ArrayType::construct(JSContext *cx, unsi
 }
 
 /*********************************
  * Structs
  *********************************/
 
 const Class StructType::class_ = {
     "StructType",
-    JSCLASS_HAS_RESERVED_SLOTS(STRUCT_TYPE_RESERVED_SLOTS) |
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEOBJ_STRUCT_SLOTS) |
     JSCLASS_HAS_PRIVATE, // used to store FieldList
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
@@ -1087,55 +993,16 @@ const JSFunctionSpec StructType::typeObj
 const JSPropertySpec StructType::typedObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructType::typedObjectMethods[] = {
     JS_FS_END
 };
 
-static bool
-ConvertAndCopyStructTo(JSContext *cx,
-                       StructTypeRepresentation *typeRepr,
-                       HandleValue from,
-                       uint8_t *mem)
-{
-    if (!from.isObject()) {
-        ReportCannotConvertTo(cx, from, typeRepr);
-        return false;
-    }
-
-    // Check for the fast case, where we can just memcpy:
-    RootedObject fromObject(cx, &from.toObject());
-    if (IsBlock(fromObject)) {
-        RootedObject fromType(cx, GetType(fromObject));
-        TypeRepresentation *fromTypeRepr = typeRepresentation(fromType);
-        if (typeRepr == fromTypeRepr) {
-            memcpy(mem, BlockMem(fromObject), typeRepr->size());
-            return true;
-        }
-    }
-
-    // Otherwise, convert the properties one by one.
-    RootedId fieldId(cx);
-    RootedValue fromProp(cx);
-    for (size_t i = 0; i < typeRepr->fieldCount(); i++) {
-        const StructField &field = typeRepr->field(i);
-
-        fieldId = field.id;
-        if (!JSObject::getGeneric(cx, fromObject, fromObject, fieldId, &fromProp))
-            return false;
-
-        if (!ConvertAndCopyTo(cx, field.typeRepr, fromProp,
-                              mem + field.offset))
-            return false;
-    }
-    return true;
-}
-
 /*
  * NOTE: layout() does not check for duplicates in fields since the arguments
  * to StructType are currently passed as an object literal. Fix this if it
  * changes to taking an array of arrays.
  */
 bool
 StructType::layout(JSContext *cx, HandleObject structType, HandleObject fields)
 {
@@ -1157,50 +1024,51 @@ StructType::layout(JSContext *cx, Handle
         uint32_t index;
         if (js_IdIsIndex(id, &index)) {
             RootedValue idValue(cx, IdToJsval(id));
             ReportCannotConvertTo(cx, idValue, "StructType field name");
             return false;
         }
 
         RootedObject fieldType(cx, ToObjectIfObject(fieldTypeVal));
-        if (!fieldType || !IsBinaryType(fieldType)) {
+        if (!fieldType || !IsTypeObject(*fieldType)) {
             ReportCannotConvertTo(cx, fieldTypeVal, "StructType field specifier");
             return false;
         }
 
         if (!fieldTypeObjs.append(fieldTypeVal)) {
             js_ReportOutOfMemory(cx);
             return false;
         }
 
-        if (!fieldTypeReprObjs.append(typeRepresentationOwnerObj(fieldType))) {
+        if (!fieldTypeReprObjs.append(typeRepresentationOwnerObj(*fieldType))) {
             js_ReportOutOfMemory(cx);
             return false;
         }
     }
 
     // Construct the `TypeRepresentation*`.
     RootedObject typeReprObj(
         cx, StructTypeRepresentation::Create(cx, ids, fieldTypeReprObjs));
     if (!typeReprObj)
         return false;
     StructTypeRepresentation *typeRepr =
         TypeRepresentation::fromOwnerObject(typeReprObj)->asStruct();
-    structType->initReservedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
+    structType->initReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR,
+                                 ObjectValue(*typeReprObj));
 
     // Construct for internal use an array with the type object for each field.
     RootedObject fieldTypeVec(
         cx, NewDenseCopiedArray(cx, fieldTypeObjs.length(),
                                 fieldTypeObjs.begin()));
     if (!fieldTypeVec)
         return false;
 
-    structType->initFixedSlot(SLOT_STRUCT_FIELD_TYPES,
-                             ObjectValue(*fieldTypeVec));
+    structType->initReservedSlot(JS_TYPEOBJ_SLOT_STRUCT_FIELD_TYPES,
+                                 ObjectValue(*fieldTypeVec));
 
     // Construct the fieldNames vector
     AutoValueVector fieldNameValues(cx);
     for (unsigned int i = 0; i < ids.length(); i++) {
         RootedValue value(cx, IdToValue(ids[i]));
         if (!fieldNameValues.append(value))
             return false;
     }
@@ -1277,17 +1145,17 @@ StructType::create(JSContext *cx, Handle
 
     if (!StructType::layout(cx, obj, fields))
         return nullptr;
 
     RootedObject fieldsProto(cx);
     if (!JSObject::getProto(cx, fields, &fieldsProto))
         return nullptr;
 
-    RootedObject typeReprObj(cx, typeRepresentationOwnerObj(obj));
+    RootedObject typeReprObj(cx, typeRepresentationOwnerObj(*obj));
     if (!InitializeCommonTypeDescriptorProperties(cx, obj, typeReprObj))
         return nullptr;
 
     RootedObject prototypeObj(
         cx, CreateComplexTypeInstancePrototype(cx, metaTypeObject));
     if (!prototypeObj)
         return nullptr;
 
@@ -1324,57 +1192,35 @@ StructType::construct(JSContext *cx, uns
 }
 
 bool
 StructType::toSource(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsStructType(thisObj)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                             JSMSG_INCOMPATIBLE_PROTO,
+    if (!thisObj || !IsStructTypeObject(*thisObj)) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
                              "StructType", "toSource",
                              InformalValueTypeName(args.thisv()));
         return false;
     }
 
     StringBuffer contents(cx);
-    if (!typeRepresentation(thisObj)->appendString(cx, contents))
+    if (!typeRepresentation(*thisObj)->appendString(cx, contents))
         return false;
 
     RootedString result(cx, contents.finishString());
     if (!result)
         return false;
 
     args.rval().setString(result);
     return true;
 }
 
-static bool
-ConvertAndCopyTo(JSContext *cx,
-                 TypeRepresentation *typeRepr,
-                 HandleValue from,
-                 uint8_t *mem)
-{
-    switch (typeRepr->kind()) {
-      case TypeRepresentation::Scalar:
-        return ConvertAndCopyScalarTo(cx, typeRepr->asScalar(), from, mem);
-
-      case TypeRepresentation::Array:
-        return ConvertAndCopyArrayTo(cx, typeRepr->asArray(), from, mem);
-
-      case TypeRepresentation::Struct:
-        return ConvertAndCopyStructTo(cx, typeRepr->asStruct(), from, mem);
-    }
-
-    MOZ_ASSUME_UNREACHABLE("Invalid kind");
-    return false;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 
 static bool
 ReifyComplex(JSContext *cx, HandleObject type, HandleObject owner,
              size_t offset, MutableHandleValue to)
 {
     RootedObject obj(cx, BinaryBlock::createDerived(cx, type, owner, offset));
     if (!obj)
@@ -1382,17 +1228,17 @@ ReifyComplex(JSContext *cx, HandleObject
     to.setObject(*obj);
     return true;
 }
 
 static bool
 Reify(JSContext *cx, TypeRepresentation *typeRepr, HandleObject type,
       HandleObject owner, size_t offset, MutableHandleValue to)
 {
-    JS_ASSERT(typeRepr == typeRepresentation(type));
+    JS_ASSERT(typeRepr == typeRepresentation(*type));
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         return ReifyScalar(cx, typeRepr->asScalar(), type, owner, offset, to);
       case TypeRepresentation::Struct:
       case TypeRepresentation::Array:
         return ReifyComplex(cx, type, owner, offset, to);
     }
     MOZ_ASSUME_UNREACHABLE("Invalid typeRepr kind");
@@ -1553,17 +1399,18 @@ DefineNumericClass(JSContext *cx,
                                                     funcProto, global));
     if (!numFun)
         return false;
 
     RootedObject typeReprObj(cx, ScalarTypeRepresentation::Create(cx, type));
     if (!typeReprObj)
         return false;
 
-    numFun->initFixedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
+    numFun->initReservedSlot(JS_TYPEOBJ_SLOT_TYPE_REPR,
+                             ObjectValue(*typeReprObj));
 
     if (!InitializeCommonTypeDescriptorProperties(cx, numFun, typeReprObj))
         return false;
 
     if (!JS_DefineFunction(cx, numFun, "toString",
                            NumericTypeToString<type>, 0, 0))
         return false;
 
@@ -1582,17 +1429,17 @@ DefineNumericClass(JSContext *cx,
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Binary blocks
 
 const Class BinaryBlock::class_ = {
     "BinaryBlock",
     Class::NON_NATIVE |
-    JSCLASS_HAS_RESERVED_SLOTS(BLOCK_RESERVED_SLOTS) |
+    JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEDOBJ_SLOTS) |
     JSCLASS_HAS_PRIVATE |
     JSCLASS_IMPLEMENTS_BARRIERS,
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
@@ -1632,20 +1479,20 @@ const Class BinaryBlock::class_ = {
     }
 };
 
 static bool
 ReportBlockTypeError(JSContext *cx,
                      const unsigned errorNumber,
                      HandleObject obj)
 {
-    JS_ASSERT(IsBlock(obj));
+    JS_ASSERT(IsBlock(*obj));
 
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     StringBuffer contents(cx);
     if (!typeRepr->appendString(cx, contents))
         return false;
 
     RootedString result(cx, contents.finishString());
     if (!result)
         return false;
@@ -1661,124 +1508,124 @@ ReportBlockTypeError(JSContext *cx,
     return false;
 }
 
 /* static */ void
 BinaryBlock::obj_trace(JSTracer *trace, JSObject *object)
 {
     JS_ASSERT(object->hasClass(&class_));
 
-    for (size_t i = 0; i < BLOCK_RESERVED_SLOTS; i++)
+    for (size_t i = 0; i < JS_TYPEDOBJ_SLOTS; i++)
         gc::MarkSlot(trace, &object->getReservedSlotRef(i), "BinaryBlockSlot");
 }
 
 /* static */ void
 BinaryBlock::obj_finalize(js::FreeOp *op, JSObject *obj)
 {
-    if (!obj->getFixedSlot(SLOT_BLOCKREFOWNER).isNull())
+    if (!obj->getReservedSlot(JS_TYPEDOBJ_SLOT_OWNER).isNull())
         return;
 
     if (void *mem = obj->getPrivate())
         op->free_(mem);
 }
 
 /* static */ JSObject *
 BinaryBlock::createNull(JSContext *cx, HandleObject type, HandleValue owner)
 {
-    JS_ASSERT(IsBinaryType(type));
+    JS_ASSERT(IsTypeObject(*type));
 
     RootedValue protoVal(cx);
     if (!JSObject::getProperty(cx, type, type,
                                cx->names().prototype, &protoVal))
         return nullptr;
 
     RootedObject obj(cx,
         NewObjectWithClassProto(cx, &class_, &protoVal.toObject(), nullptr));
-    obj->initFixedSlot(SLOT_DATATYPE, ObjectValue(*type));
-    obj->initFixedSlot(SLOT_BLOCKREFOWNER, owner);
+    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_OBJ, ObjectValue(*type));
+    obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, owner);
 
     // Tag the type object for this instance with the type
     // representation, if that has not been done already.
     if (cx->typeInferenceEnabled()) {
         RootedTypeObject typeObj(cx, obj->getType(cx));
         if (typeObj) {
-            TypeRepresentation *typeRepr = typeRepresentation(type);
+            TypeRepresentation *typeRepr = typeRepresentation(*type);
             if (!typeObj->addTypedObjectAddendum(cx, typeRepr))
                 return nullptr;
         }
     }
 
     return obj;
 }
 
 /* static */ JSObject *
 BinaryBlock::createZeroed(JSContext *cx, HandleObject type)
 {
     RootedValue owner(cx, NullValue());
     RootedObject obj(cx, createNull(cx, type, owner));
     if (!obj)
         return nullptr;
 
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
     size_t memsize = typeRepr->size();
     void *memory = JS_malloc(cx, memsize);
     if (!memory)
         return nullptr;
     memset(memory, 0, memsize);
     obj->setPrivate(memory);
     return obj;
 }
 
 /* static */ JSObject *
 BinaryBlock::createDerived(JSContext *cx, HandleObject type,
                            HandleObject owner, size_t offset)
 {
-    JS_ASSERT(IsBlock(owner));
-    JS_ASSERT(offset <= BlockSize(cx, owner));
-    JS_ASSERT(offset + TypeSize(type) <= BlockSize(cx, owner));
+    JS_ASSERT(IsBlock(*owner));
+    JS_ASSERT(offset <= BlockSize(*owner));
+    JS_ASSERT(offset + TypeSize(*type) <= BlockSize(*owner));
 
     RootedValue ownerValue(cx, ObjectValue(*owner));
     RootedObject obj(cx, createNull(cx, type, ownerValue));
     if (!obj)
         return nullptr;
 
-    obj->setPrivate(BlockMem(owner) + offset);
+    obj->setPrivate(BlockMem(*owner) + offset);
     return obj;
 }
 
 /* static */ bool
 BinaryBlock::construct(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject callee(cx, &args.callee());
-    JS_ASSERT(IsBinaryType(callee));
+    JS_ASSERT(IsTypeObject(*callee));
 
     RootedObject obj(cx, createZeroed(cx, callee));
     if (!obj)
         return false;
 
     if (argc == 1) {
         RootedValue initial(cx, args[0]);
-        if (!ConvertAndCopyTo(cx, initial, obj))
+        if (!ConvertAndCopyTo(cx, obj, initial))
             return false;
     }
 
     args.rval().setObject(*obj);
     return true;
 }
 
 bool
 BinaryBlock::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                 MutableHandleObject objp, MutableHandleShape propp)
 {
-    JS_ASSERT(IsBlock(obj));
+    JS_ASSERT(IsBlock(*obj));
 
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         break;
 
       case TypeRepresentation::Array: {
         uint32_t index;
         if (js_IdIsIndex(id, &index))
@@ -1788,20 +1635,20 @@ BinaryBlock::obj_lookupGeneric(JSContext
             MarkNonNativePropertyFound(propp);
             objp.set(obj);
             return true;
         }
         break;
       }
 
       case TypeRepresentation::Struct: {
-        RootedObject type(cx, GetType(obj));
-        JS_ASSERT(IsStructType(type));
+        RootedObject type(cx, GetType(*obj));
+        JS_ASSERT(IsStructTypeObject(*type));
         StructTypeRepresentation *typeRepr =
-            typeRepresentation(type)->asStruct();
+            typeRepresentation(*type)->asStruct();
         const StructField *field = typeRepr->fieldNamed(id);
         if (field) {
             MarkNonNativePropertyFound(propp);
             objp.set(obj);
             return true;
         }
         break;
       }
@@ -1827,17 +1674,17 @@ BinaryBlock::obj_lookupProperty(JSContex
     RootedId id(cx, NameToId(name));
     return obj_lookupGeneric(cx, obj, id, objp, propp);
 }
 
 bool
 BinaryBlock::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
                                 MutableHandleObject objp, MutableHandleShape propp)
 {
-    JS_ASSERT(IsBlock(obj));
+    JS_ASSERT(IsBlock(*obj));
     MarkNonNativePropertyFound(propp);
     objp.set(obj);
     return true;
 }
 
 static bool
 ReportPropertyError(JSContext *cx,
                     const unsigned errorNumber,
@@ -1898,31 +1745,61 @@ BinaryBlock::obj_defineElement(JSContext
 bool
 BinaryBlock::obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, HandleValue v,
                                PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
 }
 
+static JSObject *
+StructFieldType(JSContext *cx,
+                HandleObject type,
+                int32_t fieldIndex)
+{
+    JS_ASSERT(IsStructTypeObject(*type));
+
+    // Recover the original type object here (`field` contains
+    // only its canonical form). The difference is observable,
+    // e.g. in a program like:
+    //
+    //     var Point1 = new StructType({x:uint8, y:uint8});
+    //     var Point2 = new StructType({x:uint8, y:uint8});
+    //     var Line1 = new StructType({start:Point1, end: Point1});
+    //     var Line2 = new StructType({start:Point2, end: Point2});
+    //     var line1 = new Line1(...);
+    //     var line2 = new Line2(...);
+    //
+    // In this scenario, line1.start.type() === Point1 and
+    // line2.start.type() === Point2.
+    RootedObject fieldTypes(
+        cx, &type->getReservedSlot(JS_TYPEOBJ_SLOT_STRUCT_FIELD_TYPES).toObject());
+    RootedValue fieldTypeVal(cx);
+    if (!JSObject::getElement(cx, fieldTypes, fieldTypes,
+                              fieldIndex, &fieldTypeVal))
+        return nullptr;
+
+    return &fieldTypeVal.toObject();
+}
+
 bool
 BinaryBlock::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                              HandleId id, MutableHandleValue vp)
 {
-    JS_ASSERT(IsBlock(obj));
+    JS_ASSERT(IsBlock(*obj));
 
     // Dispatch elements to obj_getElement:
     uint32_t index;
     if (js_IdIsIndex(id, &index))
         return obj_getElement(cx, obj, receiver, index, vp);
 
     // Handle everything else here:
 
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         break;
 
       case TypeRepresentation::Array:
         if (JSID_IS_ATOM(id, cx->names().length)) {
             vp.setInt32(typeRepr->asArray()->length());
             return true;
@@ -1930,38 +1807,20 @@ BinaryBlock::obj_getGeneric(JSContext *c
         break;
 
       case TypeRepresentation::Struct: {
         StructTypeRepresentation *structTypeRepr = typeRepr->asStruct();
         const StructField *field = structTypeRepr->fieldNamed(id);
         if (!field)
             break;
 
-        // Recover the original type object here (`field` contains
-        // only its canonical form). The difference is observable,
-        // e.g. in a program like:
-        //
-        //     var Point1 = new StructType({x:uint8, y:uint8});
-        //     var Point2 = new StructType({x:uint8, y:uint8});
-        //     var Line1 = new StructType({start:Point1, end: Point1});
-        //     var Line2 = new StructType({start:Point2, end: Point2});
-        //     var line1 = new Line1(...);
-        //     var line2 = new Line2(...);
-        //
-        // In this scenario, line1.start.type() === Point1 and
-        // line2.start.type() === Point2.
-        RootedObject fieldTypes(
-            cx,
-            &type->getFixedSlot(SLOT_STRUCT_FIELD_TYPES).toObject());
-        RootedValue fieldTypeVal(cx);
-        if (!JSObject::getElement(cx, fieldTypes, fieldTypes,
-                                  field->index, &fieldTypeVal))
+        RootedObject fieldType(cx, StructFieldType(cx, type, field->index));
+        if (!fieldType)
             return false;
 
-        RootedObject fieldType(cx, &fieldTypeVal.toObject());
         return Reify(cx, field->typeRepr, fieldType, obj, field->offset, vp);
       }
     }
 
     RootedObject proto(cx, obj->getProto());
     if (!proto) {
         vp.setUndefined();
         return true;
@@ -1986,18 +1845,18 @@ BinaryBlock::obj_getElement(JSContext *c
     return obj_getElementIfPresent(cx, obj, receiver, index, vp, &present);
 }
 
 bool
 BinaryBlock::obj_getElementIfPresent(JSContext *cx, HandleObject obj,
                                      HandleObject receiver, uint32_t index,
                                      MutableHandleValue vp, bool *present)
 {
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
       case TypeRepresentation::Struct:
         break;
 
       case TypeRepresentation::Array: {
         *present = true;
@@ -2030,24 +1889,24 @@ BinaryBlock::obj_getSpecial(JSContext *c
                             MutableHandleValue vp)
 {
     RootedId id(cx, SPECIALID_TO_JSID(sid));
     return obj_getGeneric(cx, obj, receiver, id, vp);
 }
 
 bool
 BinaryBlock::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
-                             MutableHandleValue vp, bool strict)
+                            MutableHandleValue vp, bool strict)
 {
     uint32_t index;
     if (js_IdIsIndex(id, &index))
         return obj_setElement(cx, obj, index, vp, strict);
 
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case ScalarTypeRepresentation::Scalar:
         break;
 
       case ScalarTypeRepresentation::Array:
         if (JSID_IS_ATOM(id, cx->names().length)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage,
@@ -2056,18 +1915,21 @@ BinaryBlock::obj_setGeneric(JSContext *c
         }
         break;
 
       case ScalarTypeRepresentation::Struct: {
         const StructField *field = typeRepr->asStruct()->fieldNamed(id);
         if (!field)
             break;
 
-        uint8_t *loc = BlockMem(obj) + field->offset;
-        return ConvertAndCopyTo(cx, field->typeRepr, vp, loc);
+        RootedObject fieldType(cx, StructFieldType(cx, type, field->index));
+        if (!fieldType)
+            return false;
+
+        return ConvertAndCopyTo(cx, fieldType, obj, field->offset, vp);
       }
     }
 
     return ReportBlockTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, obj);
 }
 
 bool
 BinaryBlock::obj_setProperty(JSContext *cx, HandleObject obj,
@@ -2075,38 +1937,38 @@ BinaryBlock::obj_setProperty(JSContext *
                              bool strict)
 {
     RootedId id(cx, NameToId(name));
     return obj_setGeneric(cx, obj, id, vp, strict);
 }
 
 bool
 BinaryBlock::obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
-                             MutableHandleValue vp, bool strict)
+                            MutableHandleValue vp, bool strict)
 {
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case ScalarTypeRepresentation::Scalar:
       case ScalarTypeRepresentation::Struct:
         break;
 
       case ScalarTypeRepresentation::Array: {
         ArrayTypeRepresentation *arrayTypeRepr = typeRepr->asArray();
 
         if (index >= arrayTypeRepr->length()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage,
                                  nullptr, JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX);
             return false;
         }
 
+        RootedObject elementType(cx, ArrayElementType(type));
         size_t offset = arrayTypeRepr->element()->size() * index;
-        uint8_t *mem = BlockMem(obj) + offset;
-        return ConvertAndCopyTo(cx, arrayTypeRepr->element(), vp, mem);
+        return ConvertAndCopyTo(cx, elementType, obj, offset, vp);
       }
     }
 
     return ReportBlockTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, obj);
 }
 
 bool
 BinaryBlock::obj_setSpecial(JSContext *cx, HandleObject obj,
@@ -2117,18 +1979,18 @@ BinaryBlock::obj_setSpecial(JSContext *c
     return obj_setGeneric(cx, obj, id, vp, strict);
 }
 
 bool
 BinaryBlock::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                        HandleId id, unsigned *attrsp)
 {
     uint32_t index;
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         break;
 
       case TypeRepresentation::Array:
         if (js_IdIsIndex(id, &index)) {
             *attrsp = JSPROP_ENUMERATE | JSPROP_PERMANENT;
@@ -2156,18 +2018,18 @@ BinaryBlock::obj_getGenericAttributes(JS
 
     return JSObject::getGenericAttributes(cx, proto, id, attrsp);
 }
 
 static bool
 IsOwnId(JSContext *cx, HandleObject obj, HandleId id)
 {
     uint32_t index;
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         return false;
 
       case TypeRepresentation::Array:
         return js_IdIsIndex(id, &index) || JSID_IS_ATOM(id, cx->names().length);
 
@@ -2177,17 +2039,17 @@ IsOwnId(JSContext *cx, HandleObject obj,
 
     return false;
 }
 
 bool
 BinaryBlock::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                        HandleId id, unsigned *attrsp)
 {
-    RootedObject type(cx, GetType(obj));
+    RootedObject type(cx, GetType(*obj));
 
     if (IsOwnId(cx, obj, id))
         return ReportPropertyError(cx, JSMSG_CANT_REDEFINE_PROP, id);
 
     RootedObject proto(cx, obj->getProto());
     if (!proto) {
         *attrsp = 0;
         return true;
@@ -2247,18 +2109,18 @@ BinaryBlock::obj_deleteSpecial(JSContext
 }
 
 bool
 BinaryBlock::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                            MutableHandleValue statep, MutableHandleId idp)
 {
     uint32_t index;
 
-    RootedObject type(cx, GetType(obj));
-    TypeRepresentation *typeRepr = typeRepresentation(type);
+    RootedObject type(cx, GetType(*obj));
+    TypeRepresentation *typeRepr = typeRepresentation(*type);
 
     switch (typeRepr->kind()) {
       case TypeRepresentation::Scalar:
         switch (enum_op) {
           case JSENUMERATE_INIT_ALL:
           case JSENUMERATE_INIT:
             statep.setInt32(0);
             idp.set(INT_TO_JSID(0));
@@ -2325,10 +2187,103 @@ BinaryBlock::obj_enumerate(JSContext *cx
     }
 
     return true;
 }
 
 /* static */ size_t
 BinaryBlock::dataOffset()
 {
-    return JSObject::getPrivateDataOffset(BLOCK_RESERVED_SLOTS + 1);
+    return JSObject::getPrivateDataOffset(JS_TYPEDOBJ_SLOTS + 1);
+}
+
+bool
+js::ClampToUint8(ThreadSafeContext *, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JS_ASSERT(argc == 1);
+    JS_ASSERT(args[0].isNumber());
+    args.rval().setNumber(ClampDoubleToUint8(args[0].toNumber()));
+    return true;
+}
+
+const JSJitInfo js::ClampToUint8JitInfo =
+    JS_JITINFO_NATIVE_PARALLEL(
+        JSParallelNativeThreadSafeWrapper<js::ClampToUint8>);
+
+bool
+js::Memcpy(ThreadSafeContext *, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JS_ASSERT(args.length() == 5);
+    JS_ASSERT(args[0].isObject() && IsBlock(args[0].toObject()));
+    JS_ASSERT(args[1].isInt32());
+    JS_ASSERT(args[2].isObject() && IsBlock(args[2].toObject()));
+    JS_ASSERT(args[3].isInt32());
+    JS_ASSERT(args[4].isInt32());
+
+    uint8_t *target = BlockMem(args[0].toObject()) + args[1].toInt32();
+    uint8_t *source = BlockMem(args[2].toObject()) + args[3].toInt32();
+    int32_t size = args[4].toInt32();
+    memcpy(target, source, size);
+    args.rval().setUndefined();
+    return true;
 }
+
+const JSJitInfo js::MemcpyJitInfo =
+    JS_JITINFO_NATIVE_PARALLEL(
+        JSParallelNativeThreadSafeWrapper<js::Memcpy>);
+
+#define JS_STORE_SCALAR_CLASS_IMPL(_constant, T, _name)                       \
+bool                                                                          \
+js::StoreScalar##T::Func(ThreadSafeContext *, unsigned argc, Value *vp)       \
+{                                                                             \
+    CallArgs args = CallArgsFromVp(argc, vp);                                 \
+    JS_ASSERT(args.length() == 3);                                            \
+    JS_ASSERT(args[0].isObject() && IsBlock(args[0].toObject()));             \
+    JS_ASSERT(args[1].isInt32());                                             \
+    JS_ASSERT(args[2].isNumber());                                            \
+                                                                              \
+    int32_t offset = args[1].toInt32();                                       \
+                                                                              \
+    /* Should be guaranteed by the typed objects API: */                      \
+    JS_ASSERT(offset % MOZ_ALIGNOF(T) == 0);                                  \
+                                                                              \
+    T *target = (T*) (BlockMem(args[0].toObject()) + offset);                 \
+    double d = args[2].toNumber();                                            \
+    *target = ConvertScalar<T>(d);                                            \
+    args.rval().setUndefined();                                               \
+    return true;                                                              \
+}                                                                             \
+                                                                              \
+const JSJitInfo                                                               \
+js::StoreScalar##T::JitInfo =                                                 \
+    JS_JITINFO_NATIVE_PARALLEL(                                               \
+        JSParallelNativeThreadSafeWrapper<Func>);
+
+#define JS_LOAD_SCALAR_CLASS_IMPL(_constant, T, _name)                        \
+bool                                                                          \
+js::LoadScalar##T::Func(ThreadSafeContext *, unsigned argc, Value *vp)        \
+{                                                                             \
+    CallArgs args = CallArgsFromVp(argc, vp);                                 \
+    JS_ASSERT(args.length() == 2);                                            \
+    JS_ASSERT(args[0].isObject() && IsBlock(args[0].toObject()));             \
+    JS_ASSERT(args[1].isInt32());                                             \
+