-
Notifications
You must be signed in to change notification settings - Fork 1.2k
JS Conformance Framework
The JS Conformance framework is tool that is part of the Closure Compiler that allows developers to specify configuration for automatically checking compiled code for conformance to certain requirements, such as forbidding access to a certain property or calls to a certain function.
Conformance rules are provided to the Closure Compiler as arguments, and they are enforced during compilation and are reported as warnings (which can be promoted to errors). The conformance rules are enforced strictly, which in this case means that insufficient type information, can result in a “possible violation” warning rather than not being reported at all (this has the interesting side-effect of revealing lacking type information in unexpected places).
To invoke the Closure Compiler with a conformance configuration, pass the "--conformance_configs" flag to the compiler with a list of files that contain the conformance config.
Ex: java -jar build/compiler.jar --conformance_configs
my_conformance_config.textproto
If invoking the compiler programmatically, the setConformanceConfig
or setConformanceConfigs
function can be called in the CompilerOptions
class.
Each requirement has three required fields: “type”, “value”, and “error_message”
type is used to trigger the specific kind or require as described below.
value is a type specific value as described below. The type and meaning of this value depends on the type parameter. As a convenience “value” may be repeated to create a set of related rules that shared the same type, error_message and whitelist.
error_message is the message reported when the requirement is violated. The error_message should include short link a document that describes the reason for the requirement and a means for discussing the requirement.
Additionally, every requirement may have zero or more whitelist and/or whitelist_regexp entries. The each whitelist entry contains a path prefix of file that are allowed to violate the requirement. A complete path can be provide to whitelist a single file. The whitelist_regexp entry is an Java RegExp pattern and files that match the pattern are allowed to violate the requirement.
An example conformance configuration looks like:
requirement: {
type: BANNED_PROPERTY_WRITE
value: 'Location.prototype.href'
error_message: 'Assignment to Location.prototype.href '
'is not allowed. Use '
'goog.dom.safe.setLocationHref instead.'
whitelist: 'javascript/closure/dom/safe.js'
}
The system defines several different built-in requirement types it can enforce, and allows you to write custom requirements implemented in an external Java class.
A forbidden code pattern. Provides a way of banning code patterns.
The value for is a RefasterJS style template function. The function template is a literal AST match, where the function parameters are used to perform type matches. Due to the literal nature of the pattern comparison, patterns should be as simple as possible to avoid missing variations.
This value would ban throwing the text “error”:
function template() { throw ‘error’ }
This value would ban throwing a string value or a string object:
/** @param {string|String} str */
function template(str) { throw str }
See the RefasterJS documentation for details.
A forbidden fully distinguished name. The value for this rule is the fully distinguished name. For example:
- A global name like "eval" or "goog"
- A namespaced value: “namespace.banned”
- A 'static' property: "namespace.Foo.banned"
NOTE: This can not be used to ban a JS keyword like “with” or “debugger” or “this”.
A banned instance property. The value for this rule is the fully distinguished type name, the separating to token “.prototype.” followed by the banned property. For example:
- An 'instance' property: "namespace.Foo.prototype.banned"
- All properties of a given name "Object.prototype.banned"
NOTE: “prototype” is used here simply to separate the type name from the property. It is not limited to properties declared on the prototype. Specifically, properties assigned to an instance of a type would still be checked (such as in the constructor). Additionally, the property being banned does not need a known member of the type.
An banned instance property, like BANNED_PROPERTY but where writes of the property are allowed. The value for this rule follows the same format as BANNED_PROPERTY. For example:
- An 'instance' property: "namespace.Foo.prototype.banned"
- All properties of a given name "Object.prototype.banned"
NOTE: This allows definitions (“Foo.prototype.banned = … “) but not use (“new Foo().banned()).
An banned instance property, like BANNED_PROPERTY but where reads of the property are allowed. The value for this rule follows the same format as BANNED_PROPERTY. For example:
- An 'instance' property: "namespace.Foo.prototype.banned = 1"
- All properties of a given name "Object.prototype.banned++"
A banned function call. For example:
- An 'instance' property: "namespace.Foo.prototype.banned"
- All properties of a given name: "Object.prototype.banned"
Unlike BANNED_PROPERTY, this only bans calls to the property, i.e. using the property as a value is allowed.
A restricted call to a fully distinguished name. The value for this rule provides an alternate type signature for a function to which all call sites must conform. The format for this value is the fully distinguished name, a separating “:”, followed by function type signature. For example:
- the "parseInt" call must be called with a radix: parseInt:function(string, int)
NOTE: This rule does not override a type signature. The call site will be validated by both the original function signature during normal type checking and by the signature provided by the rule.
A restricted call to an instance property. As with RESTRICTED_NAME_CALL, the value for this rule provides an alternative type signature. The property is declared as with BANNED_PROPERTY.
The http://closure-compiler-debugger.appspot.com/ service contains a spot to write a conformance configuration and test it on sample code. In addition to verifying that it correctly catches the code that it should, the page also has fields for Compiler Warnings and source AST to help debug any problems.
Example conformance checks can be found at https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/example_conformance_proto.textproto - these conformance configurations can be copied into your own project's configuration.