Import Cobalt 19.lts.2.188191

Change-Id: Iecf408fd9658c695676701b6c8d53becd1304d67
diff --git a/src/cobalt/base/token.cc b/src/cobalt/base/token.cc
index c6b5443..ba5b852 100644
--- a/src/cobalt/base/token.cc
+++ b/src/cobalt/base/token.cc
@@ -19,6 +19,7 @@
 
 #include "base/logging.h"
 #include "base/memory/singleton.h"
+#include "base/string_piece.h"
 #include "base/synchronization/lock.h"
 
 namespace base {
@@ -54,12 +55,14 @@
 #if defined(BASE_HASH_USE_HASH_STRUCT)
 
 uint32 hash(const char* str) {
-  return BASE_HASH_NAMESPACE::hash<const char*>()(str);
+  return BASE_HASH_NAMESPACE::hash<base::StringPiece>()(str);
 }
 
 #else
 
-uint32 hash(const char* str) { return BASE_HASH_NAMESPACE::hash_value(str); }
+uint32 hash(const char* str) {
+  return BASE_HASH_NAMESPACE::hash_value(base::StringPiece(str));
+}
 
 #endif  // COMPILER
 
diff --git a/src/cobalt/black_box_tests/black_box_tests.py b/src/cobalt/black_box_tests/black_box_tests.py
index e15fce0..a5c9897 100644
--- a/src/cobalt/black_box_tests/black_box_tests.py
+++ b/src/cobalt/black_box_tests/black_box_tests.py
@@ -64,13 +64,13 @@
     return new_runner
 
 
-def LoadTests(platform, config):
+def LoadTests(platform, config, device_id):
 
   launcher = abstract_launcher.LauncherFactory(
       platform,
       'cobalt',
       config,
-      device_id=None,
+      device_id=device_id,
       target_params=None,
       output_file=None,
       out_directory=None)
@@ -101,7 +101,7 @@
       suite = unittest.TestLoader().loadTestsFromModule(
           importlib.import_module(_TEST_DIR_PATH + self.test_name))
     else:
-      suite = LoadTests(_device_params.platform, _device_params.config)
+      suite = LoadTests(_device_params.platform, _device_params.config, _device_params.device_id)
     return_code = not unittest.TextTestRunner(
         verbosity=0, stream=sys.stdout).run(suite).wasSuccessful()
     return return_code
@@ -123,4 +123,4 @@
   # make module-owned variables like device_param accessible to the tests.
   main_module = importlib.import_module(
       'cobalt.black_box_tests.black_box_tests')
-  main_module.main()
+  sys.exit(main_module.main())
diff --git a/src/cobalt/black_box_tests/threaded_web_server.py b/src/cobalt/black_box_tests/threaded_web_server.py
index b1cb297..8291375 100644
--- a/src/cobalt/black_box_tests/threaded_web_server.py
+++ b/src/cobalt/black_box_tests/threaded_web_server.py
@@ -62,27 +62,34 @@
   def __init__(self,
                handler=MakeRequestHandlerClass(os.path.dirname(__file__))):
     _ThreadedTCPServer.allow_reuse_address = True
-    # Get the socket address for the ANY interface.  Doing it this way
-    # has it so that it will work for IPv4, and IPv6 only networks.
-    # Note that putting '::' as the hostname does not work at this time
-    # (see https://bugs.python.org/issue20215).  Instead, the following code
-    # was inspired by https://docs.python.org/2/library/socket.html.
-    for result in socket.getaddrinfo(None, 0, socket.AF_UNSPEC,
-                                     socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
-      # This is (0.0.0.0, 0) or equivalent in IPv6 (could be more than 2
-      # elements).
-      socket_address = result[4]
-      break
 
-    self._server = _ThreadedTCPServer(socket_address, handler)
+    try:
+      self._server = _ThreadedTCPServer(('0.0.0.0', 8000), handler)
+    except socket.error:
+      # Get the socket address for the ANY interface.  Doing it this way
+      # has it so that it will work for IPv4. IPv6 is not supported yet because
+      # SocketServer.TCPServer can not take '::' as the hostname at this time.
+      # (see https://bugs.python.org/issue20215).  Instead, the following code
+      # was inspired by https://docs.python.org/2/library/socket.html.
+      for result in socket.getaddrinfo(None, 0, socket.AF_UNSPEC,
+                                       socket.SOCK_STREAM, 0, socket.AI_PASSIVE
+                                       ):
+        if len(result[4]) == 2:
+          # This is (0.0.0.0, 0).
+          socket_address = result[4]
+          break
+      self._server = _ThreadedTCPServer(socket_address, handler)
+
     self._server_thread = None
 
     self._bound_port = self._server.server_address[1]
     address_pack_list = socket.getaddrinfo(socket.gethostname(),
                                            self._bound_port)
-    first_address_pack = address_pack_list[0]
-    self._bound_ip, _ = first_address_pack[4]
-    self._bound_host, _ = first_address_pack[4]
+    for address_pack in address_pack_list:
+      if len(address_pack[4]) == 2:
+        self._bound_ip, _ = address_pack[4]
+        self._bound_host, _ = address_pack[4]
+        break
 
   def GetURL(self, file_name):
     """Given a |file_name|, return a HTTP URI that can be fetched.
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 741b776..ac2138c 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-186281
\ No newline at end of file
+188191
\ No newline at end of file
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 1ae118e..aef2a40 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -353,6 +353,9 @@
 std::string Window::Btoa(const std::string& string_to_encode,
                          script::ExceptionState* exception_state) {
   TRACE_EVENT0("cobalt::dom", "Window::Btoa()");
+  SB_NOTIMPLEMENTED();
+  LOG(WARNING) << "btoa() can not take a string containing NUL right now. "
+                  "Please avoid using it!";
   auto output = ForgivingBase64Encode(string_to_encode);
   if (!output) {
     DOMException::Raise(DOMException::kInvalidCharacterErr, exception_state);
diff --git a/src/cobalt/fetch/embedded_scripts/fetch.js b/src/cobalt/fetch/embedded_scripts/fetch.js
index eaaeb77..b63d1d8 100644
--- a/src/cobalt/fetch/embedded_scripts/fetch.js
+++ b/src/cobalt/fetch/embedded_scripts/fetch.js
@@ -1,20 +1,20 @@
 'use strict';(function(e){function B(a){"string"!==typeof a&&(a=String(a));if(/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(a))throw new d("Invalid character in header field name");return a.toLowerCase()}function O(a){"string"!==typeof a&&(a=String(a));var b;var c=0;for(b=a.length;c<b;c++){var f=a.charCodeAt(c);if(9!==f&&10!==f&&13!==f&&32!==f)break}for(b=a.length-1;b>c&&(f=a.charCodeAt(b),9===f||10===f||13===f||32===f);b--);a=a.substring(c,b+1);c=0;for(b=a.length;c<b;c++)if(f=a.charCodeAt(c),256<=f||0===f||
 10===f||13===f)throw new d("Invalid character in header field value");return a}function U(a,b){throw new d("Immutable header cannot be modified");}function V(a,b){return!1}function W(a,b){a=a.toLowerCase();return-1<X.indexOf(a)||a.startsWith("proxy-")||a.startsWith("sec-")?!0:!1}function Y(a,b){a=a.toLowerCase();return-1<Z.indexOf(a)||"content-type"===a&&(b=b.split(";")[0].toLowerCase(),-1<aa.indexOf(b))?!1:!0}function J(a,b){return-1<ba.indexOf(a.toLowerCase())?!0:!1}function h(a){this[l]=new G;
-void 0===this[t]&&(this[t]=V);if(void 0!==a){if(null===a||"object"!==typeof a)throw new d("Constructing Headers with invalid parameters");a instanceof h?a.forEach(function(a,c){this.append(c,a)},this):C.isArray(a)?a.forEach(function(a){if(2!==a.length)throw new d("Constructing Headers with invalid parameters");this.append(a[0],a[1])},this):Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b])},this)}}function D(a,b){var c=ca(h.prototype);c[t]=b;h.call(c,a);return c}function K(a){if(a.bodyUsed)return E.reject(new d("Body was already read"));
-if(null===a.body)return E.resolve(new u(0));if(da(a.body))return E.reject(new d("ReadableStream was already locked"));var b=a.body.getReader(),c=[],f=0;return b.read().then(function ea(a){if(a.done){if(0===c.length)a=new u(0);else if(1===c.length)a=new u(c[0]);else{a=new u(f);for(var k=0,e=c.length,g=0;k<e;k++)a.set(c[k],g),g+=c[k].length}return a}return a.value instanceof u?(f+=a.value.length,c.push(a.value),b.read().then(ea)):E.reject(new d("Invalid stream data type"))})}function P(){this._initBody=
-function(a){this[L]=!1;this[n]=null===a||void 0===a?null:a instanceof M?a:new M({start:function(b){if(a)if("string"===typeof a)b.enqueue(FetchInternal.encodeToUTF8(a));else if(Q.prototype.isPrototypeOf(a))b.enqueue(new u(a));else if(fa(a))b.enqueue(new u(a.buffer));else throw new d("Unsupported BodyInit type");b.close()}});this[r].get("content-type")||"string"===typeof a&&this[r].set("content-type","text/plain;charset=UTF-8")};N(this,{body:{get:function(){return this[n]}},bodyUsed:{get:function(){return this[L]?
-!0:this[n]?!!ha(this[n]):!1}}});this.arrayBuffer=function(){return K(this).then(function(a){return a.buffer})};this.text=function(){return K(this).then(function(a){return FetchInternal.decodeFromUTF8(a)})};this.json=function(){return this.text().then(JSON.parse)};return this}function v(a,b){var c=void 0!==b&&null!==b&&void 0===b.cloneBody;b=b||{};var f=b.body||b.cloneBody,e=b.headers;if(a instanceof v){if(a.bodyUsed)throw new d("Request body was already read");this[w]=a.url;this[y]=a.cache;this[z]=
-a.credentials;void 0===e&&(e=a.headers);this[A]=a.integrity;this[x]=a.method;this[m]=a.mode;c&&"navigate"===this[m]&&(this[m]="same-origin");this[F]=a.redirect;f||null===a.body||(f=a.body,a[L]=!0)}else{this[w]=String(a);if(!FetchInternal.isUrlValid(this[w],!1))throw new d("Invalid request URL");this[m]="cors";this[z]="omit"}if(void 0!==b.window&&null!==b.window)throw new d("Invalid request window");this[y]=b.cache||this[y]||"default";if(-1===ia.indexOf(this[y]))throw new d("Invalid request cache mode");
-this[z]=b.credentials||this[z]||"omit";if(-1===ja.indexOf(this[z]))throw new d("Invalid request credentials");void 0!==b.integrity?this[A]=b.integrity:void 0===this[A]&&(this[A]="");a=(b.method||this[x]||"GET").toUpperCase();if(-1===ka.indexOf(a))throw new d("Invalid request method");this[x]=a;if(b.mode&&-1===la.indexOf(b.mode))throw new d("Invalid request mode");this[m]=b.mode||this[m]||"no-cors";if("no-cors"===this[m]){if(-1===ma.indexOf(this[x]))throw new d("Invalid request method for no-cors");
-if(""!==this[A])throw new d("Request integrity data is not allowed with no-cors");}if("same-origin"!==this[m]&&"only-if-cached"===this[y])throw new d("Request mode must be same-origin for only-if-cached");this[F]=b.redirect||this[F]||"follow";if(-1===na.indexOf(this[F]))throw new d("Invalid request redirect mode");this[r]="no-cors"===this[m]?D(e,Y):D(e,W);if(("GET"===this[x]||"HEAD"===this[x])&&f)throw new d("Request body is not allowed for GET or HEAD");this._initBody(f)}function oa(a,b){var c=D(void 0,
-b);a.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(a){var b=a.split(":");if(a=b.shift().trim())b=b.join(":").trim(),c.append(a,b)});return c}function q(a,b){b||(b={});this[H]="default";this[p]="status"in b?b.status:200;if(200>this[p]||599<this[p])throw new R("Invalid response status");this[S]=200<=this[p]&&300>this[p];if("statusText"in b){var c=b.statusText;for(var f=0,e=c.length,g;f<e;f++)if(g=c.charCodeAt(f),9!==g&&(32>g||255<g||127===g))throw d("Invalid response status text");}else c=
-"OK";this[I]=c;this[r]=D(b.headers,J);this[w]=b.url||"";if(a&&-1<pa.indexOf(this[p]))throw new d("Response body is not allowed with a null body status");this._initBody(a)}if(!e.fetch){var C=e.Array,Q=e.ArrayBuffer,ca=e.Object.create,N=e.Object.defineProperties,g=e.Symbol,qa=g.iterator,G=e.Map,R=e.RangeError,d=e.TypeError,u=e.Uint8Array,E=e.Promise,M=e.ReadableStream,T=e.ReadableStreamTee,ha=e.IsReadableStreamDisturbed,da=e.IsReadableStreamLocked,n=g("body"),L=g("bodyUsed"),y=g("cache"),z=g("credentials"),
-t=g("guardCallback"),r=g("headers"),A=g("integrity"),l=g("map"),x=g("method"),m=g("mode"),S=g("ok"),F=g("redirect"),p=g("status"),I=g("statusText"),H=g("type"),w=g("url"),X="accept-charset accept-encoding access-control-request-headers access-control-request-method connection content-length cookie cookie2 date dnt expect host keep-alive origin referer te trailer transfer-encoding upgrade via".split(" "),ba=["set-cookie","set-cookie2"],Z=["accept","accept-language","content-language"],aa=["application/x-www-form-urlencoded",
-"multipart/form-data","text/plain"],ia="default no-store reload no-cache force-cache only-if-cached".split(" "),ja=["omit","same-origin","include"],ka="DELETE GET HEAD OPTIONS POST PUT".split(" "),ma=["GET","HEAD","POST"],la=["same-origin","no-cors","cors"],na=["follow","error","manual"],pa=[101,204,205,304],ra=[301,302,303,307,308],sa="[object Int8Array];[object Uint8Array];[object Uint8ClampedArray];[object Int16Array];[object Uint16Array];[object Int32Array];[object Uint32Array];[object Float32Array];[object Float64Array]".split(";"),
-fa=Q.isView||function(a){return a&&-1<sa.indexOf(Object.prototype.toString.call(a))};h.prototype.append=function(a,b){if(2!==arguments.length)throw d("Invalid parameters to append");a=B(a);b=O(b);this[t](a,b)||(this[l].has(a)?this[l].set(a,this[l].get(a)+", "+b):this[l].set(a,b))};h.prototype["delete"]=function(a){if(1!==arguments.length)throw d("Invalid parameters to delete");this[t](a,"invalid")||this[l].delete(B(a))};h.prototype.get=function(a){if(1!==arguments.length)throw d("Invalid parameters to get");
-a=B(a);var b=this[l].get(a);return void 0!==b?b:null};h.prototype.has=function(a){if(1!==arguments.length)throw d("Invalid parameters to has");return this[l].has(B(a))};h.prototype.set=function(a,b){if(2!==arguments.length)throw d("Invalid parameters to set");a=B(a);b=O(b);this[t](a,b)||this[l].set(a,b)};h.prototype.forEach=function(a,b){var c=this;C.from(this[l].entries()).sort().forEach(function(d){a.call(b,d[1],d[0],c)})};h.prototype.keys=function(){return(new G(C.from(this[l].entries()).sort())).keys()};
-h.prototype.values=function(){return(new G(C.from(this[l].entries()).sort())).values()};h.prototype.entries=function(){return(new G(C.from(this[l].entries()).sort())).entries()};h.prototype[qa]=h.prototype.entries;v.prototype.clone=function(){var a=null;null!==this[n]&&(a=T(this[n],!0),this[n]=a[0],a=a[1]);return new v(this,{cloneBody:a})};N(v.prototype,{cache:{get:function(){return this[y]}},credentials:{get:function(){return this[z]}},headers:{get:function(){return this[r]}},integrity:{get:function(){return this[A]}},
-method:{get:function(){return this[x]}},mode:{get:function(){return this[m]}},redirect:{get:function(){return this[F]}},url:{get:function(){return this[w]}}});P.call(v.prototype);P.call(q.prototype);q.prototype.clone=function(){var a=null;null!==this[n]&&(a=T(this[n],!0),this[n]=a[0],a=a[1]);return new q(a,{status:this[p],statusText:this[I],headers:D(this[r],J),url:this[w]})};N(q.prototype,{headers:{get:function(){return this[r]}},ok:{get:function(){return this[S]}},status:{get:function(){return this[p]}},
-statusText:{get:function(){return this[I]}},type:{get:function(){return this[H]}},url:{get:function(){return this[w]}}});q.error=function(){var a=new q(null);a[r][t]=U;a[H]="error";a[p]=0;a[I]="";return a};q.redirect=function(a,b){if(!FetchInternal.isUrlValid(a,!0))throw new d("Invalid URL for response redirect");void 0===b&&(b=302);if(-1===ra.indexOf(b))throw new R("Invalid status code for response redirect");return new q(null,{status:b,headers:{location:a}})};e.Headers=h;e.Request=v;e.Response=
+void 0===this[u]&&(this[u]=V);if(void 0!==a){if(null===a||"object"!==typeof a)throw new d("Constructing Headers with invalid parameters");a instanceof h?a.forEach(function(a,c){this.append(c,a)},this):C.isArray(a)?a.forEach(function(a){if(2!==a.length)throw new d("Constructing Headers with invalid parameters");this.append(a[0],a[1])},this):Object.getOwnPropertyNames(a).forEach(function(b){this.append(b,a[b])},this)}}function D(a,b){var c=ca(h.prototype);c[u]=b;h.call(c,a);return c}function K(a){if(a.bodyUsed)return E.reject(new d("Body was already read"));
+if(null===a.body)return E.resolve(new t(0));if(da(a.body))return E.reject(new d("ReadableStream was already locked"));var b=a.body.getReader(),c=[],f=0;return b.read().then(function ea(a){if(a.done){if(0===c.length)a=new t(0);else if(1===c.length)a=new t(c[0].buffer);else{a=new t(f);for(var k=0,e=c.length,g=0;k<e;k++)a.set(c[k],g),g+=c[k].length}return a}return a.value instanceof t?(f+=a.value.length,c.push(a.value),b.read().then(ea)):E.reject(new d("Invalid stream data type"))})}function P(){this._initBody=
+function(a){this[L]=!1;this[n]=null===a||void 0===a?null:a instanceof M?a:new M({start:function(b){if(a)if("string"===typeof a)b.enqueue(FetchInternal.encodeToUTF8(a));else if(Q.prototype.isPrototypeOf(a))b.enqueue(new t(a.slice(0)));else if(fa(a))b.enqueue(new t(a.buffer.slice(0)));else if(a instanceof Blob)b.enqueue(new t(FetchInternal.blobToArrayBuffer(a)));else throw new d("Unsupported BodyInit type");b.close()}});this[p].get("content-type")||("string"===typeof a?this[p].set("content-type","text/plain;charset=UTF-8"):
+a instanceof Blob&&""!==a.type&&this[p].set("content-type",a.type))};N(this,{body:{get:function(){return this[n]}},bodyUsed:{get:function(){return this[L]?!0:this[n]?!!ha(this[n]):!1}}});this.arrayBuffer=function(){return K(this).then(function(a){return a.buffer})};this.text=function(){return K(this).then(function(a){return FetchInternal.decodeFromUTF8(a)})};this.json=function(){return this.text().then(JSON.parse)};return this}function v(a,b){var c=void 0!==b&&null!==b&&void 0===b.cloneBody;b=b||
+{};var f=b.body||b.cloneBody,e=b.headers;if(a instanceof v){if(a.bodyUsed)throw new d("Request body was already read");this[w]=a.url;this[y]=a.cache;this[z]=a.credentials;void 0===e&&(e=a.headers);this[A]=a.integrity;this[x]=a.method;this[m]=a.mode;c&&"navigate"===this[m]&&(this[m]="same-origin");this[F]=a.redirect;f||null===a.body||(f=a.body,a[L]=!0)}else{this[w]=String(a);if(!FetchInternal.isUrlValid(this[w],!1))throw new d("Invalid request URL");this[m]="cors";this[z]="omit"}if(void 0!==b.window&&
+null!==b.window)throw new d("Invalid request window");this[y]=b.cache||this[y]||"default";if(-1===ia.indexOf(this[y]))throw new d("Invalid request cache mode");this[z]=b.credentials||this[z]||"omit";if(-1===ja.indexOf(this[z]))throw new d("Invalid request credentials");void 0!==b.integrity?this[A]=b.integrity:void 0===this[A]&&(this[A]="");a=(b.method||this[x]||"GET").toUpperCase();if(-1===ka.indexOf(a))throw new d("Invalid request method");this[x]=a;if(b.mode&&-1===la.indexOf(b.mode))throw new d("Invalid request mode");
+this[m]=b.mode||this[m]||"no-cors";if("no-cors"===this[m]){if(-1===ma.indexOf(this[x]))throw new d("Invalid request method for no-cors");if(""!==this[A])throw new d("Request integrity data is not allowed with no-cors");}if("same-origin"!==this[m]&&"only-if-cached"===this[y])throw new d("Request mode must be same-origin for only-if-cached");this[F]=b.redirect||this[F]||"follow";if(-1===na.indexOf(this[F]))throw new d("Invalid request redirect mode");this[p]="no-cors"===this[m]?D(e,Y):D(e,W);if(("GET"===
+this[x]||"HEAD"===this[x])&&f)throw new d("Request body is not allowed for GET or HEAD");this._initBody(f)}function oa(a,b){var c=D(void 0,b);a.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(a){var b=a.split(":");if(a=b.shift().trim())b=b.join(":").trim(),c.append(a,b)});return c}function q(a,b){b||(b={});this[H]="default";this[r]="status"in b?b.status:200;if(200>this[r]||599<this[r])throw new R("Invalid response status");this[S]=200<=this[r]&&300>this[r];if("statusText"in b){var c=b.statusText;
+for(var f=0,e=c.length,g;f<e;f++)if(g=c.charCodeAt(f),9!==g&&(32>g||255<g||127===g))throw d("Invalid response status text");}else c="OK";this[I]=c;this[p]=D(b.headers,J);this[w]=b.url||"";if(a&&-1<pa.indexOf(this[r]))throw new d("Response body is not allowed with a null body status");this._initBody(a)}if(!e.fetch){var C=e.Array,Q=e.ArrayBuffer,ca=e.Object.create,N=e.Object.defineProperties,g=e.Symbol,qa=g.iterator,G=e.Map,R=e.RangeError,d=e.TypeError,t=e.Uint8Array,E=e.Promise,M=e.ReadableStream,
+T=e.ReadableStreamTee,ha=e.IsReadableStreamDisturbed,da=e.IsReadableStreamLocked,n=g("body"),L=g("bodyUsed"),y=g("cache"),z=g("credentials"),u=g("guardCallback"),p=g("headers"),A=g("integrity"),l=g("map"),x=g("method"),m=g("mode"),S=g("ok"),F=g("redirect"),r=g("status"),I=g("statusText"),H=g("type"),w=g("url"),X="accept-charset accept-encoding access-control-request-headers access-control-request-method connection content-length cookie cookie2 date dnt expect host keep-alive origin referer te trailer transfer-encoding upgrade via".split(" "),
+ba=["set-cookie","set-cookie2"],Z=["accept","accept-language","content-language"],aa=["application/x-www-form-urlencoded","multipart/form-data","text/plain"],ia="default no-store reload no-cache force-cache only-if-cached".split(" "),ja=["omit","same-origin","include"],ka="DELETE GET HEAD OPTIONS POST PUT".split(" "),ma=["GET","HEAD","POST"],la=["same-origin","no-cors","cors"],na=["follow","error","manual"],pa=[101,204,205,304],ra=[301,302,303,307,308],sa="[object Int8Array];[object Uint8Array];[object Uint8ClampedArray];[object Int16Array];[object Uint16Array];[object Int32Array];[object Uint32Array];[object Float32Array];[object Float64Array]".split(";"),
+fa=Q.isView||function(a){return a&&-1<sa.indexOf(Object.prototype.toString.call(a))};h.prototype.append=function(a,b){if(2!==arguments.length)throw d("Invalid parameters to append");a=B(a);b=O(b);this[u](a,b)||(this[l].has(a)?this[l].set(a,this[l].get(a)+", "+b):this[l].set(a,b))};h.prototype["delete"]=function(a){if(1!==arguments.length)throw d("Invalid parameters to delete");this[u](a,"invalid")||this[l].delete(B(a))};h.prototype.get=function(a){if(1!==arguments.length)throw d("Invalid parameters to get");
+a=B(a);var b=this[l].get(a);return void 0!==b?b:null};h.prototype.has=function(a){if(1!==arguments.length)throw d("Invalid parameters to has");return this[l].has(B(a))};h.prototype.set=function(a,b){if(2!==arguments.length)throw d("Invalid parameters to set");a=B(a);b=O(b);this[u](a,b)||this[l].set(a,b)};h.prototype.forEach=function(a,b){var c=this;C.from(this[l].entries()).sort().forEach(function(d){a.call(b,d[1],d[0],c)})};h.prototype.keys=function(){return(new G(C.from(this[l].entries()).sort())).keys()};
+h.prototype.values=function(){return(new G(C.from(this[l].entries()).sort())).values()};h.prototype.entries=function(){return(new G(C.from(this[l].entries()).sort())).entries()};h.prototype[qa]=h.prototype.entries;v.prototype.clone=function(){var a=null;null!==this[n]&&(a=T(this[n],!0),this[n]=a[0],a=a[1]);return new v(this,{cloneBody:a})};N(v.prototype,{cache:{get:function(){return this[y]}},credentials:{get:function(){return this[z]}},headers:{get:function(){return this[p]}},integrity:{get:function(){return this[A]}},
+method:{get:function(){return this[x]}},mode:{get:function(){return this[m]}},redirect:{get:function(){return this[F]}},url:{get:function(){return this[w]}}});P.call(v.prototype);P.call(q.prototype);q.prototype.clone=function(){var a=null;null!==this[n]&&(a=T(this[n],!0),this[n]=a[0],a=a[1]);return new q(a,{status:this[r],statusText:this[I],headers:D(this[p],J),url:this[w]})};N(q.prototype,{headers:{get:function(){return this[p]}},ok:{get:function(){return this[S]}},status:{get:function(){return this[r]}},
+statusText:{get:function(){return this[I]}},type:{get:function(){return this[H]}},url:{get:function(){return this[w]}}});q.error=function(){var a=new q(null);a[p][u]=U;a[H]="error";a[r]=0;a[I]="";return a};q.redirect=function(a,b){if(!FetchInternal.isUrlValid(a,!0))throw new d("Invalid URL for response redirect");void 0===b&&(b=302);if(-1===ra.indexOf(b))throw new R("Invalid status code for response redirect");return new q(null,{status:b,headers:{location:a}})};e.Headers=h;e.Request=v;e.Response=
 q;e.fetch=function(a,b){return new E(function(c,f){var e=!1,g=!1,h=new v(a,b),k=new XMLHttpRequest,l=null,n=new M({start:function(a){l=a},cancel:function(a){e=!0;k.abort()}});k.onload=function(){l.close()};k.onreadystatechange=function(){if(k.readyState===k.HEADERS_RECEIVED){var a={status:k.status,statusText:k.statusText,headers:oa(k.getAllResponseHeaders()||"",J)};a.url="responseURL"in k?k.responseURL:a.headers.get("X-Request-URL");try{var b=new q(n,a);b[H]=g?"cors":"basic";c(b)}catch(ta){f(ta)}}};
 k.onerror=function(){l.error(new d("Network request failed"));f(new d("Network request failed"))};k.ontimeout=function(){l.error(new d("Network request failed"));f(new d("Network request failed"))};k.open(h.method,h.url,!0);"include"===h.credentials&&(k.withCredentials=!0);h.headers.forEach(function(a,b){k.setRequestHeader(b,a)});var m=function(a){e||l.enqueue(a)},p=function(a){g=a};null===h.body?k.fetch(m,p,null):K(h).then(function(a){k.fetch(m,p,a)})})};e.fetch.polyfill=!0}})(this);
\ No newline at end of file
diff --git a/src/cobalt/fetch/fetch.js b/src/cobalt/fetch/fetch.js
index 8073db1..543786f 100644
--- a/src/cobalt/fetch/fetch.js
+++ b/src/cobalt/fetch/fetch.js
@@ -397,7 +397,8 @@
         if (results.length === 0) {
           data = new Uint8Array(0)
         } else if (results.length === 1) {
-          data = new Uint8Array(results[0])
+          // Create a view of the ArrayBuffer. No copy is made.
+          data = new Uint8Array(results[0].buffer)
         } else {
           data = new Uint8Array(resultsLength)
           for (var i = 0, len = results.length, offset = 0; i < len; i++) {
@@ -418,13 +419,18 @@
 
   // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
   function extractBody(controller, data, errorString) {
+    // Copy the incoming data. This is to prevent subsequent changes to |data|
+    // from impacting the Body's contents, and also to prevent changes to the
+    // Body's contents from impacting the original data.
     if (!data) {
     } else if (typeof data === 'string') {
       controller.enqueue(FetchInternal.encodeToUTF8(data))
     } else if (ArrayBuffer.prototype.isPrototypeOf(data)) {
-      controller.enqueue(new Uint8Array(data))
+      controller.enqueue(new Uint8Array(data.slice(0)))
     } else if (isArrayBufferView(data)) {
-      controller.enqueue(new Uint8Array(data.buffer))
+      controller.enqueue(new Uint8Array(data.buffer.slice(0)))
+    } else if (data instanceof Blob) {
+      controller.enqueue(new Uint8Array(FetchInternal.blobToArrayBuffer(data)))
     } else {
       throw new TypeError(errorString)
     }
@@ -452,6 +458,8 @@
       if (!this[HEADERS_SLOT].get('content-type')) {
         if (typeof body === 'string') {
           this[HEADERS_SLOT].set('content-type', 'text/plain;charset=UTF-8')
+        } else if (body instanceof Blob && body.type !== "") {
+          this[HEADERS_SLOT].set('content-type', body.type)
         }
       }
     }
@@ -799,7 +807,8 @@
 
       var fetchUpdate = function(data) {
         if (!cancelled) {
-          // Data is already an Uint8Array.
+          // Data is already a Uint8Array. Enqueue a reference to this, rather
+          // than make a copy of it, since caller no longer references it.
           responseStreamController.enqueue(data)
         }
       }
diff --git a/src/cobalt/fetch/fetch_internal.cc b/src/cobalt/fetch/fetch_internal.cc
index c6fe72b..2be861f 100644
--- a/src/cobalt/fetch/fetch_internal.cc
+++ b/src/cobalt/fetch/fetch_internal.cc
@@ -68,5 +68,16 @@
   return std::string();
 }
 
+// static
+script::Handle<script::ArrayBuffer> FetchInternal::BlobToArrayBuffer(
+    script::EnvironmentSettings* settings,
+    const scoped_refptr<dom::Blob>& blob) {
+  dom::DOMSettings* dom_settings =
+      base::polymorphic_downcast<dom::DOMSettings*>(settings);
+  // Create a copy of the data so that the caller cannot modify the Blob.
+  return script::ArrayBuffer::New(dom_settings->global_environment(),
+                                  blob->data(), blob->size());
+}
+
 }  // namespace fetch
 }  // namespace cobalt
diff --git a/src/cobalt/fetch/fetch_internal.h b/src/cobalt/fetch/fetch_internal.h
index 9ecd7f3..16a5ee1 100644
--- a/src/cobalt/fetch/fetch_internal.h
+++ b/src/cobalt/fetch/fetch_internal.h
@@ -18,6 +18,7 @@
 #include <string>
 
 #include "base/memory/ref_counted.h"
+#include "cobalt/dom/blob.h"
 #include "cobalt/script/environment_settings.h"
 #include "cobalt/script/exception_state.h"
 #include "cobalt/script/typed_arrays.h"
@@ -46,6 +47,11 @@
       const script::Handle<script::Uint8Array>& data,
       script::ExceptionState* exception_state);
 
+  // Translate a dom Blob to ArrayBuffer.
+  static script::Handle<script::ArrayBuffer> BlobToArrayBuffer(
+      script::EnvironmentSettings* settings,
+      const scoped_refptr<dom::Blob>& blob);
+
   DEFINE_WRAPPABLE_TYPE(FetchInternal);
 };
 
diff --git a/src/cobalt/fetch/fetch_internal.idl b/src/cobalt/fetch/fetch_internal.idl
index ecdc920..d665bf2 100644
--- a/src/cobalt/fetch/fetch_internal.idl
+++ b/src/cobalt/fetch/fetch_internal.idl
@@ -22,4 +22,6 @@
   [CallWith=EnvironmentSettings,RaisesException] static Uint8Array encodeToUTF8(
       DOMString text);
   [RaisesException] static DOMString decodeFromUTF8(Uint8Array data);
+  [CallWith=EnvironmentSettings] static ArrayBuffer blobToArrayBuffer(
+      Blob blob);
 };
diff --git a/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt b/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
index 3fd8ec9..b0a5089 100644
--- a/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
+++ b/src/cobalt/layout_tests/testdata/web-platform-tests/fetch/web_platform_tests.txt
@@ -120,11 +120,11 @@
 # Fails because Blob is not fully supported.
 api/response/response-cancel-stream.html,DISABLE
 api/response/response-clone.html,PASS
-api/response/response-consume.cobalt.html,PASS
+api/response/response-consume.cobalt.blob.html,PASS
 api/response/response-consume.html,DISABLE
 api/response/response-consume-empty.cobalt.html,PASS
 api/response/response-consume-empty.html,DISABLE
-api/response/response-consume-stream.cobalt.html,PASS
+api/response/response-consume-stream.cobalt.blob.html,PASS
 api/response/response-consume-stream.html,DISABLE
 api/response/response-error.html,PASS
 # Fails because implementation is a polyfill.
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc b/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc
index e7d52fc..d081290 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc
+++ b/src/cobalt/renderer/rasterizer/egl/draw_object_manager.cc
@@ -162,6 +162,7 @@
       flush_external_offscreen_draws_.Run();
     }
   }
+  graphics_state->SetDirty();
 
   SortOffscreenDraws(&offscreen_draws_, &sorted_offscreen_draws_);
   SortOnscreenDraws(&onscreen_draws_, &sorted_onscreen_draws_);
diff --git a/src/cobalt/renderer/rasterizer/egl/graphics_state.cc b/src/cobalt/renderer/rasterizer/egl/graphics_state.cc
index 21d5d26..52ab82c 100644
--- a/src/cobalt/renderer/rasterizer/egl/graphics_state.cc
+++ b/src/cobalt/renderer/rasterizer/egl/graphics_state.cc
@@ -17,6 +17,7 @@
 #include <algorithm>
 
 #include "cobalt/renderer/backend/egl/utils.h"
+#include "starboard/memory.h"
 
 namespace cobalt {
 namespace renderer {
@@ -60,7 +61,11 @@
 
   GL_CALL(glGenBuffers(kNumFramesBuffered, vertex_data_buffer_handle_));
   GL_CALL(glGenBuffers(kNumFramesBuffered, vertex_index_buffer_handle_));
-  memset(clip_adjustment_, 0, sizeof(clip_adjustment_));
+  for (int frame = 0; frame < kNumFramesBuffered; ++frame) {
+    DCHECK_NE(vertex_data_buffer_handle_[frame], 0);
+    DCHECK_NE(vertex_index_buffer_handle_[frame], 0);
+  }
+  SbMemorySet(clip_adjustment_, 0, sizeof(clip_adjustment_));
   SetDirty();
   blend_enabled_ = false;
   Reset();
@@ -351,6 +356,10 @@
   DCHECK(!vertex_buffers_updated_);
   vertex_buffers_updated_ = true;
 
+  if (state_dirty_) {
+    Reset();
+  }
+
   if (vertex_data_allocated_ > 0) {
     if (array_buffer_handle_ != vertex_data_buffer_handle_[frame_index_]) {
       array_buffer_handle_ = vertex_data_buffer_handle_[frame_index_];
@@ -413,8 +422,8 @@
   array_buffer_handle_ = 0;
   index_buffer_handle_ = 0;
   texture_unit_ = 0;
-  memset(&texunit_target_, 0, sizeof(texunit_target_));
-  memset(&texunit_texture_, 0, sizeof(texunit_texture_));
+  SbMemorySet(&texunit_target_, 0, sizeof(texunit_target_));
+  SbMemorySet(&texunit_texture_, 0, sizeof(texunit_texture_));
   clip_adjustment_dirty_ = true;
 
   enabled_vertex_attrib_array_mask_ = 0;
diff --git a/src/cobalt/script/v8c/isolate_fellowship.cc b/src/cobalt/script/v8c/isolate_fellowship.cc
index f3981ff..78a99e4 100644
--- a/src/cobalt/script/v8c/isolate_fellowship.cc
+++ b/src/cobalt/script/v8c/isolate_fellowship.cc
@@ -26,10 +26,35 @@
 namespace script {
 namespace v8c {
 
+namespace {
 // This file will also be touched and rebuilt every time V8 is re-built
 // according to the update_snapshot_time gyp target.
 const char kIsolateFellowshipBuildTime[] = __DATE__ " " __TIME__;
 
+const char* kV8CommandLineFlags[] = {"--optimize_for_size",
+                                     // Starboard disallow rwx memory access.
+                                     "--write_protect_code_memory",
+                                     // Cobalt's TraceMembers and
+                                     // ScriptValue::*Reference do not currently
+                                     // support incremental tracing.
+                                     "--noincremental_marking_wrappers",
+#if defined(COBALT_GC_ZEAL)
+                                     "--gc_interval=1200"
+#endif
+};
+
+
+// Configure v8's global command line flag options for Cobalt.
+// It can be called more than once, but make sure it is called before any
+// v8 instance is created.
+void V8FlagsInit() {
+  for (auto flag_str : kV8CommandLineFlags) {
+    v8::V8::SetFlagsFromString(flag_str, SbStringGetLength(flag_str));
+  }
+}
+
+} // namespace
+
 IsolateFellowship::IsolateFellowship() {
   TRACE_EVENT0("cobalt::script", "IsolateFellowship::IsolateFellowship");
   // TODO: Initialize V8 ICU stuff here as well.
@@ -39,6 +64,10 @@
   v8::V8::Initialize();
   array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
 
+  // If a new snapshot data is needed, a temporary v8 isoalte will be created
+  // to write the snapshot data. We need to make sure all global command line
+  // flags are set before that.
+  V8FlagsInit();
   InitializeStartupData();
 }
 
diff --git a/src/cobalt/script/v8c/v8c_engine.cc b/src/cobalt/script/v8c/v8c_engine.cc
index 5885c69..25daf87 100644
--- a/src/cobalt/script/v8c/v8c_engine.cc
+++ b/src/cobalt/script/v8c/v8c_engine.cc
@@ -98,15 +98,6 @@
   }
 }
 
-SbOnceControl v8_flag_init_once_control = SB_ONCE_INITIALIZER;
-
-// Configure v8's global command line flag options for Cobalt.
-void V8FlagInitOnce() {
-  char optimize_for_size_flag_str[] = "--optimize_for_size=true";
-  v8::V8::SetFlagsFromString(optimize_for_size_flag_str,
-                             sizeof(optimize_for_size_flag_str));
-}
-
 }  // namespace
 
 V8cEngine::V8cEngine(const Options& options) : options_(options) {
@@ -127,7 +118,6 @@
                     "significantly slow down startup time.";
   }
 
-  SbOnce(&v8_flag_init_once_control, V8FlagInitOnce);
   isolate_ = v8::Isolate::New(create_params);
   CHECK(isolate_);
   isolate_fellowship->platform->RegisterIsolateOnThread(isolate_,
diff --git a/src/cobalt/version.h b/src/cobalt/version.h
index b4c38c7..e6a94f6 100644
--- a/src/cobalt/version.h
+++ b/src/cobalt/version.h
@@ -35,6 +35,6 @@
 //                  release is cut.
 //.
 
-#define COBALT_VERSION "19.lts.1"
+#define COBALT_VERSION "19.lts.2"
 
 #endif  // COBALT_VERSION_H_
diff --git a/src/net/socket/tcp_client_socket_starboard.cc b/src/net/socket/tcp_client_socket_starboard.cc
index e1a2c6e..0ea6c4d 100644
--- a/src/net/socket/tcp_client_socket_starboard.cc
+++ b/src/net/socket/tcp_client_socket_starboard.cc
@@ -243,8 +243,10 @@
     return ERR_INVALID_ARGUMENT;
   }
 
-  bool success = SbSocketConnect(socket_, &address);
-  DCHECK_EQ(true, success);
+  SbSocketError error = SbSocketConnect(socket_, &address);
+  if (error != kSbSocketOk) {
+    DCHECK_EQ(kSbSocketPending, error);
+  }
 
   int rv = MapLastSocketError(socket_);
   if (rv != ERR_IO_PENDING) {
diff --git a/src/starboard/contrib/creator/README.md b/src/starboard/contrib/creator/README.md
index 6e66ee0..3554cfd 100644
--- a/src/starboard/contrib/creator/README.md
+++ b/src/starboard/contrib/creator/README.md
@@ -26,6 +26,12 @@
 
     export CI20_HOME=<PATH_TO_DIRECTORY_WHERE_PACKAGE_IS_EXTRACTED>
 
+## JavaScript engine
+
+Default configuration for JavaScript engine is V8 with JIT enabled.
+Alternative configuration is to use mozjs-45, which has JIT disabled by defualt.
+Configuration with mozjs-45 is only available when building Cobalt with Clang.
+
 ## Building
 
 Follow all generic instructions from:
@@ -51,6 +57,20 @@
     cobalt/build/gyp_cobalt -C gold creator-ci20x11
     ninja -j4 -C out/creator-ci20x11_gold cobalt
 
+Using mozjs-45 JavaScript engine:
+
+    cobalt/build/gyp_cobalt -C debug creator-ci20x11-mozjs
+    ninja -j4 -C out/creator-ci20x11-mozjs_debug all
+
+    cobalt/build/gyp_cobalt -C devel creator-ci20x11-mozjs
+    ninja -j4 -C out/creator-ci20x11-mozjs_devel all
+
+    cobalt/build/gyp_cobalt -C qa creator-ci20x11-mozjs
+    ninja -j4 -C out/creator-ci20x11-mozjs_qa cobalt
+
+    cobalt/build/gyp_cobalt -C gold creator-ci20x11-mozjs
+    ninja -j4 -C out/creator-ci20x11-mozjs_gold cobalt
+
 ### Building with GCC 4.9
 
 Configuration files for GCC build are located in creator/ci20x11/gcc/4.9
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/atomic_public.h b/src/starboard/contrib/creator/ci20x11/mozjs/atomic_public.h
new file mode 100644
index 0000000..534eeae
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/atomic_public.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_ATOMIC_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_ATOMIC_PUBLIC_H_
+
+#include "starboard/linux/shared/atomic_public.h"
+
+#endif  // STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/configuration_public.h b/src/starboard/contrib/creator/ci20x11/mozjs/configuration_public.h
new file mode 100644
index 0000000..2dcdb7b
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/configuration_public.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_CONFIGURATION_PUBLIC_H_
+
+#include "starboard/contrib/creator/shared/configuration_public.h"
+
+#endif  // STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.gypi b/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.gypi
new file mode 100644
index 0000000..54be982
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.gypi
@@ -0,0 +1,42 @@
+# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+{
+  'variables': {
+    'gl_type': 'system_gles2',
+  },
+  'target_defaults': {
+    'default_configuration': 'creator-ci20x11-mozjs_debug',
+    'configurations': {
+      'creator-ci20x11-mozjs_debug': {
+        'inherit_from': ['debug_base'],
+      },
+      'creator-ci20x11-mozjs_devel': {
+        'inherit_from': ['devel_base'],
+      },
+      'creator-ci20x11-mozjs_qa': {
+        'inherit_from': ['qa_base'],
+      },
+      'creator-ci20x11-mozjs_gold': {
+        'inherit_from': ['gold_base'],
+      },
+    }, # end of configurations
+  },
+
+  'includes': [
+    '../libraries.gypi',
+    '../../shared/compiler_flags.gypi',
+    '../../shared/gyp_configuration.gypi',
+  ],
+}
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.py b/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.py
new file mode 100644
index 0000000..a7c0f12
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/gyp_configuration.py
@@ -0,0 +1,42 @@
+# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+"""Starboard Creator Ci20 X11 mozjs platform configuration."""
+
+from starboard.contrib.creator.shared import gyp_configuration as shared_configuration
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import touch
+
+
+class CreatorCI20X11MozjsConfiguration(shared_configuration.CreatorConfiguration):
+  """Starboard Creator X11 mozjs platform configuration."""
+
+  def __init__(self, platform_name='creator-ci20x11-mozjs'):
+    super(CreatorCI20X11MozjsConfiguration, self).__init__(platform_name)
+
+  def GetVariables(self, config_name):
+    variables = super(CreatorCI20X11MozjsConfiguration, self).GetVariables(
+        config_name)
+    variables.update({
+        'javascript_engine': 'mozjs-45',
+        'cobalt_enable_jit': 0,
+    })
+
+    return variables
+
+def CreatePlatformConfig():
+  return CreatorCI20X11MozjsConfiguration()
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/starboard_platform.gyp b/src/starboard/contrib/creator/ci20x11/mozjs/starboard_platform.gyp
new file mode 100644
index 0000000..bc313df
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/starboard_platform.gyp
@@ -0,0 +1,40 @@
+# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+{
+  'includes': [
+    '../starboard_platform.gypi'
+  ],
+  'targets': [
+    {
+      'target_name': 'starboard_platform',
+      'type': 'static_library',
+      'sources': [
+        '<@(starboard_platform_sources)',
+        '<(DEPTH)/starboard/shared/starboard/player/video_dmp_common.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/video_dmp_common.h',
+        '<(DEPTH)/starboard/shared/starboard/player/video_dmp_writer.cc',
+        '<(DEPTH)/starboard/shared/starboard/player/video_dmp_writer.h',
+      ],
+      'defines': [
+        'SB_PLAYER_ENABLE_VIDEO_DUMPER',
+        # This must be defined when building Starboard, and must not when
+        # building Starboard client code.
+        'STARBOARD_IMPLEMENTATION',
+      ],
+      'dependencies': [
+        '<@(starboard_platform_dependencies)',
+      ],
+    },
+  ],
+}
diff --git a/src/starboard/contrib/creator/ci20x11/mozjs/thread_types_public.h b/src/starboard/contrib/creator/ci20x11/mozjs/thread_types_public.h
new file mode 100644
index 0000000..5038e89
--- /dev/null
+++ b/src/starboard/contrib/creator/ci20x11/mozjs/thread_types_public.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+#ifndef STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+
+#include "starboard/linux/shared/thread_types_public.h"
+
+#endif  // STARBOARD_CONTRIB_CREATOR_CI20X11_MOZJS_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/contrib/creator/shared/gyp_configuration.py b/src/starboard/contrib/creator/shared/gyp_configuration.py
index 244d13d..6b94934 100644
--- a/src/starboard/contrib/creator/shared/gyp_configuration.py
+++ b/src/starboard/contrib/creator/shared/gyp_configuration.py
@@ -52,6 +52,12 @@
         config_name, use_clang=1)
     variables.update({
         'sysroot': sysroot,
+        'javascript_engine': 'v8',
+        'cobalt_enable_jit': 1,
+        'v8_target_arch': 'mipsel',
+        'mips_arch_variant': 'r2',
+        'mips_fpu_mode': 'fp32',
+        'mips_float_abi': 'hard',
     })
 
     return variables
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index 2ad6091..fe261b5 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -395,6 +395,7 @@
     "//starboard/shared/posix/socket_set_tcp_keep_alive.cc",
     "//starboard/shared/posix/socket_set_tcp_no_delay.cc",
     "//starboard/shared/posix/socket_set_tcp_window_scaling.cc",
+    "//starboard/shared/posix/storage_write_record.cc",
     "//starboard/shared/posix/string_compare_no_case.cc",
     "//starboard/shared/posix/string_compare_no_case_n.cc",
     "//starboard/shared/posix/string_compare_wide.cc",
@@ -459,7 +460,6 @@
     "//starboard/shared/starboard/file_storage/storage_get_record_size.cc",
     "//starboard/shared/starboard/file_storage/storage_open_record.cc",
     "//starboard/shared/starboard/file_storage/storage_read_record.cc",
-    "//starboard/shared/starboard/file_storage/storage_write_record.cc",
     "//starboard/shared/starboard/log_message.cc",
     "//starboard/shared/starboard/log_raw_dump_stack.cc",
     "//starboard/shared/starboard/log_raw_format.cc",
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
index c7588ca..a3e3f74 100644
--- a/src/starboard/linux/shared/starboard_platform.gypi
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -154,6 +154,7 @@
       '<(DEPTH)/starboard/shared/posix/socket_set_tcp_keep_alive.cc',
       '<(DEPTH)/starboard/shared/posix/socket_set_tcp_no_delay.cc',
       '<(DEPTH)/starboard/shared/posix/socket_set_tcp_window_scaling.cc',
+      '<(DEPTH)/starboard/shared/posix/storage_write_record.cc',
       '<(DEPTH)/starboard/shared/posix/string_compare_no_case.cc',
       '<(DEPTH)/starboard/shared/posix/string_compare_no_case_n.cc',
       '<(DEPTH)/starboard/shared/posix/string_compare_wide.cc',
@@ -218,7 +219,6 @@
       '<(DEPTH)/starboard/shared/starboard/file_storage/storage_get_record_size.cc',
       '<(DEPTH)/starboard/shared/starboard/file_storage/storage_open_record.cc',
       '<(DEPTH)/starboard/shared/starboard/file_storage/storage_read_record.cc',
-      '<(DEPTH)/starboard/shared/starboard/file_storage/storage_write_record.cc',
       '<(DEPTH)/starboard/shared/starboard/log_message.cc',
       '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
       '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
diff --git a/src/starboard/nplb/memory_map_test.cc b/src/starboard/nplb/memory_map_test.cc
index 7404403..36808db 100644
--- a/src/starboard/nplb/memory_map_test.cc
+++ b/src/starboard/nplb/memory_map_test.cc
@@ -206,11 +206,11 @@
 // to executable.
 TEST(SbMemoryMapTest, CanNotDirectlyMapMemoryWithExecFlag) {
   SbMemoryMapFlags exec_flags[] = {
-    SbMemoryMapFlags(kSbMemoryMapProtectExec),
-    SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectExec),
-    SbMemoryMapFlags(kSbMemoryMapProtectWrite | kSbMemoryMapProtectExec),
-    SbMemoryMapFlags(kSbMemoryMapProtectWrite | kSbMemoryMapProtectWrite |
-                     kSbMemoryMapProtectExec),
+      SbMemoryMapFlags(kSbMemoryMapProtectExec),
+      SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectExec),
+      SbMemoryMapFlags(kSbMemoryMapProtectWrite | kSbMemoryMapProtectExec),
+      SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectWrite |
+                       kSbMemoryMapProtectExec),
   };
   for (auto exec_flag : exec_flags) {
     void* memory = SbMemoryMap(kSize, exec_flag, "test");
diff --git a/src/starboard/nplb/system_get_path_test.cc b/src/starboard/nplb/system_get_path_test.cc
index 5a3babc..2e89803 100644
--- a/src/starboard/nplb/system_get_path_test.cc
+++ b/src/starboard/nplb/system_get_path_test.cc
@@ -14,6 +14,8 @@
 
 #include <string.h>
 
+#include <algorithm>
+
 #include "starboard/file.h"
 #include "starboard/memory.h"
 #include "starboard/nplb/file_helpers.h"
@@ -50,6 +52,19 @@
 #undef LOCAL_CONTEXT
 }
 
+void UnmodifiedOnFailureTest(SbSystemPathId id, int line) {
+  char path[kPathSize];
+  SbMemorySet(path, 0xCD, kPathSize);
+  for (size_t i = 0; i <= kPathSize; ++i) {
+    if (SbSystemGetPath(id, path, i)) {
+      return;
+    }
+    for (auto ch : path) {
+      ASSERT_EQ('\xCD', ch) << "Context : id=" << id << ", line=" << line;
+    }
+  }
+}
+
 TEST(SbSystemGetPathTest, ReturnsRequiredPaths) {
   BasicTest(kSbSystemPathContentDirectory, true, true, __LINE__);
   BasicTest(kSbSystemPathCacheDirectory, true, true, __LINE__);
@@ -85,6 +100,15 @@
   BasicTest(kSbSystemPathFontConfigurationDirectory, false, false, __LINE__);
 }
 
+TEST(SbSystemGetPathTest, DoesNotTouchOutputBufferOnFailureForDefinedIds) {
+  UnmodifiedOnFailureTest(kSbSystemPathDebugOutputDirectory, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPathTempDirectory, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPathTestOutputDirectory, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPathCacheDirectory, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPathFontDirectory, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPathFontConfigurationDirectory, __LINE__);
+}
+
 TEST(SbSystemGetPathTest, CanCreateAndRemoveDirectoryInCache) {
   char path[kPathSize];
   SbMemorySet(path, 0xCD, kPathSize);
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index 5df797a..bb4379b 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -62,6 +62,19 @@
 #undef LOCAL_CONTEXT
 }
 
+void UnmodifiedOnFailureTest(SbSystemPropertyId id, int line) {
+  char value[kValueSize] = {0};
+  SbMemorySet(value, 0xCD, kValueSize);
+  for (size_t i = 0; i <= kValueSize; ++i) {
+    if (SbSystemGetProperty(id, value, i)) {
+      return;
+    }
+    for (auto ch : value) {
+      ASSERT_EQ('\xCD', ch) << "Context : id=" << id << ", line=" << line;
+    }
+  }
+}
+
 TEST(SbSystemGetPropertyTest, ReturnsRequired) {
   BasicTest(kSbSystemPropertyFriendlyName, true, true, __LINE__);
   BasicTest(kSbSystemPropertyPlatformName, true, true, __LINE__);
@@ -100,6 +113,25 @@
   BasicTest(static_cast<SbSystemPropertyId>(99999), true, false, __LINE__);
 }
 
+TEST(SbSystemGetPathTest, DoesNotTouchOutputBufferOnFailureForDefinedIds) {
+  UnmodifiedOnFailureTest(kSbSystemPropertyChipsetModelNumber, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyFirmwareVersion, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyFriendlyName, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyManufacturerName, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyBrandName, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyModelName, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyModelYear, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyNetworkOperatorName, __LINE__);
+  UnmodifiedOnFailureTest(kSbSystemPropertyPlatformName, __LINE__);
+#if SB_API_VERSION < 10
+  UnmodifiedOnFailureTest(kSbSystemPropertyPlatformUuid, __LINE__);
+#endif  // SB_API_VERSION < 10
+  UnmodifiedOnFailureTest(kSbSystemPropertySpeechApiKey, __LINE__);
+#if SB_API_VERSION >= 5
+  UnmodifiedOnFailureTest(kSbSystemPropertyUserAgentAuxField, __LINE__);
+#endif  // SB_API_VERSION >= 5
+}
+
 TEST(SbSystemGetPropertyTest, SpeechApiKeyNotLeaked) {
   static const size_t kSize = 512;
   char speech_api_key[kSize] = {0};
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h
index 4816c62..09cc42c 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.h
+++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -49,6 +49,7 @@
                   const ErrorCB& error_cb) override;
   size_t GetPrerollFrameCount() const override { return 1; }
   SbTime GetPrerollTimeout() const override { return kSbTimeMax; }
+  size_t GetMaxNumberOfCachedFrames() const override { return 12; }
   void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
       override;
   void WriteEndOfStream() override;
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi
index be746db..8520f7a 100644
--- a/src/starboard/raspi/shared/starboard_platform.gypi
+++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -203,6 +203,7 @@
         '<(DEPTH)/starboard/shared/posix/socket_set_tcp_keep_alive.cc',
         '<(DEPTH)/starboard/shared/posix/socket_set_tcp_no_delay.cc',
         '<(DEPTH)/starboard/shared/posix/socket_set_tcp_window_scaling.cc',
+        '<(DEPTH)/starboard/shared/posix/storage_write_record.cc',
         '<(DEPTH)/starboard/shared/posix/string_compare_no_case.cc',
         '<(DEPTH)/starboard/shared/posix/string_compare_no_case_n.cc',
         '<(DEPTH)/starboard/shared/posix/string_compare_wide.cc',
@@ -267,7 +268,6 @@
         '<(DEPTH)/starboard/shared/starboard/file_storage/storage_get_record_size.cc',
         '<(DEPTH)/starboard/shared/starboard/file_storage/storage_open_record.cc',
         '<(DEPTH)/starboard/shared/starboard/file_storage/storage_read_record.cc',
-        '<(DEPTH)/starboard/shared/starboard/file_storage/storage_write_record.cc',
         '<(DEPTH)/starboard/shared/starboard/log_message.cc',
         '<(DEPTH)/starboard/shared/starboard/log_raw_dump_stack.cc',
         '<(DEPTH)/starboard/shared/starboard/log_raw_format.cc',
diff --git a/src/starboard/raspi/shared/system_get_property.cc b/src/starboard/raspi/shared/system_get_property.cc
index 3930087..a04ae5e 100644
--- a/src/starboard/raspi/shared/system_get_property.cc
+++ b/src/starboard/raspi/shared/system_get_property.cc
@@ -15,6 +15,9 @@
 #include "starboard/system.h"
 
 #include <sys/utsname.h>
+
+#include <string>
+
 #include "starboard/log.h"
 #include "starboard/string.h"
 
@@ -60,19 +63,10 @@
       if (uname(&name) == -1)
         return false;
 
-      if (SbStringCopy(out_value, "Raspian ", value_length) >= value_length)
-        return false;
+      std::string temp =
+          starboard::FormatString("Raspian %s %s", name.sysname, name.machine);
 
-      if (SbStringConcat(out_value, name.sysname, value_length) >= value_length)
-        return false;
-
-      if (SbStringConcat(out_value, " ", value_length) >= value_length)
-        return false;
-
-      if (SbStringConcat(out_value, name.machine, value_length) >= value_length)
-        return false;
-
-      return true;
+      return CopyStringAndTestIfSuccess(out_value, value_length, temp.c_str());
     }
 
     default:
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_dispatch.h b/src/starboard/shared/ffmpeg/ffmpeg_dispatch.h
index c83f9f7..4050cab 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_dispatch.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_dispatch.h
@@ -92,6 +92,9 @@
   void (*avcodec_flush_buffers)(AVCodecContext* avctx);
   AVFrame* (*avcodec_alloc_frame)(void);
   void (*avcodec_get_frame_defaults)(AVFrame* frame);
+  void (*avcodec_align_dimensions2)(AVCodecContext* avctx,
+                                    int* width, int* height,
+                                    int linesize_align[]);
 
   unsigned (*avformat_version)(void);
   void (*av_register_all)(void);
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_dynamic_load_dispatch_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_dynamic_load_dispatch_impl.cc
index 31f3905..44f669e 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_dynamic_load_dispatch_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_dynamic_load_dispatch_impl.cc
@@ -235,6 +235,7 @@
   INITSYMBOL(avcodec_, avcodec_flush_buffers);
   INITSYMBOL(avcodec_, avcodec_alloc_frame);
   INITSYMBOL(avcodec_, avcodec_get_frame_defaults);
+  INITSYMBOL(avcodec_, avcodec_align_dimensions2);
 
   // Load symbols from the avformat shared library.
   INITSYMBOL(avformat_, avformat_version);
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_linked_dispatch_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_linked_dispatch_impl.cc
index 4472e06..e515791 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_linked_dispatch_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_linked_dispatch_impl.cc
@@ -77,6 +77,7 @@
   INITSYMBOL(avcodec_alloc_frame);
   INITSYMBOL(avcodec_get_frame_defaults);
 #endif
+  INITSYMBOL(avcodec_align_dimensions2);
 
   // Load symbols from the avformat shared library.
   INITSYMBOL(avformat_version);
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
index b5795b5..37170aa 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
@@ -279,7 +279,13 @@
     return false;
   }
 
-  int pitch = AlignUp(av_frame_->width, kAlignment * 2);
+  int codec_aligned_width = av_frame_->width;
+  int codec_aligned_height = av_frame_->height;
+  int codec_linesize_align[AV_NUM_DATA_POINTERS];
+  ffmpeg_->avcodec_align_dimensions2(codec_context_,
+      &codec_aligned_width, &codec_aligned_height, codec_linesize_align);
+
+  int pitch = AlignUp(av_frame_->width, codec_linesize_align[0] * 2);
 
   scoped_refptr<CpuVideoFrame> frame = CpuVideoFrame::CreateYV12Frame(
       av_frame_->width, av_frame_->height, pitch, av_frame_->reordered_opaque,
@@ -417,10 +423,17 @@
     return ret;
   }
 
-  // Align to kAlignment * 2 as we will divide y_stride by 2 for u and v planes
-  size_t y_stride = AlignUp(codec_context->width, kAlignment * 2);
+  int codec_aligned_width = codec_context->width;
+  int codec_aligned_height = codec_context->height;
+  int codec_linesize_align[AV_NUM_DATA_POINTERS];
+  ffmpeg_->avcodec_align_dimensions2(codec_context,
+      &codec_aligned_width, &codec_aligned_height, codec_linesize_align);
+
+  // Align to linesize alignment * 2 as we will divide y_stride by 2 for
+  // u and v planes.
+  size_t y_stride = AlignUp(codec_context->width, codec_linesize_align[0] * 2);
   size_t uv_stride = y_stride / 2;
-  size_t aligned_height = AlignUp(codec_context->height, kAlignment * 2);
+  size_t aligned_height = codec_aligned_height;
 
   uint8_t* frame_buffer = reinterpret_cast<uint8_t*>(SbMemoryAllocateAligned(
       kAlignment, GetYV12SizeInBytes(y_stride, aligned_height)));
@@ -463,10 +476,17 @@
     return ret;
   }
 
-  // Align to kAlignment * 2 as we will divide y_stride by 2 for u and v planes
-  size_t y_stride = AlignUp(codec_context->width, kAlignment * 2);
+  int codec_aligned_width = codec_context->width;
+  int codec_aligned_height = codec_context->height;
+  int codec_linesize_align[AV_NUM_DATA_POINTERS];
+  ffmpeg_->avcodec_align_dimensions2(codec_context,
+      &codec_aligned_width, &codec_aligned_height, codec_linesize_align);
+
+  // Align to linesize alignment * 2 as we will divide y_stride by 2 for
+  // u and v planes.
+  size_t y_stride = AlignUp(codec_context->width, codec_linesize_align[0] * 2);
   size_t uv_stride = y_stride / 2;
-  size_t aligned_height = AlignUp(codec_context->height, kAlignment * 2);
+  size_t aligned_height = codec_aligned_height;
   uint8_t* frame_buffer = reinterpret_cast<uint8_t*>(SbMemoryAllocateAligned(
       kAlignment, GetYV12SizeInBytes(y_stride, aligned_height)));
 
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.h b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.h
index 29e4ea5..b1b05b3 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.h
@@ -69,6 +69,7 @@
                   const ErrorCB& error_cb) override;
   size_t GetPrerollFrameCount() const override { return 8; }
   SbTime GetPrerollTimeout() const override { return kSbTimeMax; }
+  size_t GetMaxNumberOfCachedFrames() const override { return 12; }
 
   void WriteInputBuffer(
       const scoped_refptr<InputBuffer>& input_buffer) override;
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.h b/src/starboard/shared/libvpx/vpx_video_decoder.h
index 7bea0c5..12eb6f3 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.h
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.h
@@ -47,6 +47,7 @@
                   const ErrorCB& error_cb) override;
   size_t GetPrerollFrameCount() const override { return 8; }
   SbTime GetPrerollTimeout() const override { return kSbTimeMax; }
+  size_t GetMaxNumberOfCachedFrames() const override { return 12; }
 
   void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
       override;
diff --git a/src/starboard/shared/posix/storage_write_record.cc b/src/starboard/shared/posix/storage_write_record.cc
new file mode 100644
index 0000000..f47fd0c
--- /dev/null
+++ b/src/starboard/shared/posix/storage_write_record.cc
@@ -0,0 +1,86 @@
+// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+#include "starboard/storage.h"
+
+#include <algorithm>
+
+#include "starboard/file.h"
+#include "starboard/log.h"
+#include "starboard/shared/starboard/file_storage/storage_internal.h"
+#include "starboard/string.h"
+
+const char kTempFileSuffix[] = ".temp";
+
+bool SbStorageWriteRecord(SbStorageRecord record,
+                          const char* data,
+                          int64_t data_size) {
+  if (!SbStorageIsValidRecord(record) || !data || data_size < 0) {
+    return false;
+  }
+
+#if SB_API_VERSION >= 6
+  const char* name = record->name.c_str();
+#else
+  const char* name = NULL;
+#endif
+  char original_file_path[SB_FILE_MAX_PATH];
+  if (!starboard::shared::starboard::GetUserStorageFilePath(
+          record->user, name, original_file_path, SB_FILE_MAX_PATH)) {
+    return false;
+  }
+  char temp_file_path[SB_FILE_MAX_PATH];
+  SbStringCopy(temp_file_path, original_file_path, SB_FILE_MAX_PATH);
+  SbStringConcat(temp_file_path, kTempFileSuffix, SB_FILE_MAX_PATH);
+
+  SbFileError error;
+  SbFile temp_file = SbFileOpen(
+      temp_file_path, kSbFileCreateAlways | kSbFileWrite | kSbFileRead, NULL,
+      &error);
+  if (error != kSbFileOk) {
+    return false;
+  }
+
+  SbFileTruncate(temp_file, 0);
+
+  const char* source = data;
+  int64_t to_write = data_size;
+  while (to_write > 0) {
+    int to_write_max =
+        static_cast<int>(std::min(to_write, static_cast<int64_t>(kSbInt32Max)));
+    int bytes_written = SbFileWrite(temp_file, source, to_write_max);
+    if (bytes_written < 0) {
+      SbFileClose(temp_file);
+      SbFileDelete(temp_file_path);
+      return false;
+    }
+
+    source += bytes_written;
+    to_write -= bytes_written;
+  }
+
+  SbFileFlush(temp_file);
+
+  if (!SbFileClose(record->file) || !SbFileDelete(original_file_path)) {
+    return false;
+  }
+
+  if (rename(temp_file_path, original_file_path) != 0) {
+    return false;
+  }
+
+  record->file = temp_file;
+
+  return true;
+}
diff --git a/src/starboard/shared/starboard/file_storage/storage_write_record.cc b/src/starboard/shared/starboard/file_storage/storage_write_record.cc
index 125f228..1e58819 100644
--- a/src/starboard/shared/starboard/file_storage/storage_write_record.cc
+++ b/src/starboard/shared/starboard/file_storage/storage_write_record.cc
@@ -19,6 +19,11 @@
 #include "starboard/file.h"
 #include "starboard/shared/starboard/file_storage/storage_internal.h"
 
+#pragma message( \
+    "You are using the old SbStorageWriteRecord implementation, it does not"\
+    " guarantee automic storage record writing, please consider switching to"\
+    " the new posix/win32 implementation.")
+
 bool SbStorageWriteRecord(SbStorageRecord record,
                           const char* data,
                           int64_t data_size) {
diff --git a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
index a20ec3e..e6dbcfa 100644
--- a/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
+++ b/src/starboard/shared/starboard/media/media_can_play_mime_and_key_system.cc
@@ -84,6 +84,10 @@
                                  ,
                                  decode_to_texture_required
 #endif  // SB_API_VERSION >= 10
+#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+                                 ,
+                                 kSbMediaTransferIdUnspecified
+#endif  // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
                                  )) {
       return kSbMediaSupportTypeNotSupported;
     }
@@ -203,9 +207,12 @@
     }
 
     std::string eotf = mime_type.GetParamStringValue("eotf", "");
+    SbMediaTransferId transfer_id = kSbMediaTransferIdUnspecified;
     if (!eotf.empty()) {
-      SbMediaTransferId transfer_id = GetTransferIdFromString(eotf);
-      if (!SbMediaIsTransferCharacteristicsSupported(transfer_id)) {
+      transfer_id = GetTransferIdFromString(eotf);
+      // If the eotf is not known, reject immediately - without checking with
+      // the platform.
+      if (transfer_id == kSbMediaTransferIdUnknown) {
         return kSbMediaSupportTypeNotSupported;
       }
     }
@@ -239,6 +246,10 @@
                                 ,
                                 decode_to_texture_required
 #endif  // SB_API_VERSION >= 10
+#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+                                ,
+                                transfer_id
+#endif  // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
                                 )) {
       return kSbMediaSupportTypeProbably;
     }
diff --git a/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc b/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc
new file mode 100644
index 0000000..e3bbe03
--- /dev/null
+++ b/src/starboard/shared/starboard/media/media_is_transfer_characteristics_supported.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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.
+
+#include "starboard/shared/starboard/media/media_support_internal.h"
+
+#include "starboard/media.h"
+
+#if !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported(
+    SbMediaTransferId transfer_id) {
+  return transfer_id == kSbMediaTransferIdBt709 ||
+         transfer_id == kSbMediaTransferIdUnspecified;
+}
+#endif  // !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
diff --git a/src/starboard/shared/starboard/media/media_support_internal.h b/src/starboard/shared/starboard/media/media_support_internal.h
index 0ecefdf..f7e7dd4 100644
--- a/src/starboard/shared/starboard/media/media_support_internal.h
+++ b/src/starboard/shared/starboard/media/media_support_internal.h
@@ -46,6 +46,10 @@
                                        ,
                                        bool decode_to_texture_required
 #endif  // SB_API_VERSION >= 10
+#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+                                       ,
+                                       SbMediaTransferId eotf
+#endif  // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
                                        );
 
 // Indicates whether this platform supports |audio_codec| at |bitrate|.
@@ -57,6 +61,7 @@
 SB_EXPORT bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
                                        int64_t bitrate);
 
+#if !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
 // Indicates whether this platform supports |transfer_id| as a transfer
 // characteristics.  If |transfer_id| is not supported under any condition, this
 // function returns |false|.
@@ -64,6 +69,7 @@
 // |transfer_id|: The id of transfer charateristics listed in SbMediaTransferId.
 SB_EXPORT bool SbMediaIsTransferCharacteristicsSupported(
     SbMediaTransferId transfer_id);
+#endif  // !SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/src/starboard/shared/starboard/microphone/microphone_get_available.cc b/src/starboard/shared/starboard/microphone/microphone_get_available.cc
index 007ec06..07b36a8 100644
--- a/src/starboard/shared/starboard/microphone/microphone_get_available.cc
+++ b/src/starboard/shared/starboard/microphone/microphone_get_available.cc
@@ -24,7 +24,7 @@
 int SbMicrophoneGetAvailable(SbMicrophoneInfo* out_info_array,
                              int info_array_size) {
   if (out_info_array && info_array_size > 0) {
-    SbMemorySet(out_info_array, 0, info_array_size);
+    SbMemorySet(out_info_array, 0, sizeof(SbMicrophoneInfo) * info_array_size);
   }
   return SbMicrophonePrivate::GetAvailableMicrophones(out_info_array,
                                                       info_array_size);
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
index 51976ea..1f899c7 100644
--- a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
@@ -170,6 +170,7 @@
   }
   size_t GetPrerollFrameCount() const override { return 1; }
   SbTime GetPrerollTimeout() const override { return kSbTimeMax; }
+  size_t GetMaxNumberOfCachedFrames() const override { return 12; }
   void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
       override {
     SB_DCHECK(input_buffer);
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
index 12622c5..3f678f0 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -368,6 +368,10 @@
   EXPECT_GT(video_decoder_->GetPrerollFrameCount(), 0);
 }
 
+TEST_P(VideoDecoderTest, MaxNumberOfCachedFrames) {
+  EXPECT_GT(video_decoder_->GetMaxNumberOfCachedFrames(), 1);
+}
+
 TEST_P(VideoDecoderTest, PrerollTimeout) {
   EXPECT_GE(video_decoder_->GetPrerollTimeout(), 0);
 }
@@ -651,6 +655,10 @@
                   ,
               false
 #endif  // SB_API_VERSION >= 10
+#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+              ,
+              kSbMediaTransferIdUnspecified
+#endif  // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
               )) {
         test_params.push_back({output_mode, filename});
       }
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
index c4f400f..9f06901 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -81,8 +81,10 @@
   // of the video pipeline like the VideoRendererSink may also cache frames.  It
   // is the responsibility of the decoder to ensure that this wouldn't result in
   // anything catastrophic.
-  // TODO:  Turn this into pure virtual.
-  virtual size_t GetMaxNumberOfCachedFrames() const { return 12; }
+  // Also it is worth noting that the return value should always greater than 1
+  // for the video renderer to work properly.  It should be at least 4 for
+  // acceptable playback performance.  A number greater than 6 is recommended.
+  virtual size_t GetMaxNumberOfCachedFrames() const = 0;
 
   // Send encoded video frame stored in |input_buffer| to decode.
   virtual void WriteInputBuffer(
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
index 6f76e3a..48ab311 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -48,6 +48,11 @@
   SB_DCHECK(decoder_ != NULL);
   SB_DCHECK(algorithm_ != NULL);
   SB_DCHECK(sink_ != NULL);
+  SB_DCHECK(decoder_->GetMaxNumberOfCachedFrames() > 1);
+  SB_DLOG_IF(WARNING, decoder_->GetMaxNumberOfCachedFrames() < 4)
+      << "VideoDecoder::GetMaxNumberOfCachedFrames() returns "
+      << decoder_->GetMaxNumberOfCachedFrames() << ", which is less than 4."
+      << " Playback performance may not be ideal.";
 }
 
 VideoRenderer::~VideoRenderer() {
@@ -107,6 +112,37 @@
   SB_DCHECK(need_more_input_.load());
   need_more_input_.store(false);
 
+#if ENABLE_VIDEO_FRAME_LAG_LOG
+  {
+    ScopedLock scoped_lock_decoder_frames(decoder_frames_mutex_);
+    if (!decoder_frames_.empty()) {
+      auto frame = decoder_frames_.back();
+      bool is_playing;
+      bool is_eos_played;
+      bool is_underflow;
+      SbTime media_time = media_time_provider_->GetCurrentMediaTime(
+          &is_playing, &is_eos_played, &is_underflow);
+      if (!is_eos_played) {
+        const int kMaxDiffFrameMediaTime = 2 * kSbTimeSecond;
+        const int kMinLagWarningPeriod = 10 * kSbTimeSecond;
+        SbTime frame_time = frame->timestamp();
+        SbTime diff_media_frame_time = media_time - frame_time;
+        SbTimeMonotonic monotonic_now = SbTimeGetMonotonicNow();
+        if (diff_media_frame_time > kMaxDiffFrameMediaTime &&
+            (!time_of_last_lag_warning_ ||
+             monotonic_now - time_of_last_lag_warning_.value() >=
+                 kMinLagWarningPeriod)) {
+          SB_LOG(WARNING) << "Video renderer wrote sample with frame time"
+                          << " lagging "
+                          << diff_media_frame_time * 1.0f / kSbTimeSecond
+                          << " s behind media time";
+          time_of_last_lag_warning_ = monotonic_now;
+        }
+      }
+    }
+  }
+#endif  // ENABLE_VIDEO_FRAME_LAG_LOG
+
   decoder_->WriteInputBuffer(input_buffer);
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index 7049d37..d141cea 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -18,6 +18,7 @@
 #include <list>
 
 #include "starboard/atomic.h"
+#include "starboard/common/optional.h"
 #include "starboard/common/ref_counted.h"
 #include "starboard/common/scoped_ptr.h"
 #include "starboard/log.h"
@@ -114,6 +115,14 @@
   Frames decoder_frames_;
   Mutex sink_frames_mutex_;
   Frames sink_frames_;
+
+#if !defined(STARBOARD_BUILD_TYPE_GOLD)
+#define ENABLE_VIDEO_FRAME_LAG_LOG 1
+#endif  // !defined(STARBOARD_BUILD_TYPE_GOLD)
+
+#if ENABLE_VIDEO_FRAME_LAG_LOG
+  optional<SbTimeMonotonic> time_of_last_lag_warning_;
+#endif  // ENABLE_VIDEO_FRAME_LAG_LOG
 };
 
 }  // namespace filter
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index 725a021..1f9c81b 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -85,6 +85,10 @@
                                ,
                                output_mode == kSbPlayerOutputModeDecodeToTexture
 #endif
+#if SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
+                               ,
+                               kSbMediaTransferIdUnspecified
+#endif  // SB_HAS(MEDIA_EOTF_CHECK_SUPPORT)
                                )) {
     SB_LOG(ERROR) << "Unsupported video codec " << video_codec;
     return kSbPlayerInvalid;
diff --git a/src/v8/src/base/cpu.cc b/src/v8/src/base/cpu.cc
index 22e0511..32b1c33 100644
--- a/src/v8/src/base/cpu.cc
+++ b/src/v8/src/base/cpu.cc
@@ -4,6 +4,11 @@
 
 #include "src/base/cpu.h"
 
+#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
+// Assume that if we're on a MIPS platform, we're on Linux.
+#define V8_OS_LINUX 1
+#endif
+
 #if V8_LIBC_MSVCRT
 #include <intrin.h>  // __cpuid()
 #endif
diff --git a/src/v8/src/flag-definitions.h b/src/v8/src/flag-definitions.h
index 71e33ac..e40e182 100644
--- a/src/v8/src/flag-definitions.h
+++ b/src/v8/src/flag-definitions.h
@@ -612,11 +612,7 @@
 DEFINE_INT(random_gc_interval, 0,
            "Collect garbage after random(0, X) allocations. It overrides "
            "gc_interval.")
-#if defined(COBALT_GC_ZEAL)
-DEFINE_INT(gc_interval, 1200, "garbage collect after <n> allocations")
-#else
 DEFINE_INT(gc_interval, -1, "garbage collect after <n> allocations")
-#endif
 DEFINE_INT(retain_maps_for_n_gc, 2,
            "keeps maps alive for <n> old space garbage collections")
 DEFINE_BOOL(trace_gc, false,
@@ -641,21 +637,11 @@
 DEFINE_BOOL(trace_mutator_utilization, false,
             "print mutator utilization, allocation speed, gc speed")
 DEFINE_BOOL(incremental_marking, true, "use incremental marking")
-#if defined(COBALT)
-// Cobalt's TraceMembers and ScriptValue::*Reference do not currently support
-// incremental tracing.
-DEFINE_BOOL(incremental_marking_wrappers, false,
-            "use incremental marking for marking wrappers")
-#else  // defined(COBALT)
 DEFINE_BOOL(incremental_marking_wrappers, true,
             "use incremental marking for marking wrappers")
-#endif  // defined(COBALT)
 DEFINE_BOOL(parallel_scavenge, true, "parallel scavenge")
 DEFINE_BOOL(trace_parallel_scavenge, false, "trace parallel scavenge")
-#if defined(COBALT)
-// Starboard disallow rwx memory access.
-DEFINE_BOOL(write_protect_code_memory, true, "write protect code memory")
-#endif
+DEFINE_BOOL(write_protect_code_memory, false, "write protect code memory")
 #ifdef V8_CONCURRENT_MARKING
 #define V8_CONCURRENT_MARKING_BOOL true
 #else
diff --git a/src/v8/src/mips/cpu-mips.cc b/src/v8/src/mips/cpu-mips.cc
index 1199365..7662a1d 100644
--- a/src/v8/src/mips/cpu-mips.cc
+++ b/src/v8/src/mips/cpu-mips.cc
@@ -4,12 +4,15 @@
 
 // CPU specific code for arm independent of OS goes here.
 
+// Starboard implementation will use SbMemoryFlush().
+#if !defined(V8_OS_STARBOARD)
 #include <sys/syscall.h>
 #include <unistd.h>
 
 #ifdef __mips
 #include <asm/cachectl.h>
 #endif  // #ifdef __mips
+#endif  // !defined(V8_OS_STARBOARD)
 
 #if V8_TARGET_ARCH_MIPS
 
@@ -34,6 +37,12 @@
   char *end = reinterpret_cast<char *>(start) + size;
   cacheflush(
     reinterpret_cast<intptr_t>(start), reinterpret_cast<intptr_t>(end), 0);
+#elif defined(V8_OS_STARBOARD)
+  // SbMemoryFlush uses BCACHE as argument for _flush_cache() call.
+  // This should not affect performance, since MIPS kernel only uses BCACHE,
+  // according to:
+  // https://elixir.bootlin.com/linux/latest/source/arch/mips/mm/cache.c#L74
+  SbMemoryFlush(start, size);
 #else  // ANDROID
   int res;
   // See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
diff --git a/src/v8/src/utils.cc b/src/v8/src/utils.cc
index a669c9f..cd0e3d5 100644
--- a/src/v8/src/utils.cc
+++ b/src/v8/src/utils.cc
@@ -394,7 +394,7 @@
 MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
     Isolate* isolate, MemCopyUint16Uint8Function stub);
 
-#elif (V8_OS_POSIX && V8_OS_STARBOARD) && V8_HOST_ARCH_MIPS
+#elif (V8_OS_POSIX || V8_OS_STARBOARD) && V8_HOST_ARCH_MIPS
 V8_EXPORT_PRIVATE MemCopyUint8Function memcopy_uint8_function =
     &MemCopyUint8Wrapper;
 // Defined in codegen-mips.cc.