Macro bug fixes / enhancements

(edit: now fixed in svn head for Velocity 1.6. leaving this note up until Velocity 1.6 is released. Will)

some notes by Will <wglass@forio.com>.

I'm starting to look into the remain bug fix/enhancements for the 1.5 release.
Not surprisingly, many of the remaining issues are all pretty subtle. I thought I'd publically share a few notes on macros.

Here's a catalog of the open macro-related issues targeted for 1.5.

Most of these issues stem from how Velocity stores macros. Macros can be stored either at a global level or on a per-template level. This is controlled by the config key "velocimacro.permissions.allow.inline.local.scope", which is false by default. (i.e. all macros are part of global scope). See the developer's guide.

This means that the following common-sense use case (referenced in VELOCITY-277, VELOCITY-362, and VELOCITY-136) just doesn't work.

file1.vm

#parse("macros.txt")

#NewMacro()

macros.txt

#macro(NewMacro) do something #end

Here's why. Case 1. If "velocimacro.permissions.allow.inline.local.scope" is true, then #NewMacro is defined in "macros.txt" but not "file1.vm". Thus the macro is not available for use.

Case 2. If "velocimacro.permissions.allow.inline.local.scope" is false, then then #NewMacro is defined globally and available from all templates. This seems like a good idea but is impractical in practice for the following reasons.

  • First of all, it doesn't work. Hence the first three bugs. They are technically not bugs since this behavior is documented, though that's difficult to find.
  • Currently macros are evaluated at parse time while #parse is evaluated at runtime. (allowing the template to dynamically choose a page to include). That's why the macro is not picked up by the #parse.
  • Even if we fix this, there's a threading problem and a namespace problem. This macro is available to any template. If a website has hundreds or thousands of templates, there's no guarantee that another page hasn't defined a macro with the same name which could be loaded into the same common name space unexpectedly. The results could be very hard to debug.

Proposed Solution: Add a new mode for macros. (really, this should be the default in the future), which is request based. When a macro is defined in a page, it should be follow the execution of the page, be available in any subpages called with #parse and be available to a calling page that has called this with #parse. However, the macro shouldn't interfere with the global namespace or any non-related templates.

Open issues / discussion points -

  • Can this be done while preserving Velocity's high-performance template caching?
  • If we add a new scope for macros, is this backwards compatible? (assuming we allow old modes to continue to work).
  • No labels