Author: felix8a
Date: Wed Jul 8 13:28:33 2009
New Revision: 3563
Modified:
trunk/src/com/google/caja/lang/html/html4-attributes-defs.json
trunk/src/com/google/caja/plugin/templates/TemplateCompiler.java
trunk/tests/com/google/caja/plugin/templates/TemplateCompilerTest.java
Log:
fix 1056, NPE when cajoling <textarea>, and relax about mandatory attrs
http://codereview.appspot.com/90071
The new html emitter is more aggressive about emitting default
values for attributes that the html spec claims are not optional.
1. The spec for <textarea> says the cols= attribute isn't optional,
but doesn't specify an acceptable default value. caja tries to
emit a default anyway, which is an NPE.
2. It seems to me that caja should not be forcing default values
if I haven't specified one. For example, <img> without alt=
is meaningfully different from <img alt=''>. I don't see any
reason for caja to normalize these attributes, rather than
letting the browser do it naturally.
r=ihab.a...@gmail.com
Modified: trunk/src/com/google/caja/lang/html/html4-attributes-defs.json
==============================================================================
--- trunk/src/com/google/caja/lang/html/html4-attributes-defs.json
(original)
+++ trunk/src/com/google/caja/lang/html/html4-attributes-defs.json Wed Jul
8 13:28:33 2009
@@ -5,7 +5,9 @@
"Derived by taking
http://www.w3.org/TR/html401/index/attributes.html",
"and copying&pasting it into a text file which gave me a 7 column
file:",
" Name Related Elements Type Default Depr. DTD
Comment",
- "and running html4-attributes.pl."
+ "and running html4-attributes.pl.",
+ "Note, there are some deviations from html401's declaration of
optional",
+ "because optional=false is used to force mandatory attributes."
],
"types": [
@@ -90,9 +92,9 @@
{ "key": "APPLET::ALT", "description": "short description",
"optional": true },
{ "key": "AREA::ALT", "description": "short description",
- "optional": false },
+ "optional": true },
{ "key": "IMG::ALT", "description": "short description",
- "optional": false },
+ "optional": true },
{ "key": "INPUT::ALT", "description": "short description",
"optional": true },
{ "key": "APPLET::ARCHIVE", "description": "comma-separated archive
list",
@@ -194,7 +196,7 @@
{ "key": "FRAMESET::COLS", "description": "list of lengths, default:
100% (1 col)",
"optional": true },
{ "key": "TEXTAREA::COLS",
- "pattern": "[0-9]+", "optional": false },
+ "pattern": "[0-9]+", "optional": true },
{ "key": "TD::COLSPAN", "description": "number of cols spanned by
cell",
"pattern": "[0-9]+", "default": "1", "optional": true },
{ "key": "TH::COLSPAN", "description": "number of cols spanned by
cell",
@@ -461,7 +463,7 @@
{ "key": "FRAMESET::ROWS", "description": "list of lengths, default:
100% (1 row)",
"optional": true },
{ "key": "TEXTAREA::ROWS",
- "pattern": "[0-9]+", "optional": false },
+ "pattern": "[0-9]+", "optional": true },
{ "key": "TD::ROWSPAN", "description": "number of rows spanned by
cell",
"pattern": "[0-9]+", "default": "1", "optional": true },
{ "key": "TH::ROWSPAN", "description": "number of rows spanned by
cell",
@@ -507,7 +509,7 @@
{ "key": "IFRAME::SRC", "description": "source of frame content",
"mimeTypes": "text/html", "type": "URI", "optional": true },
{ "key": "IMG::SRC", "description": "URI of image to embed",
- "mimeTypes": "image/*", "type": "URI", "optional": false },
+ "mimeTypes": "image/*", "type": "URI", "optional": true },
{ "key": "OBJECT::STANDBY", "description": "message to show while
loading",
"optional": true },
{ "key": "OL::START", "description": "starting sequence number",
@@ -553,9 +555,9 @@
{ "key": "PARAM::TYPE", "description": "content type for value when
valuetype=ref",
"optional": true },
{ "key": "SCRIPT::TYPE", "description": "content type of script
language",
- "optional": false },
+ "optional": false, "default": "text/javascript" },
{ "key": "STYLE::TYPE", "description": "content type of style
language",
- "optional": false },
+ "optional": false, "default": "text/css" },
{ "key": "INPUT::TYPE", "description": "what kind of widget is
needed",
"pattern": "TEXT|PASSWORD|CHECKBOX|RADIO|SUBMIT|RESET|FILE|HIDDEN|
IMAGE|BUTTON", "default": "TEXT", "optional": true },
{ "key": "LI::TYPE", "description": "list item style",
Modified: trunk/src/com/google/caja/plugin/templates/TemplateCompiler.java
==============================================================================
--- trunk/src/com/google/caja/plugin/templates/TemplateCompiler.java
(original)
+++ trunk/src/com/google/caja/plugin/templates/TemplateCompiler.java Wed
Jul 8 13:28:33 2009
@@ -228,6 +228,13 @@
} else {
safeValue = a.getSafeValue();
}
+ if (safeValue == null) {
+ mq.addMessage(IhtmlMessageType.MISSING_ATTRIB,
+ Nodes.getFilePositionFor(el),
+ MessagePart.Factory.valueOf(elName.toString()),
+ MessagePart.Factory.valueOf(attrNameStr));
+ continue;
+ }
attr.setNodeValue(safeValue);
el.setAttributeNode(attr);
}
Modified:
trunk/tests/com/google/caja/plugin/templates/TemplateCompilerTest.java
==============================================================================
--- trunk/tests/com/google/caja/plugin/templates/TemplateCompilerTest.java
(original)
+++ trunk/tests/com/google/caja/plugin/templates/TemplateCompilerTest.java
Wed Jul 8 13:28:33 2009
@@ -245,7 +245,7 @@
assertSafeHtml(
htmlFragment(fromString("<img src='blank.gif' width='20'/>")),
htmlFragment(fromString(
- "<img alt='' src='/proxy?url=test%3A%2Fblank.gif"
+ "<img src='/proxy?url=test%3A%2Fblank.gif"
+ "&mime-type=image%2F%2A' width='20'/>")),
new Block());
}
@@ -336,6 +336,18 @@
+ " emitter___.signalLoaded();"
+ "}"
)));
+ }
+
+ /**
+ * <textarea> without cols= was triggering an NPE due to buggy handling
+ * of mandatory attributes.
+ * http://code.google.com/p/google-caja/issues/detail?id=1056
+ */
+ public void testBareTextarea() throws Exception {
+ assertSafeHtml(
+ htmlFragment(fromString("<textarea></textarea>")),
+ htmlFragment(fromString("<textarea></textarea>")),
+ new Block());
}
private void assertSafeHtml(