Attributes

Being able to write code in C# is a lovely thing, but chances are that you also want to interact with JavaScript libraries that are written without Saltarelle in mind. The compiler has been written with this in mind, so it has a large number of options available to customize the generated script for this. All these customizations are performed by applying attributes. This page lists the available options. All attributes in this section are in the System.Runtime.CompilerServices namespace.

Attributes that control the generated script

IgnoreNamespaceAttribute

If this attribute is used, the type is pretended have no namespace in the generated script. This is equivalent to [ScriptNamespace("")].

ScriptNamespaceAttribute

This attribute can be used to specify the namespace in which the type appears in the generated script.

ResourcesAttribute

This attribute can be placed on a static class that only contains static fields representing a set of resource strings.

Example:

[Resources]
public static class MyResources {
	public const int MyInt = 1;
	public const string MyString = "x";
} 

is compiled to

MyResources = { myInt: 1, myString: 'x' }; 

GlobalMethodsAttribute

This attribute means that all members on the type (which must be static) to which it is applied are generated and treated as global members (or members directly on the exports object if applied to a module with a [ModuleNameAttribute]).

Example:

[GlobalMethods]
public static class MyStaticMethods {
	public static void MyMethod() {
	}
} 

is compiled to

window.myMethod = function() {
}; 

MixinAttribute

This attribute is similar to the GlobalMethodsAttribute, but it allows you to specify a prefix for the generated methods.

Example:

[Mixin("$.fn")]
public static class MyStaticMethods {
	public static void MyMethod() {
	}
} 

is compiled to

$.fn.myMethod = function() {
}; 

IntrinsicPropertyAttribute

If specified on a property, tells the compiler to treat that property as a field. If specified on an indexer, tells the compiler to treat the indexer (which must have exactly one argument) as an array access.

Interoperability attributes

ImportedAttribute

This attribute should be used on types that are defined in an external script. No code will be generated for the type, and all members are treated as having a [PreserveNameAttribute] unless they are decorated with another attribute. The type will be treated as Object if inheriting from it or using it as a generic argument (unless the ObeysTypeSystem property on the attribute is true).

Imported types and all their members ignore their generic arguments, except an [IncludeGenericArgumentsAttribute(true)] is also specified on the type or member.

NamedValuesAttribute

If specified on an enum, the members of that enum are strings instead of integers. Since this is not supported in C#, they might behave a little strange and should be use sparingly.

NumericValuesAttribute

The opposite of NamedValuesAttribute, causes that behavior to not be used. Since this is the default, this attribute is never needed, but can be used for documentation purposes.

ScriptNameAttribute

This attribute allows you to specify the name of a member or type in script. What you write here is exactly what you get, no camel casing is applied to the name. An empty name can be specified for a constructor to specify which is the unnamed constructor. For compatibility with Script#, the empty name can also be used on methods, but for new code it is recommended to use [InlineCodeAttribute] in these instances since the intention is clearer. If the name is not a valid Javascript identifier, indexing expressions (objec[member]) will be used for all accesses to the member.

PreserveCaseAttribute

Acts as PreserveNameAttribute, and also specifies that camel casing is not applied to the member to which it is applied.

PreserveMemberCaseAttribute

This attribute can be applied to a type or an assembly to prevent the default behaviour of camel-casing members. It will not affect minimization.

PreserveNameAttribute

This attribute causes a member not to be renamed in the generated script, neither due to minimization nor due to overloading or shadowing.

MinimizePublicNamesAttribute

Can be set on an assembly to indicate that public symbols are minimized in addition to non-public ones (unless an attribute that prevents this is present on the member).

ScriptAliasAttribute

This attribute allows specifying a global, potentially nested script name for an imported method or property.

Example: Given this type:

public static class jQueryHistory {
    [ScriptAlias("$.bbq.getState")]
    public static object GetState(string key) {
        return null;
    }
} 

The call

jQueryHistory.GetState("myKey") 

is compiled to

$.bbq.getState('myKey') 

ScriptSkipAttribute

Specifies that calls to the method will be ignored. The method must either be an instance method with no arguments, or a static method (or, commonly, operator) with one argument.

InlineConstantAttribute

Can be specified on a const field to indicate that the literal value should always be used instead of the symbolic name, even in non-minimized builds.

InlineCodeAttribute

This is the most powerful of the interop attributes, and can perform virtually any syntax transformation you want (actually, internally, many of the other interop attributes are implemented as special cases of this one). It allows you to specify a special format string that has access to all arguments and type arguments in the call.

Example:

The AutoOpen property of the jQueryUI DialogObject has the following definition:

public bool AutoOpen {
    [InlineCode("{this}.dialog('option', 'autoOpen')")]
    get;
    [InlineCode("{this}.dialog('option', 'autoOpen', {value})")]
    set;
} 

This means that the call

myDialog.AutoOpen = true 

will be transformed to

myDialog.dialog('option', 'autoOpen', true) 

