}
break;
case SCRIPT:
String handlerFnName = handlerCache.get(value);
if (handlerFnName == null) {
Block b = jsFromAttrib(attr);
if (b == null || b.children().isEmpty()) { return noResult(attr); }
rewriteEventHandlerReferences(b);
handlerFnName = meta.generateUniqueName("c");
Declaration handler = (Declaration) QuasiBuilder.substV(
""
+ "var @handlerName = ___./*@synthetic*/markFuncFreeze("
+ " /*@synthetic*/function ("
+ " event, " + ReservedNames.THIS_NODE + ") { @body*; });",
"handlerName", SyntheticNodes.s(
new Identifier(FilePosition.UNKNOWN, handlerFnName)),
"body", new ParseTreeNodeContainer(b.children()));
handlers.add(new EventHandler(attr.env, handler));
handlerCache.put(value, handlerFnName);
}
FunctionConstructor eventAdapter
= (FunctionConstructor) QuasiBuilder.substV(
""
+ "(/*@synthetic*/ function (event) {"
+ " return /*@synthetic*/ (___.plugin_dispatchEvent___("
+ " /*@synthetic*/this, event, "
+ " ___./*@synthetic*/getId(IMPORTS___), @tail));"
+ "})",
"tail", new Reference(SyntheticNodes.s(
new Identifier(pos, handlerFnName))));
eventAdapter.setFilePosition(pos);
eventAdapter.getAttributes().set(HANDLER_NAME, handlerFnName);
dynamicValue = eventAdapter;
break;
case STYLE:
CssTree.DeclarationGroup decls = styleFromAttrib(attr);
if (decls == null || decls.children().isEmpty()) {
return noResult(attr);
}
// The validator will check that property values are well-formed,
// marking those that aren't, and identifies all URLs.
CssValidator v = new CssValidator(cssSchema, htmlSchema, mq)
.withInvalidNodeMessageLevel(MessageLevel.WARNING);
v.validateCss(AncestorChain.instance(decls));
// The rewriter will remove any unsafe constructs.
// and put URLs in the proper filename namespace
new CssRewriter(meta.getUriPolicy(), cssSchema, mq)
.withInvalidNodeMessageLevel(MessageLevel.WARNING)
.rewrite(AncestorChain.instance(decls));
new CssDynamicExpressionRewriter(meta).rewriteCss(decls);
ArrayConstructor jsValue = CssDynamicExpressionRewriter.cssToJs(decls);
if (jsValue.children().size() == 0) {
// No declarations remain after sanitizing
return noResult(attr);
} else if (jsValue.children().size() == 1) {
// Declarations have been reduced to a single, statically known
// StringLiteral or dynamically computed Expression
dynamicValue = jsValue.children().get(0);
} else {
throw new SomethingWidgyHappenedError(
"Rewriter thinks STYLE attribute should contain plugin ID");
}
break;
case URI:
if (attributeContent.containsKey(attr.src)) { // A javascript: URI
Block b = this.jsFromAttrib(attr);
if (b == null || b.children().isEmpty()) { return noResult(attr); }
String handlerIndexName = meta.generateUniqueName("c");
Identifier handlerIndex = SyntheticNodes.s(new Identifier(
FilePosition.UNKNOWN, handlerIndexName));
Statement handler = (Statement) QuasiBuilder.substV(
""
+ "var @handlerIndex = IMPORTS___.handlers___.push("
+ " ___./*@synthetic*/markFuncFreeze("
// There is no node or event object available to code in
// javascript: URIs.
+ " /*@synthetic*/function () { @body*; })) - 1;",
"handlerIndex", handlerIndex,
"body", new ParseTreeNodeContainer(b.children()));
handlers.add(new EventHandler(attr.env, handler));
handlerCache.put(value, handlerIndexName);
Operation urlAdapter = (Operation) QuasiBuilder.substV(
""