Skip to content

Commit fc4cb57

Browse files
author
epriestley
committedJan 29, 2013
Fix JSON encoding of PhutilSafeHTML for browser consumption
Summary: If you run this code: json_encode(array('tag' => phutil_tag('div', array()))); ...you get this result, because json_encode() does not call toString() on objects: {"tag":{}} Instead, convert such objects to their underlying strings. Javelin has support for JX.HTML and for implicit conversion (which is kind of sketchy for other reasons) but it's sort of complicated (only happens on Ajax, not behaviors) and messy (not metadata-based), so ignore it for now. We'll need to do something similar for serialization to the database. My plan there is just to throw on any objects. The only time we put HTML in the database is cache-related and those tiny number of callsites can manually handle it. Test Plan: Various ajax things now receive the correct data. Reviewers: vrana Reviewed By: vrana CC: aran Maniphest Tasks: T2432 Differential Revision: https://secure.phabricator.com/D4684
1 parent 47f2df5 commit fc4cb57

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed
 

‎externals/javelinjs/src/lib/DOM.js

+11
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,18 @@ JX.$ = function(id) {
8787
JX.install('HTML', {
8888

8989
construct : function(str) {
90+
if (str instanceof JX.HTML) {
91+
this._content = str._content;
92+
return;
93+
}
94+
9095
if (__DEV__) {
96+
if ((typeof str !== 'string') && (!str || !str.match)) {
97+
JX.$E(
98+
'new JX.HTML(<empty?>): ' +
99+
'call initializes an HTML object with an empty value.');
100+
}
101+
91102
var tags = ['legend', 'thead', 'tbody', 'tfoot', 'column', 'colgroup',
92103
'caption', 'tr', 'th', 'td', 'option'];
93104
var evil_stuff = new RegExp('^\\s*<(' + tags.join('|') + ')\\b', 'i');

‎src/aphront/response/AphrontResponse.php

+15-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,21 @@ public function setFrameable($frameable) {
5454
return $this;
5555
}
5656

57-
protected function encodeJSONForHTTPResponse(array $object) {
57+
public static function processValueForJSONEncoding(&$value, $key) {
58+
if ($value instanceof PhutilSafeHTML) {
59+
// TODO: Javelin supports implicity conversion of '__html' objects to
60+
// JX.HTML, but only for Ajax responses, not behaviors. Just leave things
61+
// as they are for now (where behaviors treat responses as HTML or plain
62+
// text at their discretion).
63+
$value = $value->getHTMLContent();
64+
}
65+
}
66+
67+
public static function encodeJSONForHTTPResponse(array $object) {
68+
69+
array_walk_recursive(
70+
$object,
71+
array('AphrontResponse', 'processValueForJSONEncoding'));
5872

5973
$response = json_encode($object);
6074

‎src/infrastructure/celerity/CelerityStaticResourceResponse.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ private function renderResource(array $resource) {
128128
public function renderHTMLFooter() {
129129
$data = array();
130130
if ($this->metadata) {
131-
$json_metadata = json_encode($this->metadata);
131+
$json_metadata = AphrontResponse::encodeJSONForHTTPResponse(
132+
$this->metadata);
132133
$this->metadata = array();
133134
} else {
134135
$json_metadata = '{}';
@@ -164,7 +165,9 @@ public function renderHTMLFooter() {
164165
if (!$group) {
165166
continue;
166167
}
167-
$onload[] = 'JX.initBehaviors('.json_encode($group).')';
168+
$group_json = AphrontResponse::encodeJSONForHTTPResponse(
169+
$group);
170+
$onload[] = 'JX.initBehaviors('.$group_json.')';
168171
}
169172
}
170173

0 commit comments

Comments
 (0)
Failed to load comments.