The special format string can contain literal text as well as placeholders within braces ( {ph} ). As in a .net format string, duplicate the braces if you want a literal brace.
Placeholders can be the following:

  • {name}, where name is one of the parameters to the method, or one of the type parameters to the method or its declaring type. The argument (or type argument) will be substituted.
  • {this} (for instance methods). The invocation target will be substituted.
  • {$Namespace.Type}. Used to reference another type. The actual type name in script will be substituted. This form should always be used in favor of just specifying the script type name literally.
  • {*arg}, where arg is a param array parameter. The entire array supplied for the parameter will be inserted into the location of this placeholder. Pretend that the parameter is a normal parameter, and commas will be inserted or omitted at the correct locations.
  • [email protected]}, where arg is a string parameter. The argument has to be a literal string (or a compile error is issued), which is inserted literally without quotes in this position. This can be used to transform a call like x.set("X", y) to x.set_X(y).

It is possible to specify that code is also generated for the member (the GeneratedMethodName property) and that different code should be generated when invoking the method non-virtually as a base member access (the NonVirtualCode property), but these features are probably of little use outside of mscorlib.

InstanceMethodOnFirstArgument

This attribute can be used on a static method to indicate that it is to be treated as an instance method on the first argument. Useful for some extension methods (which, without this attribute, are treated as normal static methods).

IncludeGenericArgumentsAttribute

This attribute is used to specify (per type or method) for generic entities whether they should be treated as generic in script. The default for the assembly is set with the IncludeGenericArgumentsDefaultAttribute.

IncludeGenericArgumentsDefaultAttribute

This attribute is used to define how an assembly treats generic types which do not have an [IncludeGenericArgumentsAttribute]. Different defaults are set for types (the TypeDefault property) and methods (the MethodDefault property). The possibility for each of these properties are:

  • IncludeExceptGeneric (the default): Generic arguments are included, except for generic types.
  • Ignore: Generic arguments are ignored.
  • RequireExplicitSpecification: All generic types/methods require an [IncludeGenericArgumentsAttribute], otherwise a compilation error is issued. Types with an [ImportedAttribute], and methods of such types, are exempted from the rule and their generic arguments are ignored by default.

IntrinsicOperatorAttribute

Used to specify that a call to a user-defined operator is to be treated as if it were non-userdefined. Probably of limited use outside of mscorlib.

ExpandParamsAttribute

Specifies that the param array parameter to a method or delegate should be expanded at the call site.

BindThisToFirstParameterAttribute

When applied to a delegate, the first parameter to the delegate will be the “this context” for which the delegate was invoked. This is used extensively in jQuery to be able to do things like this:

jQuery.Select("#el").Blur((el, evt) => {
    // el will be the element on which the event occurred.
    // evt will be the event that occurred.
}); 

where el will be the element for which the (implicitly created) delegate was invoked, even though the jQuery source at the call site did something like m.call(theElement, theEvent).

ObjectLiteralAttribute

If this attribute is applied to a constructor for a serializable type, it means that the constructor will not be called, but rather an object initializer will be created. Eg. new MyRecord(1, "X") can become { a: 1, b: 'X' }. All parameters must have a field or property with the same (case-insensitive) name, of the same type.

This attribute is implicit on constructors for imported serializable types.

EnumerateAsArrayAttribute

This attribute can be specified on a public GetEnumerator() method to specify that whenever this method is used for a foreach statement, it will be enumerated with a for loop, as if it were an array.

Other attributes

ModuleNameAttribute

When specified on an assembly, specifies that all types in it are to be imported from a module with this name. This will also cause code to be generated to publish types to the exports object instead of globally, so it can be used to generate code that lives in a module. When specified on a type, indicates that the type lives in a module with the specified name.

AsyncModuleAttribute

If this attribute is specified, the script generated for a module will conform to the AMD specification, which means the entire module will be wrapped in a define() call, with all required dependencies (as long as those dependencies have a [ModuleNameAttribute]).

NonScriptableAttribute

This attribute can be applied to specify that a method cannot be used from script (and that no code will be generated for it). It probably has little use outside of mscorlib.

AlternateSignatureAttribute

This attribute specifies that a method is just another way of calling another method. Exactly one method in the method group (the set of methods with the same name) must not have this attribute, and is the method that will actually end up getting called. This is mainly intended to be used by people who are porting Script# code. In new code, it should rarely have to be used since Saltarelle supports proper overloads.

Note: Unlike in Script#, you should not mark methods with this attribute as external. Using that modifier seems to trigger all kinds of internal errors in mcs.

ScriptSharpCompatibilityAttribute

This attribute can be used on an assembly to specify additional options for compatibility with Script#. Using any of these options means you may have latent bugs in your code, but the attribute is provided to ease migration from Script#. The available options are:

  • OmitDowncasts: If true, code will not be generated for casts of type (MyClass)someValue. Code will still be generated for someValue is MyClass and someValue as MyClass.
  • OmitNullableChecks: If true, code will not be generated to verify that a nullable value is not null before converting it to its underlying type.