Added new class TrustedScript to TrustedTypes

New class TrustedScript added as a C++ implementation of JS
TrustedScript.

Bug: 739170
Change-Id: Ife70f8838aefa6bb4aac45f09639464c19de6e1b
Reviewed-on: https://chromium-review.googlesource.com/1168494
Commit-Queue: Maja Kabus <kabusm@google.com>
Reviewed-by: Mike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584197}
diff --git a/trusted-types/TrustedTypePolicyFactory-createPolicy.tentative.html b/trusted-types/TrustedTypePolicyFactory-createPolicy.tentative.html
index d6f6b35..76e6d13 100644
--- a/trusted-types/TrustedTypePolicyFactory-createPolicy.tentative.html
+++ b/trusted-types/TrustedTypePolicyFactory-createPolicy.tentative.html
@@ -84,6 +84,77 @@
     }));
   }, "html - calling undefined callback");
 
+  //Script tests
+  function createScriptTest(policy, expectedScript, t) {
+    let p = window.trustedTypes.createPolicy('SomeName', policy)
+        .then(t.step_func_done(p => {
+            assert_true(p.createScript('whatever') instanceof TrustedScript);
+            assert_equals(p.createScript('whatever') + "", expectedScript);
+    }));
+  }
+
+  async_test(t => {
+    createScriptTest( { createScript: s => s }, 'whatever', t);
+  }, "script = identity function");
+
+  async_test(t => {
+    createScriptTest( { createScript: s => null }, "null", t);
+  }, "script = null");
+
+  var Scriptstr = 'well, ';
+  async_test(t => {
+    createScriptTest( { createScript: s => Scriptstr + s }, Scriptstr + 'whatever', t);
+  }, "script = string + global string");
+
+  var Scriptx = 'global';
+  async_test(t => {
+    let p = window.trustedTypes.createPolicy('SomeName', {
+        createScript: s => { Scriptx = s; return s; }
+      })
+      .then(t.step_func_done(p => {
+        assert_true(p.createScript('whatever') instanceof TrustedScript);
+        assert_equals(p.createScript('whatever') + "", 'whatever');
+        assert_equals(Scriptx, 'whatever');
+    }));
+  }, "script = identity function, global string changed");
+
+  async_test(t => {
+    let p = window.trustedTypes.createPolicy('SomeName', {
+        createScript: s => { throw new Error(); }
+      })
+      .then(t.step_func_done(p => {
+        assert_throws(new Error(), _ => {
+          p.createScript('whatever');
+        });
+    }));
+  }, "script = callback that throws");
+
+  var obj = {
+    "foo": "well,"
+  }
+
+  function getScript(s) {
+    return this.foo + " " + s;
+  }
+
+  async_test(t => {
+    createScriptTest( {
+      createScript: getScript.bind(obj)},
+      'well, whatever', t);
+  }, "script = this bound to an object");
+
+  var foo = "well,";
+  async_test(t => {
+    createScriptTest( { createScript: s => getScript(s) }, 'well, whatever', t);
+  }, "script = this without bind");
+
+  async_test(t => {
+    let p = window.trustedTypes.createPolicy('SomeName', null)
+        .then(t.step_func_done(p => {
+            assert_equals(p.createScript('whatever'), null);
+    }));
+  }, "script - calling undefined callback");
+
   //ScriptURL tests
   function createScriptURLTest(policy, expectedScriptURL, t) {
     window.trustedTypes.createPolicy('SomeName', policy)
diff --git a/trusted-types/support/helper.sub.js b/trusted-types/support/helper.sub.js
index 07e8902..b543591 100644
--- a/trusted-types/support/helper.sub.js
+++ b/trusted-types/support/helper.sub.js
@@ -1,11 +1,13 @@
 var INPUTS = {
   HTML: "Hi, I want to be transformed!",
+  SCRIPT: "Hi, I want to be transformed!",
   SCRIPTURL: "http://this.is.a.scripturl.test/",
   URL: "http://hello.i.am.an.url/"
 };
 
 var RESULTS = {
   HTML: "Quack, I want to be a duck!",
+  SCRIPT: "Meow, I want to be a cat!",
   SCRIPTURL: "http://this.is.a.successful.test/",
   URL: "http://hooray.i.am.successfully.transformed/"
 };
@@ -15,6 +17,11 @@
       .replace("transformed", "a duck");
 }
 
+function createScriptJS(script) {
+  return script.replace("Hi", "Meow")
+      .replace("transformed", "a cat");
+}
+
 function createScriptURLJS(scripturl) {
   return scripturl.replace("scripturl", "successful");
 }
@@ -28,6 +35,10 @@
   return win.trustedTypes.createPolicy('SomeName', { createHTML: createHTMLJS });
 }
 
+function createScript_policy(win) {
+  return win.trustedTypes.createPolicy('SomeName', { createScript: createScriptJS });
+}
+
 function createScriptURL_policy(win) {
   return win.trustedTypes.createPolicy('SomeName', { createScriptURL: createScriptURLJS });
 }
@@ -44,6 +55,14 @@
       }));
 }
 
+function assert_element_accepts_trusted_script(win, t, tag, attribute, expected) {
+  createScript_policy(win)
+      .then(t.step_func_done(p => {
+          let script = p.createScript(INPUTS.SCRIPT);
+          assert_element_accepts_trusted_type(tag, attribute, script, expected);
+      }));
+}
+
 function assert_element_accepts_trusted_script_url(win, t, tag, attribute, expected) {
   createScriptURL_policy(win)
       .then(t.step_func_done(p => {