jscrewit
Version:
Converts plain JavaScript into JSFuck code, which consists of only six different characters: ! ( ) + [ ]
320 lines (298 loc) • 11.2 kB
TypeScript
import type { ElementaryFeatureName, FeatureAll, PredefinedFeatureName } from './feature-all';
export interface CustomFeature extends Feature
{
readonly elementary: false;
}
export interface ElementaryFeature extends PredefinedFeature
{
readonly elementary: true;
readonly name: ElementaryFeatureName;
}
/**
* Objects of this type indicate which of the capabilities that JScrewIt can use to minimize the
* length of its output are available in a particular JavaScript engine.
*
* JScrewIt comes with a set of predefined feature objects exposed as property values of
* `JScrewIt.Feature` or {@link FeatureConstructor.ALL | `JScrewIt.Feature.ALL`}, where the property
* name is the feature's name or alias.
*
* Besides these predefined features, it is possible to construct custom features from the union or
* intersection of other features.
*
* Among the predefined features, there are some special ones called *elementary* features.
* Elementary features either cannot be expressed as a union of any number of other features, or
* they are different from such a union in that they exclude some other feature not excluded by
* their elementary components.
* All other features, called *composite* features, can be constructed as a union of zero or more
* elementary features.
* Two of the predefined composite features are particularly important: {@link
* FeatureConstructor.DEFAULT | `DEFAULT`} is the empty feature, indicating that no elementary
* feature is available at all; {@link FeatureConstructor.AUTO | `AUTO`} is the union of all
* elementary features available in the current environment.
*
* Not all features can be available at the same time: some features are necessarily incompatible,
* meaning that they mutually exclude each other, and thus their union cannot be constructed.
*/
export interface Feature
{
/**
* An array of all elementary feature names included in this feature object, without aliases and
* implied features.
*/
readonly canonicalNames: ElementaryFeatureName[];
/** A boolean value indicating whether this is an elementary feature object. */
readonly elementary: boolean;
/**
* An array of all elementary feature names included in this feature object, without aliases.
*/
readonly elementaryNames: ElementaryFeatureName[];
/**
* The primary name of this feature object, useful for identification purpose.
*
* All predefined features have a name; custom features may be optionally assigned a name, too.
* If a name is assigned, it will be used when the feature is converted into a string.
*/
name?: string;
/**
* Determines whether this feature object includes all of the specified features.
*
* @returns
*
* `true` if this feature object includes all of the specified features; otherwise, `false`.
* If no arguments are specified, the return value is `true`.
*/
includes(...features: FeatureElementOrCompatibleArray[]): boolean;
/**
* Creates a new feature object from this feature by removing elementary features that are not
* available inside a particular environment.
*
* This method is useful to selectively exclude features that are not available in environments
* that require strict mode code, or inside web workers.
*
* @param environment
*
* The environment to which this feature should be restricted.
* Two environments are currently supported.
*
* <dl>
*
* <dt><code>"forced-strict-mode"</code></dt>
* <dd>
* Removes features that are not available in environments that require strict mode code.
* </dd>
*
* <dt><code>"web-worker"</code></dt>
* <dd>Removes features that are not available inside web workers.</dd>
*
* </dl>
*
* @param engineFeatureObjs
*
* An array of predefined feature objects, each corresponding to a particular engine in which
* the restriction should be enacted.
* If this parameter is omitted, the restriction is enacted in all engines.
*/
restrict
(
environment: 'forced-strict-mode' | 'web-worker',
engineFeatureObjs?: readonly PredefinedFeature[],
):
CustomFeature;
}
export const Feature: FeatureConstructor;
export interface FeatureConstructor extends FeatureAll
{
/**
* Creates a new feature object from the union of the specified features.
*
* The constructor can be used with or without the `new` operator, e.g.
* `new JScrewIt.Feature(feature1, feature2)` or `JScrewIt.Feature(feature1, feature2)`.
* If no arguments are specified, the new feature object will be equivalent to
* {@link FeatureConstructor.DEFAULT | `DEFAULT`}.
*
* @example
*
* The following statements are equivalent, and will all construct a new feature object
* including both {@link FeatureConstructor.ANY_DOCUMENT | `ANY_DOCUMENT`} and {@link
* FeatureConstructor.ANY_WINDOW | `ANY_WINDOW`}.
*
* ```js
* new JScrewIt.Feature("ANY_DOCUMENT", "ANY_WINDOW");
* ```
*
* ```js
* new JScrewIt.Feature(JScrewIt.Feature.ANY_DOCUMENT, JScrewIt.Feature.ANY_WINDOW);
* ```
*
* ```js
* new JScrewIt.Feature([JScrewIt.Feature.ANY_DOCUMENT, JScrewIt.Feature.ANY_WINDOW]);
* ```
*
* @throws
*
* An error is thrown if any of the specified features are not mutually compatible.
*/
(...features: FeatureElementOrCompatibleArray[]): CustomFeature;
/**
* An immutable mapping of all predefined feature objects accessed by name or alias.
*
* @example
*
* This will produce an array with the names and aliases of all predefined features.
*
* ```js
* Object.keys(JScrewIt.Feature.ALL)
* ```
*
* This will determine if a particular feature object is predefined or not.
*
* ```js
* featureObj === JScrewIt.Feature.ALL[featureObj.name]
* ```
*/
readonly ALL: FeatureAll;
/** An immutable array of all elementary feature objects ordered by name. */
readonly ELEMENTARY: readonly ElementaryFeature[];
/**
* Creates a new feature object from the union of the specified features.
*
* The constructor can be used with or without the `new` operator, e.g.
* `new JScrewIt.Feature(feature1, feature2)` or `JScrewIt.Feature(feature1, feature2)`.
* If no arguments are specified, the new feature object will be equivalent to
* {@link FeatureConstructor.DEFAULT | `DEFAULT`}.
*
* @example
*
* The following statements are equivalent, and will all construct a new feature object
* including both {@link FeatureConstructor.ANY_DOCUMENT | `ANY_DOCUMENT`} and {@link
* FeatureConstructor.ANY_WINDOW | `ANY_WINDOW`}.
*
* ```js
* JScrewIt.Feature("ANY_DOCUMENT", "ANY_WINDOW");
* ```
*
* ```js
* JScrewIt.Feature(JScrewIt.Feature.ANY_DOCUMENT, JScrewIt.Feature.ANY_WINDOW);
* ```
*
* ```js
* JScrewIt.Feature([JScrewIt.Feature.ANY_DOCUMENT, JScrewIt.Feature.ANY_WINDOW]);
* ```
*
* @throws
*
* An error is thrown if any of the specified features are not mutually compatible.
*/
new (...features: FeatureElementOrCompatibleArray[]): CustomFeature;
/**
* Determines whether the specified features are mutually compatible.
*
* @returns
*
* `true` if the specified features are mutually compatible; otherwise, `false`.
* If less than two features are specified, the return value is `true`.
*
* @example
*
* ```js
* // false: only one of "V8_SRC" or "IE_SRC" may be available.
* JScrewIt.Feature.areCompatible("V8_SRC", "IE_SRC")
* ```
*
* ```js
* // true
* JScrewIt.Feature.areCompatible(JScrewIt.Feature.DEFAULT, JScrewIt.Feature.FILL)
* ```
*/
areCompatible(...features: FeatureElement[]): boolean;
/**
* Determines whether all of the specified features are equivalent.
*
* Different features are considered equivalent if they include the same set of elementary
* features, regardless of any other difference.
*
* @returns
*
* `true` if all of the specified features are equivalent; otherwise, `false`.
* If less than two arguments are specified, the return value is `true`.
*
* @example
*
* ```js
* // false
* JScrewIt.Feature.areEqual(JScrewIt.Feature.CHROME, JScrewIt.Feature.FF)
* ```
*
* ```js
* // true
* JScrewIt.Feature.areEqual("DEFAULT", [])
* ```
*/
areEqual(...features: FeatureElementOrCompatibleArray[]): boolean;
/**
* Creates a new feature object equivalent to the intersection of the specified features.
*
* @returns
*
* A feature object, or `null` if no arguments are specified.
*
* @example
*
* This will create a new feature object equivalent to {@link FeatureConstructor.NAME | `NAME`}.
*
* ```js
* const newFeature = JScrewIt.Feature.commonOf(["ATOB", "NAME"], ["NAME", "SELF"]);
* ```
*
* This will create a new feature object equivalent to {@link FeatureConstructor.ANY_WINDOW |
* `ANY_WINDOW`}.
* This is because both {@link FeatureConstructor.DOMWINDOW | `DOMWINDOW`} and {@link
* FeatureConstructor.WINDOW | `WINDOW`} imply {@link FeatureConstructor.ANY_WINDOW |
* `ANY_WINDOW`}.
*
* ```js
* const newFeature = JScrewIt.Feature.commonOf("DOMWINDOW", "WINDOW");
* ```
*/
commonOf(...features: FeatureElementOrCompatibleArray[]): CustomFeature | null;
/**
* Returns a short description of a predefined feature in plain English.
*
* @param name
*
* A name or alias of a predefined feature.
*
* @remarks
*
* Different names or aliases of the same feature may have different descriptions.
*
* @throws
*
* An error is thrown if the specified argument is not a name or alias of a predefined feature.
*/
descriptionFor(name: keyof FeatureAll): string;
}
/**
* A feature object or a name or alias of a predefined feature.
*
* @remarks
*
* Methods that accept parameters of this type throw an error if the specified value is neither a
* feature object nor a name or alias of a predefined feature.
*/
export type FeatureElement = Feature | keyof FeatureAll;
/**
* A feature object, a name or alias of a predefined feature, or an array of such values that
* defines a union of mutually compatible features.
*
* @remarks
*
* Methods that accept parameters of this type throw an error if the specified value is neither a
* feature object nor a name or alias of a predefined feature, or if it is an array of values that
* does not define a union of mutually compatible features.
*/
export type FeatureElementOrCompatibleArray = FeatureElement | readonly FeatureElement[];
export interface PredefinedFeature extends Feature
{
readonly name: PredefinedFeatureName;
}