Revision: 5570
Author:   [email protected]
Date:     Wed Aug 21 21:36:49 2013 UTC
Log: a.href now returns a virtualized URL and fragment for the current page.
https://codereview.appspot.com/12834046

* jQuery UI tabs expects that <a href="#foo">.href ===
  window.location + '#foo', so implement that.
* Fix toString overrides in Domado not working in ES5/3 mode with the +
  operator.

Fixes <http://code.google.com/p/google-caja/issues/detail?id=1835>.

[email protected]

http://code.google.com/p/google-caja/source/detail?r=5570

Modified:
 /trunk/src/com/google/caja/plugin/domado.js
 /trunk/tests/com/google/caja/plugin/test-domado-dom-guest.html
 /trunk/tests/com/google/caja/plugin/test-domado-global-location.js
 /trunk/tests/com/google/caja/plugin/third-party-tests.json

=======================================
--- /trunk/src/com/google/caja/plugin/domado.js Wed Aug 21 20:22:22 2013 UTC
+++ /trunk/src/com/google/caja/plugin/domado.js Wed Aug 21 21:36:49 2013 UTC
@@ -323,8 +323,15 @@
    * Alias for a common pattern: non-enumerable toString method.
    */
   function setToString(obj, fn) {
-    Object.defineProperty(obj, 'toString',
-        allowNonWritableOverride(obj, 'toString', {value: fn}));
+    // ES5/3's virtualization of toString does not work properly w/
+    // defineProperty
+ if ('USELESS' in cajaVM) { // TODO(kpreid): Better condition/kill this code + // Under ES5/3, this will have the overridable semantics we wanted anyway
+      obj.toString = fn;
+    } else {
+      Object.defineProperty(obj, 'toString',
+          allowNonWritableOverride(obj, 'toString', {value: fn}));
+    }
   }

   /**
@@ -1827,6 +1834,8 @@
var window = bridalMaker.getWindow(outerContainerNode, makeDOMAccessible);
       window = makeDOMAccessible(window);

+      makeDOMAccessible(document.location);
+
// Note that feralPseudoWindow may be an Element or a Window depending.
       var feralPseudoDocument, feralPseudoWindow;
       if (outerContainerNode.nodeType === 9) { // Document node
@@ -2178,6 +2187,14 @@
           return fail;
         }
       }
+
+      /** Split a URI reference into URI and fragment (still escaped). */
+      function splitURIFragment(uriString) {
+        var parsed = URI.parse(uriString);
+        var frag = parsed.getRawFragment();
+        parsed.setRawFragment('');
+        return {frag: frag, uri: parsed.toString()};
+      }

       var ID_LIST_PARTS_PATTERN = new RegExp(
         '([^' + XML_SPACE + ']+)([' + XML_SPACE + ']+|$)', 'g');
@@ -2199,7 +2216,19 @@
             if (realValue && '#' === realValue.charAt(0)) {
               return unsuffix(realValue, idSuffix, realValue);
             } else {
-              return realValue;
+              // convert "http://hostpage#fragment-suffix___"; into
+              // "http://guestpage#fragment";
+              var valueSplit = splitURIFragment(realValue);
+              var baseSplit = splitURIFragment(
+                    // .baseURI not available on IE
+                    document.baseURI || document.location.href);
+              // compare against document's base URL
+              if (valueSplit.uri === baseSplit.uri) {
+                valueSplit.uri = domicile.pseudoLocation.href;
+              }
+              return valueSplit.uri +
+                  (valueSplit.frag === null ? '' : '#' +
+ unsuffix(valueSplit.frag, idSuffix, valueSplit.frag));
             }
           case html4.atype.URI_FRAGMENT:
             if (realValue && '#' === realValue.charAt(0)) {
@@ -2779,6 +2808,25 @@
       // configuration.
       var NP_writePolicyOnly = PT.filter(false, identity, true, identity);

+      function NP_UriValuedProperty(schemaEl, schemaAttr) {
+        return Props.markPropMaker(function(env) {
+          var prop = env.prop;
+          return {
+            // this is not just an attribute wrapper because the .href is
+            // expected to be absolute even if the attribute is not.
+            // But we can still use the same virt logic.
+            get: env.amplifying(function(privates) {
+              return virtualizeAttributeValue(
+                  html4.atype.URI, privates.feral[prop]);
+            }),
+            set: env.amplifying(function(privates, value) {
+              privates.feral.href = rewriteAttribute(
+                  schemaEl, schemaAttr, html4.atype.URI, value);
+            })
+          };
+        });
+      }
+
       var nodeClassNoImplWarnings = {};
       var elementTamerCache = {};
       function makeTameNodeByType(node) {
@@ -4609,8 +4657,7 @@
             false,
             // TODO(felix8a): add suffix if href is self
             identity),
-          // TODO(felix8a): fragment rewriting?
-          href: NP_writePolicyOnly
+          href: NP_UriValuedProperty('a', 'href')
         }; }
       });

