Migrating from Ajax Minifier Version 4.x to Version 5
have any migration issues. However, if you are using the parser, node, and visitor classes directly from the library, there are a number of breaking changes in this release.
Working from the command-line should be the same with version 5 as it is with version 4; no changes needed.
Working with the Minifier class should be the same with version 5 as it is with version 4; no changes needed.
Working with any of the AjaxMin build tasks should be the same with version 5 as it is with version 4; no changes needed.
Obsolete Properties and Methods
All methods that were previously marked with the Obsolete attribute have been removed. If you were using any of these properties or methods, your code will need to migrate to the new alternative method.
If you are creating your own classes derived from IVisitor and performing operations on parsed abstract syntax trees, you will need to add a number of methods to your class to correspond to the new AST nodes:
- void Visit(BindingIdentifier node); // a binding name associated to a field
- void Visit(ClassNode node); // a class declaration
- void Visit(ComprehensionNode node); // array and generator comprehension expressions
- void Visit(ComprehensionForClause node); // comprehension for-clause
- void Visit(ComprehensionIfClause node); // comprehension if-clause
- void Visit(ExportNode node); // export statement
- void Visit(ImportExportSpecifier node); // name specifier for import and export statements
- void Visit(ImportNode node); // import statement
- void Visit(InitializerNode node); // node representing an optional initializer for a binding
- void Visit(ModuleDeclaration node); // module declaration
- void Visit(TemplateLiteral node); // template literal; may contain zero or more template literal expressions
- void Visit(TemplateLiteralExpression node); // an expression portion of a template literal
Node constructors no longer require a JSParser object be passed to them. The vast majority of the classes simply take a Context object that describes where the node exists in the source code.
Some node classes will have no changes (other than the constructor). Others may have a couple different properties and methods. For example, the VariableDeclaration node used to have a string property, Identifier, representing the name of the variable being
declared, and an AstNode property, Initializer, representing the optional initializer. With ES6 destructuring available now, the VariableDeclaration class derives from the new InitializerNode class, and it has an AstNode property, Binding, which may be a BindingIdentifier
(the name part of the previous architecture), or it may be an ArrayLiteral or ObjectLiteral object. The InitializerNode is now where the AstNode property, Initializer, lives. It’s more complex than the v4 architecture, but it needs to be flexible enough to
handle the ES6 destructuring syntax. Most of the node changes in this release as because of the destructuring syntax, although there were a lot of clean-up for duplicated properties and information.
Node ToCode Methods No Longer Supported
OutputVisitor. The Apply method on the
OutputVisitor class has two overrides: one that take a
TextWriter stream reference, and one that does not. Both take the node to output and a
CodeSettings object. This not only gives finer control over output settings, but also allows for different output visitors to be used. For example, if you know the parsed nodes represent a JSON object (and no other nodes/structures
that aren’t supported by JSON syntax), you could also use the new
JSONOutputVisitor class to generate valid JSON output. This method also allows the output to be generated directly to a stream rather than to a memory string that might need to then be copied to a stream. The stream could have the appropriate
JSEncoderFallback object applied to it, should
\uXXXX escape sequences be required for the output. If you want the exact same equivalent to the old
ToCode() method, use the override for
OutputVisitor.Apply that takes the node and the settings objects and returns the generated string.
Over the years, the ways of using the JSParser object morphed until it became basically the opposite of what I would expect the class to do. In Version 4.x of the tool, one created the JSParser object by passing in a string of source code. You could optionally
put a context (file name, for instance) on the parser. Then to parse the code, you called the Parse method and passed in a CodeSettings object. This made parsing multiple script parts within the same global context extremely difficult, as it required a new
JSParser object for each segment, and a method of sharing the global namespace between them.
In version 5, the process has significantly changed. JSParser objects can be created with no arguments and stand alone, maintaining their global namespace. The Parse method can now be called any number of times with any number of different source code segments,
and they will all be parsed into the same global namespace. The CodeSettings object can be set on the JSParse.Settings property once, or it can be specified each time Parse is called with an optional parameter. This facilitates parsing multiple segments, as
in multiple scripts within a single webpage for instance: one JSParser object for the page, with multiple calls to the Parse method for each segment, each building upon the previous.