=======================================
--- /trunk/tests/com/google/caja/plugin/test-domado-dom-guest.html Wed Aug 14 04:56:12 2013 UTC +++ /trunk/tests/com/google/caja/plugin/test-domado-dom-guest.html Wed Aug 21 21:36:49 2013 UTC
@@ -3254,28 +3254,30 @@
 </script>

 <div class="testcontainer" id="testHash">
-  <a id='test-hash' href="#foo">test a.hash</a>
+  <a id='test-hash' href="#foo">test a.hash and hash in a.href</a>
 </div>
 <script type="text/javascript">
   jsunitRegister('testHash', function testHash() {
     var a = document.getElementById('test-hash');
+
     assertEquals('#foo', a.hash);
     // a.href is an absolute url; a.getAttribute('href') is just the hash
     assertEquals('#foo', a.getAttribute('href'));
-    // TODO(felix8a): maybe this should succeed?
-    //assertEquals('#foo', a.href.substr(-4));
+    assertEquals(window.location + '#foo', a.href);
+
     a.hash = '#bar';
     assertEquals('#bar', a.hash);
     // setting a.hash forces a.getAttribute('href') to be a resolved url
-    // TODO(felix8a): maybe this should succeed?
-    //assertEquals('#bar', a.href.substr(-4));
-    pass('testHash');
+    assertEquals(window.location + '#bar', a.getAttribute('href'));
+    assertEquals(window.location + '#bar', a.href);
+
+    pass();
   });
 </script>

 <div class="testcontainer" id="testBaseURI"></div>
 <script type="text/javascript">
-  jsunitRegister('testBaseURI', function testHash() {
+  jsunitRegister('testBaseURI', function testBaseURI() {
     // http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-baseURI
     var loc = window.location;
     assertEquals(
=======================================
--- /trunk/tests/com/google/caja/plugin/test-domado-global-location.js Wed Aug 14 04:56:12 2013 UTC +++ /trunk/tests/com/google/caja/plugin/test-domado-global-location.js Wed Aug 21 21:36:49 2013 UTC
@@ -50,6 +50,8 @@
         '',
         window.location.search);
   }
+
+ assertEquals('implicit toString', window.location.href, '' + window.location);

   // document.location is an identical property to window.location
   assertTrue('document.location', window.location === document.location);
=======================================
--- /trunk/tests/com/google/caja/plugin/third-party-tests.json Tue Aug 13 22:39:24 2013 UTC +++ /trunk/tests/com/google/caja/plugin/third-party-tests.json Wed Aug 21 21:36:49 2013 UTC
@@ -124,7 +124,7 @@
       },
       {
         "guest": "css",
-        "expected-pass": { "firefox": 239, "chrome": 241 },
+        "expected-pass": { "firefox": 237, "chrome": 241 },
         "comment": [
           "Current failure categories:",
             "Not yet examined."
@@ -222,7 +222,7 @@
       },
       {
         "guest": "dialog",
-        "expected-pass": { "firefox": 294, "chrome": 306 },
+        "expected-pass": { "firefox": 291, "chrome": 306 },
         "comment": [
           "Current failure categories:",
             "What may be event simulation failures",
@@ -271,7 +271,7 @@
       },
       {
         "guest": "tabs",
-        "expected-pass": { "firefox": 487, "chrome": 519 },
+        "expected-pass": { "firefox": 547, "chrome": 594 },
         "comment": [
           "Current modifications made to test suite:",
"Work around lost-signal problems due to lack of event simulation",

--

--- You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to