chore: update node_modules with new binary files and dependencies

- Add new binary files for nodemon, onnxruntime-web, and xenova/transformers
- Update various JavaScript and TypeScript files in node_modules
- Remove unused files and dependencies
- Add new test fixtures and documentation files
This commit is contained in:
2025-07-18 08:41:48 +08:00
parent 2f1dd687d0
commit c90f503821
4655 changed files with 811329 additions and 35112 deletions
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../nodemon/bin/nodemon.js
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../touch/bin/nodetouch.js
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../protobufjs/bin/pbjs
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../protobufjs/bin/pbts
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../prebuild-install/bin.js
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../rc/cli.js
Generated Vendored Symlink
+1
View File
@@ -0,0 +1 @@
../semver/bin/semver.js
+1133 -118
View File
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Inspect JS
Copyright (c) 2023 Hugging Face
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+79
View File
@@ -0,0 +1,79 @@
# Jinja
A minimalistic JavaScript implementation of the Jinja templating engine, specifically designed for parsing and rendering ML chat templates.
## Usage
### Load template from a model on the Hugging Face Hub
First, install the jinja and hub packages:
```sh
npm i @huggingface/jinja
npm i @huggingface/hub
```
You can then load a tokenizer from the Hugging Face Hub and render a list of chat messages, as follows:
```js
import { Template } from "@huggingface/jinja";
import { downloadFile } from "@huggingface/hub";
const config = await (
await downloadFile({
repo: "mistralai/Mistral-7B-Instruct-v0.1",
path: "tokenizer_config.json",
})
).json();
const chat = [
{ role: "user", content: "Hello, how are you?" },
{ role: "assistant", content: "I'm doing great. How can I help you today?" },
{ role: "user", content: "I'd like to show off how chat templating works!" },
];
const template = new Template(config.chat_template);
const result = template.render({
messages: chat,
bos_token: config.bos_token,
eos_token: config.eos_token,
});
// "<s>[INST] Hello, how are you? [/INST]I'm doing great. How can I help you today?</s> [INST] I'd like to show off how chat templating works! [/INST]"
```
### Transformers.js
First, install the `@huggingface/jinja` and `@xenova/transformers` packages:
```sh
npm i @huggingface/jinja
npm i @xenova/transformers
```
You can then render a list of chat messages using a tokenizer's `apply_chat_template` method.
```js
import { AutoTokenizer } from "@xenova/transformers";
// Load tokenizer from the Hugging Face Hub
const tokenizer = await AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1");
// Define chat messages
const chat = [
{ role: "user", content: "Hello, how are you?" },
{ role: "assistant", content: "I'm doing great. How can I help you today?" },
{ role: "user", content: "I'd like to show off how chat templating works!" },
];
const text = tokenizer.apply_chat_template(chat, { tokenize: false });
// "<s>[INST] Hello, how are you? [/INST]I'm doing great. How can I help you today?</s> [INST] I'd like to show off how chat templating works! [/INST]"
```
Notice how the entire chat is condensed into a single string. If you would instead like to return the tokenized version (i.e., a list of token IDs), you can use the following:
```js
const input_ids = tokenizer.apply_chat_template(chat, { tokenize: true, return_tensor: false });
// [1, 733, 16289, 28793, 22557, 28725, 910, 460, 368, 28804, 733, 28748, 16289, 28793, 28737, 28742, 28719, 2548, 1598, 28723, 1602, 541, 315, 1316, 368, 3154, 28804, 2, 28705, 733, 16289, 28793, 315, 28742, 28715, 737, 298, 1347, 805, 910, 10706, 5752, 1077, 3791, 28808, 733, 28748, 16289, 28793]
```
For more information about chat templates, check out the transformers [documentation](https://huggingface.co/docs/transformers/main/en/chat_templating).
+1603
View File
File diff suppressed because it is too large Load Diff
+269
View File
@@ -0,0 +1,269 @@
/**
* Represents tokens that our language understands in parsing.
*/
declare const TOKEN_TYPES: Readonly<{
Text: "Text";
NumericLiteral: "NumericLiteral";
BooleanLiteral: "BooleanLiteral";
StringLiteral: "StringLiteral";
Identifier: "Identifier";
Equals: "Equals";
OpenParen: "OpenParen";
CloseParen: "CloseParen";
OpenStatement: "OpenStatement";
CloseStatement: "CloseStatement";
OpenExpression: "OpenExpression";
CloseExpression: "CloseExpression";
OpenSquareBracket: "OpenSquareBracket";
CloseSquareBracket: "CloseSquareBracket";
OpenCurlyBracket: "OpenCurlyBracket";
CloseCurlyBracket: "CloseCurlyBracket";
Comma: "Comma";
Dot: "Dot";
Colon: "Colon";
Pipe: "Pipe";
CallOperator: "CallOperator";
AdditiveBinaryOperator: "AdditiveBinaryOperator";
MultiplicativeBinaryOperator: "MultiplicativeBinaryOperator";
ComparisonBinaryOperator: "ComparisonBinaryOperator";
UnaryOperator: "UnaryOperator";
Set: "Set";
If: "If";
For: "For";
In: "In";
Is: "Is";
NotIn: "NotIn";
Else: "Else";
EndIf: "EndIf";
ElseIf: "ElseIf";
EndFor: "EndFor";
And: "And";
Or: "Or";
Not: "UnaryOperator";
}>;
type TokenType = keyof typeof TOKEN_TYPES;
/**
* Represents a single token in the template.
*/
declare class Token {
value: string;
type: TokenType;
/**
* Constructs a new Token.
* @param {string} value The raw value as seen inside the source code.
* @param {TokenType} type The type of token.
*/
constructor(value: string, type: TokenType);
}
interface PreprocessOptions {
trim_blocks?: boolean;
lstrip_blocks?: boolean;
}
/**
* Generate a list of tokens from a source string.
*/
declare function tokenize(source: string, options?: PreprocessOptions): Token[];
/**
* Statements do not result in a value at runtime. They contain one or more expressions internally.
*/
declare class Statement {
type: string;
}
/**
* Defines a block which contains many statements. Each chat template corresponds to one Program.
*/
declare class Program extends Statement {
body: Statement[];
type: string;
constructor(body: Statement[]);
}
/**
* Generate the Abstract Syntax Tree (AST) from a list of tokens.
* Operator precedence can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table
*/
declare function parse(tokens: Token[]): Program;
type AnyRuntimeValue = NumericValue | StringValue | BooleanValue | ObjectValue | ArrayValue | FunctionValue | NullValue | UndefinedValue;
/**
* Abstract base class for all Runtime values.
* Should not be instantiated directly.
*/
declare abstract class RuntimeValue<T> {
type: string;
value: T;
/**
* A collection of built-in functions for this type.
*/
builtins: Map<string, AnyRuntimeValue>;
/**
* Creates a new RuntimeValue.
*/
constructor(value?: T);
/**
* Determines truthiness or falsiness of the runtime value.
* This function should be overridden by subclasses if it has custom truthiness criteria.
* @returns {BooleanValue} BooleanValue(true) if the value is truthy, BooleanValue(false) otherwise.
*/
__bool__(): BooleanValue;
}
/**
* Represents a numeric value at runtime.
*/
declare class NumericValue extends RuntimeValue<number> {
type: string;
}
/**
* Represents a string value at runtime.
*/
declare class StringValue extends RuntimeValue<string> {
type: string;
builtins: Map<string, AnyRuntimeValue>;
}
/**
* Represents a boolean value at runtime.
*/
declare class BooleanValue extends RuntimeValue<boolean> {
type: string;
}
/**
* Represents an Object value at runtime.
*/
declare class ObjectValue extends RuntimeValue<Map<string, AnyRuntimeValue>> {
type: string;
/**
* NOTE: necessary to override since all JavaScript arrays are considered truthy,
* while only non-empty Python arrays are consider truthy.
*
* e.g.,
* - JavaScript: {} && 5 -> 5
* - Python: {} and 5 -> {}
*/
__bool__(): BooleanValue;
builtins: Map<string, AnyRuntimeValue>;
}
/**
* Represents an Array value at runtime.
*/
declare class ArrayValue extends RuntimeValue<AnyRuntimeValue[]> {
type: string;
builtins: Map<string, AnyRuntimeValue>;
/**
* NOTE: necessary to override since all JavaScript arrays are considered truthy,
* while only non-empty Python arrays are consider truthy.
*
* e.g.,
* - JavaScript: [] && 5 -> 5
* - Python: [] and 5 -> []
*/
__bool__(): BooleanValue;
}
/**
* Represents a Function value at runtime.
*/
declare class FunctionValue extends RuntimeValue<(args: AnyRuntimeValue[], scope: Environment) => AnyRuntimeValue> {
type: string;
}
/**
* Represents a Null value at runtime.
*/
declare class NullValue extends RuntimeValue<null> {
type: string;
}
/**
* Represents an Undefined value at runtime.
*/
declare class UndefinedValue extends RuntimeValue<undefined> {
type: string;
}
/**
* Represents the current environment (scope) at runtime.
*/
declare class Environment {
parent?: Environment | undefined;
/**
* The variables declared in this environment.
*/
variables: Map<string, AnyRuntimeValue>;
/**
* The tests available in this environment.
*/
tests: Map<string, (...value: AnyRuntimeValue[]) => boolean>;
constructor(parent?: Environment | undefined);
/**
* Set the value of a variable in the current environment.
*/
set(name: string, value: unknown): AnyRuntimeValue;
private declareVariable;
/**
* Set variable in the current scope.
* See https://jinja.palletsprojects.com/en/3.0.x/templates/#assignments for more information.
*/
setVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue;
/**
* Resolve the environment in which the variable is declared.
* @param {string} name The name of the variable.
* @returns {Environment} The environment in which the variable is declared.
*/
private resolve;
lookupVariable(name: string): AnyRuntimeValue;
}
declare class Interpreter {
global: Environment;
constructor(env?: Environment);
/**
* Run the program.
*/
run(program: Program): AnyRuntimeValue;
/**
* Evaluates expressions following the binary operation type.
*/
private evaluateBinaryExpression;
/**
* Evaluates expressions following the filter operation type.
*/
private evaluateFilterExpression;
/**
* Evaluates expressions following the test operation type.
*/
private evaluateTestExpression;
/**
* Evaluates expressions following the unary operation type.
*/
private evaluateUnaryExpression;
private evalProgram;
private evaluateBlock;
private evaluateIdentifier;
private evaluateCallExpression;
private evaluateSliceExpression;
private evaluateMemberExpression;
private evaluateSet;
private evaluateIf;
private evaluateFor;
evaluate(statement: Statement | undefined, environment: Environment): AnyRuntimeValue;
}
/**
* @file Jinja templating engine
*
* A minimalistic JavaScript reimplementation of the [Jinja](https://github.com/pallets/jinja) templating engine,
* to support the chat templates. Special thanks to [Tyler Laceby](https://github.com/tlaceby) for his amazing
* ["Guide to Interpreters"](https://github.com/tlaceby/guide-to-interpreters-series) tutorial series,
* which provided the basis for this implementation.
*
* See the [Transformers documentation](https://huggingface.co/docs/transformers/main/en/chat_templating) for more information.
*
* @module index
*/
declare class Template {
parsed: Program;
/**
* @param {string} template The template string
*/
constructor(template: string);
render(items: Record<string, unknown>): string;
}
export { Environment, Interpreter, Template, parse, tokenize };
+1572
View File
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
{
"name": "@huggingface/jinja",
"packageManager": "pnpm@8.10.5",
"version": "0.2.2",
"description": "A minimalistic JavaScript implementation of the Jinja templating engine, specifically designed for parsing and rendering ML chat templates.",
"repository": "https://github.com/huggingface/huggingface.js.git",
"publishConfig": {
"access": "public"
},
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.cjs",
"import": "./dist/index.js"
}
},
"engines": {
"node": ">=18"
},
"source": "src/index.ts",
"files": [
"src",
"dist",
"README.md",
"tsconfig.json"
],
"keywords": [
"huggingface",
"jinja",
"templates",
"hugging",
"face"
],
"author": "Hugging Face",
"license": "MIT",
"devDependencies": {
"typescript": "^5.3.2",
"@xenova/transformers": "^2.9.0",
"@huggingface/hub": "^0.14.2"
},
"scripts": {
"lint": "eslint --quiet --fix --ext .cjs,.ts .",
"lint:check": "eslint --ext .cjs,.ts .",
"format": "prettier --write .",
"format:check": "prettier --check .",
"build": "tsup src/index.ts --format cjs,esm --clean --dts",
"test": "vitest run",
"test:browser": "vitest run --browser.name=chrome --browser.headless",
"check": "tsc"
}
}
+246
View File
@@ -0,0 +1,246 @@
import type { Token } from "./lexer";
/**
* Statements do not result in a value at runtime. They contain one or more expressions internally.
*/
export class Statement {
type = "Statement";
}
/**
* Defines a block which contains many statements. Each chat template corresponds to one Program.
*/
export class Program extends Statement {
override type = "Program";
constructor(public body: Statement[]) {
super();
}
}
export class If extends Statement {
override type = "If";
constructor(
public test: Expression,
public body: Statement[],
public alternate: Statement[]
) {
super();
}
}
export class For extends Statement {
override type = "For";
constructor(
public loopvar: Identifier | TupleLiteral,
public iterable: Expression,
public body: Statement[]
) {
super();
}
}
export class SetStatement extends Statement {
override type = "Set";
constructor(
public assignee: Expression,
public value: Expression
) {
super();
}
}
/**
* Expressions will result in a value at runtime (unlike statements).
*/
export class Expression extends Statement {
override type = "Expression";
}
export class MemberExpression extends Expression {
override type = "MemberExpression";
constructor(
public object: Expression,
public property: Expression,
public computed: boolean
) {
super();
}
}
export class CallExpression extends Expression {
override type = "CallExpression";
constructor(
public callee: Expression,
public args: Expression[]
) {
super();
}
}
/**
* Represents a user-defined variable or symbol in the template.
*/
export class Identifier extends Expression {
override type = "Identifier";
/**
* @param {string} value The name of the identifier
*/
constructor(public value: string) {
super();
}
}
/**
* Abstract base class for all Literal expressions.
* Should not be instantiated directly.
*/
abstract class Literal<T> extends Expression {
override type = "Literal";
constructor(public value: T) {
super();
}
}
/**
* Represents a numeric constant in the template.
*/
export class NumericLiteral extends Literal<number> {
override type = "NumericLiteral";
}
/**
* Represents a text constant in the template.
*/
export class StringLiteral extends Literal<string> {
override type = "StringLiteral";
}
/**
* Represents a boolean constant in the template.
*/
export class BooleanLiteral extends Literal<boolean> {
override type = "BooleanLiteral";
}
/**
* Represents an array literal in the template.
*/
export class ArrayLiteral extends Literal<Expression[]> {
override type = "ArrayLiteral";
}
/**
* Represents a tuple literal in the template.
*/
export class TupleLiteral extends Literal<Expression[]> {
override type = "TupleLiteral";
}
/**
* Represents an object literal in the template.
*/
export class ObjectLiteral extends Literal<Map<Expression, Expression>> {
override type = "ObjectLiteral";
}
/**
* An operation with two sides, separated by an operator.
* Note: Either side can be a Complex Expression, with order
* of operations being determined by the operator.
*/
export class BinaryExpression extends Expression {
override type = "BinaryExpression";
constructor(
public operator: Token,
public left: Expression,
public right: Expression
) {
super();
}
}
/**
* An operation with two sides, separated by the | operator.
* Operator precedence: https://github.com/pallets/jinja/issues/379#issuecomment-168076202
*/
export class FilterExpression extends Expression {
override type = "FilterExpression";
constructor(
public operand: Expression,
public filter: Identifier | CallExpression
) {
super();
}
}
/**
* An operation with two sides, separated by the "is" operator.
*/
export class TestExpression extends Expression {
override type = "TestExpression";
constructor(
public operand: Expression,
public negate: boolean,
public test: Identifier // TODO: Add support for non-identifier tests
) {
super();
}
}
/**
* An operation with one side (operator on the left).
*/
export class UnaryExpression extends Expression {
override type = "UnaryExpression";
constructor(
public operator: Token,
public argument: Expression
) {
super();
}
}
/**
* Logical negation of an expression.
*/
export class LogicalNegationExpression extends Expression {
override type = "LogicalNegationExpression";
constructor(public argument: Expression) {
super();
}
}
export class SliceExpression extends Expression {
override type = "SliceExpression";
constructor(
public start: Expression | undefined = undefined,
public stop: Expression | undefined = undefined,
public step: Expression | undefined = undefined
) {
super();
}
}
export class KeywordArgumentExpression extends Expression {
override type = "KeywordArgumentExpression";
constructor(
public key: Identifier,
public value: Expression
) {
super();
}
}
+58
View File
@@ -0,0 +1,58 @@
/**
* @file Jinja templating engine
*
* A minimalistic JavaScript reimplementation of the [Jinja](https://github.com/pallets/jinja) templating engine,
* to support the chat templates. Special thanks to [Tyler Laceby](https://github.com/tlaceby) for his amazing
* ["Guide to Interpreters"](https://github.com/tlaceby/guide-to-interpreters-series) tutorial series,
* which provided the basis for this implementation.
*
* See the [Transformers documentation](https://huggingface.co/docs/transformers/main/en/chat_templating) for more information.
*
* @module index
*/
import { tokenize } from "./lexer";
import { parse } from "./parser";
import { Environment, Interpreter } from "./runtime";
import type { Program } from "./ast";
import type { StringValue } from "./runtime";
import { range } from "./utils";
export class Template {
parsed: Program;
/**
* @param {string} template The template string
*/
constructor(template: string) {
const tokens = tokenize(template, {
lstrip_blocks: true,
trim_blocks: true,
});
this.parsed = parse(tokens);
}
render(items: Record<string, unknown>): string {
// Create a new environment for this template
const env = new Environment();
// Declare global variables
env.set("false", false);
env.set("true", true);
env.set("raise_exception", (args: string) => {
throw new Error(args);
});
env.set("range", range);
// Add user-defined variables
for (const [key, value] of Object.entries(items)) {
env.set(key, value);
}
const interpreter = new Interpreter(env);
const result = interpreter.run(this.parsed) as StringValue;
return result.value;
}
}
export { Environment, Interpreter, tokenize, parse };
+332
View File
@@ -0,0 +1,332 @@
/**
* Represents tokens that our language understands in parsing.
*/
export const TOKEN_TYPES = Object.freeze({
Text: "Text", // The text between Jinja statements or expressions
NumericLiteral: "NumericLiteral", // e.g., 123
BooleanLiteral: "BooleanLiteral", // true or false
StringLiteral: "StringLiteral", // 'string'
Identifier: "Identifier", // Variables, functions, etc.
Equals: "Equals", // =
OpenParen: "OpenParen", // (
CloseParen: "CloseParen", // )
OpenStatement: "OpenStatement", // {%
CloseStatement: "CloseStatement", // %}
OpenExpression: "OpenExpression", // {{
CloseExpression: "CloseExpression", // }}
OpenSquareBracket: "OpenSquareBracket", // [
CloseSquareBracket: "CloseSquareBracket", // ]
OpenCurlyBracket: "OpenCurlyBracket", // {
CloseCurlyBracket: "CloseCurlyBracket", // }
Comma: "Comma", // ,
Dot: "Dot", // .
Colon: "Colon", // :
Pipe: "Pipe", // |
CallOperator: "CallOperator", // ()
AdditiveBinaryOperator: "AdditiveBinaryOperator", // + -
MultiplicativeBinaryOperator: "MultiplicativeBinaryOperator", // * / %
ComparisonBinaryOperator: "ComparisonBinaryOperator", // < > <= >= == !=
UnaryOperator: "UnaryOperator", // ! - +
// Keywords
Set: "Set",
If: "If",
For: "For",
In: "In",
Is: "Is",
NotIn: "NotIn",
Else: "Else",
EndIf: "EndIf",
ElseIf: "ElseIf",
EndFor: "EndFor",
And: "And",
Or: "Or",
Not: "UnaryOperator",
});
export type TokenType = keyof typeof TOKEN_TYPES;
/**
* Constant lookup for keywords and known identifiers + symbols.
*/
const KEYWORDS = Object.freeze({
set: TOKEN_TYPES.Set,
for: TOKEN_TYPES.For,
in: TOKEN_TYPES.In,
is: TOKEN_TYPES.Is,
if: TOKEN_TYPES.If,
else: TOKEN_TYPES.Else,
endif: TOKEN_TYPES.EndIf,
elif: TOKEN_TYPES.ElseIf,
endfor: TOKEN_TYPES.EndFor,
and: TOKEN_TYPES.And,
or: TOKEN_TYPES.Or,
not: TOKEN_TYPES.Not,
"not in": TOKEN_TYPES.NotIn,
// Literals
true: TOKEN_TYPES.BooleanLiteral,
false: TOKEN_TYPES.BooleanLiteral,
});
/**
* Represents a single token in the template.
*/
export class Token {
/**
* Constructs a new Token.
* @param {string} value The raw value as seen inside the source code.
* @param {TokenType} type The type of token.
*/
constructor(
public value: string,
public type: TokenType
) {}
}
function isWord(char: string): boolean {
return /\w/.test(char);
}
function isInteger(char: string): boolean {
return /[0-9]/.test(char);
}
/**
* A data structure which contains a list of rules to test
*/
const ORDERED_MAPPING_TABLE: [string, TokenType][] = [
// Control sequences
["{%", TOKEN_TYPES.OpenStatement],
["%}", TOKEN_TYPES.CloseStatement],
["{{", TOKEN_TYPES.OpenExpression],
["}}", TOKEN_TYPES.CloseExpression],
// Single character tokens
["(", TOKEN_TYPES.OpenParen],
[")", TOKEN_TYPES.CloseParen],
["{", TOKEN_TYPES.OpenCurlyBracket],
["}", TOKEN_TYPES.CloseCurlyBracket],
["[", TOKEN_TYPES.OpenSquareBracket],
["]", TOKEN_TYPES.CloseSquareBracket],
[",", TOKEN_TYPES.Comma],
[".", TOKEN_TYPES.Dot],
[":", TOKEN_TYPES.Colon],
["|", TOKEN_TYPES.Pipe],
// Comparison operators
["<=", TOKEN_TYPES.ComparisonBinaryOperator],
[">=", TOKEN_TYPES.ComparisonBinaryOperator],
["==", TOKEN_TYPES.ComparisonBinaryOperator],
["!=", TOKEN_TYPES.ComparisonBinaryOperator],
["<", TOKEN_TYPES.ComparisonBinaryOperator],
[">", TOKEN_TYPES.ComparisonBinaryOperator],
// Arithmetic operators
["+", TOKEN_TYPES.AdditiveBinaryOperator],
["-", TOKEN_TYPES.AdditiveBinaryOperator],
["*", TOKEN_TYPES.MultiplicativeBinaryOperator],
["/", TOKEN_TYPES.MultiplicativeBinaryOperator],
["%", TOKEN_TYPES.MultiplicativeBinaryOperator],
// Assignment operator
["=", TOKEN_TYPES.Equals],
];
const ESCAPE_CHARACTERS = new Map([
["n", "\n"], // New line
["t", "\t"], // Horizontal tab
["r", "\r"], // Carriage return
["b", "\b"], // Backspace
["f", "\f"], // Form feed
["v", "\v"], // Vertical tab
["'", "'"], // Single quote
['"', '"'], // Double quote
["\\", "\\"], // Backslash
]);
export interface PreprocessOptions {
trim_blocks?: boolean;
lstrip_blocks?: boolean;
}
function preprocess(template: string, options: PreprocessOptions = {}): string {
// According to https://jinja.palletsprojects.com/en/3.0.x/templates/#whitespace-control
// In the default configuration:
// - a single trailing newline is stripped if present
// - other whitespace (spaces, tabs, newlines etc.) is returned unchanged
if (template.endsWith("\n")) {
template = template.slice(0, -1);
}
// Replace all comments with a placeholder
// This ensures that comments don't interfere with the following options
template = template.replace(/{#.*?#}/gs, "{##}");
if (options.lstrip_blocks) {
// The lstrip_blocks option can also be set to strip tabs and spaces from the
// beginning of a line to the start of a block. (Nothing will be stripped if
// there are other characters before the start of the block.)
template = template.replace(/^[ \t]*({[#%])/gm, "$1");
}
if (options.trim_blocks) {
// If an application configures Jinja to trim_blocks, the first newline after
// a template tag is removed automatically (like in PHP).
template = template.replace(/([#%]})\n/g, "$1");
}
return template
.replace(/{##}/g, "") // Remove comments
.replace(/-%}\s*/g, "%}")
.replace(/\s*{%-/g, "{%")
.replace(/-}}\s*/g, "}}")
.replace(/\s*{{-/g, "{{");
}
/**
* Generate a list of tokens from a source string.
*/
export function tokenize(source: string, options: PreprocessOptions = {}): Token[] {
const tokens: Token[] = [];
const src: string = preprocess(source, options);
let cursorPosition = 0;
const consumeWhile = (predicate: (char: string) => boolean): string => {
let str = "";
while (predicate(src[cursorPosition])) {
// Check for escaped characters
if (src[cursorPosition] === "\\") {
// Consume the backslash
++cursorPosition;
// Check for end of input
if (cursorPosition >= src.length) throw new SyntaxError("Unexpected end of input");
// Add the escaped character
const escaped = src[cursorPosition++];
const unescaped = ESCAPE_CHARACTERS.get(escaped);
if (unescaped === undefined) {
throw new SyntaxError(`Unexpected escaped character: ${escaped}`);
}
str += unescaped;
continue;
}
str += src[cursorPosition++];
if (cursorPosition >= src.length) throw new SyntaxError("Unexpected end of input");
}
return str;
};
// Build each token until end of input
main: while (cursorPosition < src.length) {
// First, consume all text that is outside of a Jinja statement or expression
const lastTokenType = tokens.at(-1)?.type;
if (
lastTokenType === undefined ||
lastTokenType === TOKEN_TYPES.CloseStatement ||
lastTokenType === TOKEN_TYPES.CloseExpression
) {
let text = "";
while (
cursorPosition < src.length &&
// Keep going until we hit the next Jinja statement or expression
!(src[cursorPosition] === "{" && (src[cursorPosition + 1] === "%" || src[cursorPosition + 1] === "{"))
) {
// Consume text
text += src[cursorPosition++];
}
// There is some text to add
if (text.length > 0) {
tokens.push(new Token(text, TOKEN_TYPES.Text));
continue;
}
}
// Consume (and ignore) all whitespace inside Jinja statements or expressions
consumeWhile((char) => /\s/.test(char));
// Handle multi-character tokens
const char = src[cursorPosition];
// Check for unary operators
if (char === "-" || char === "+") {
const lastTokenType = tokens.at(-1)?.type;
if (lastTokenType === TOKEN_TYPES.Text || lastTokenType === undefined) {
throw new SyntaxError(`Unexpected character: ${char}`);
}
switch (lastTokenType) {
case TOKEN_TYPES.Identifier:
case TOKEN_TYPES.NumericLiteral:
case TOKEN_TYPES.BooleanLiteral:
case TOKEN_TYPES.StringLiteral:
case TOKEN_TYPES.CloseParen:
case TOKEN_TYPES.CloseSquareBracket:
// Part of a binary operator
// a - 1, 1 - 1, true - 1, "apple" - 1, (1) - 1, a[1] - 1
// Continue parsing normally
break;
default: {
// Is part of a unary operator
// (-1), [-1], (1 + -1), not -1, -apple
++cursorPosition; // consume the unary operator
// Check for numbers following the unary operator
const num = consumeWhile(isInteger);
tokens.push(
new Token(`${char}${num}`, num.length > 0 ? TOKEN_TYPES.NumericLiteral : TOKEN_TYPES.UnaryOperator)
);
continue;
}
}
}
// Try to match one of the tokens in the mapping table
for (const [char, token] of ORDERED_MAPPING_TABLE) {
const slice = src.slice(cursorPosition, cursorPosition + char.length);
if (slice === char) {
tokens.push(new Token(char, token));
cursorPosition += char.length;
continue main;
}
}
if (char === "'" || char === '"') {
++cursorPosition; // Skip the opening quote
const str = consumeWhile((c) => c !== char);
tokens.push(new Token(str, TOKEN_TYPES.StringLiteral));
++cursorPosition; // Skip the closing quote
continue;
}
if (isInteger(char)) {
const num = consumeWhile(isInteger);
tokens.push(new Token(num, TOKEN_TYPES.NumericLiteral));
continue;
}
if (isWord(char)) {
const word = consumeWhile(isWord);
// Check for special/reserved keywords
// NOTE: We use Object.hasOwn() to avoid matching `.toString()` and other Object methods
const type = Object.hasOwn(KEYWORDS, word) ? KEYWORDS[word as keyof typeof KEYWORDS] : TOKEN_TYPES.Identifier;
// Special case of not in:
// If the previous token was a "not", and this token is "in"
// then we want to combine them into a single token
if (type === TOKEN_TYPES.In && tokens.at(-1)?.type === TOKEN_TYPES.Not) {
tokens.pop();
tokens.push(new Token("not in", TOKEN_TYPES.NotIn));
} else {
tokens.push(new Token(word, type));
}
continue;
}
throw new SyntaxError(`Unexpected character: ${char}`);
}
return tokens;
}
+536
View File
@@ -0,0 +1,536 @@
import type { Token, TokenType } from "./lexer";
import { TOKEN_TYPES } from "./lexer";
import type { Statement } from "./ast";
import {
Program,
If,
For,
SetStatement,
MemberExpression,
CallExpression,
Identifier,
NumericLiteral,
StringLiteral,
BooleanLiteral,
ArrayLiteral,
ObjectLiteral,
BinaryExpression,
FilterExpression,
TestExpression,
UnaryExpression,
SliceExpression,
KeywordArgumentExpression,
TupleLiteral,
} from "./ast";
/**
* Generate the Abstract Syntax Tree (AST) from a list of tokens.
* Operator precedence can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence#table
*/
export function parse(tokens: Token[]): Program {
const program = new Program([]);
let current = 0;
/**
* Consume the next token if it matches the expected type, otherwise throw an error.
* @param type The expected token type
* @param error The error message to throw if the token does not match the expected type
* @returns The consumed token
*/
function expect(type: string, error: string): Token {
const prev = tokens[current++];
if (!prev || prev.type !== type) {
throw new Error(`Parser Error: ${error}. ${prev.type} !== ${type}.`);
}
return prev;
}
function parseAny(): Statement {
switch (tokens[current].type) {
case TOKEN_TYPES.Text:
return parseText();
case TOKEN_TYPES.OpenStatement:
return parseJinjaStatement();
case TOKEN_TYPES.OpenExpression:
return parseJinjaExpression();
default:
throw new SyntaxError(`Unexpected token type: ${tokens[current].type}`);
}
}
function not(...types: TokenType[]): boolean {
return current + types.length <= tokens.length && types.some((type, i) => type !== tokens[current + i].type);
}
function is(...types: TokenType[]): boolean {
return current + types.length <= tokens.length && types.every((type, i) => type === tokens[current + i].type);
}
function parseText(): StringLiteral {
return new StringLiteral(expect(TOKEN_TYPES.Text, "Expected text token").value);
}
function parseJinjaStatement(): Statement {
// Consume {% %} tokens
expect(TOKEN_TYPES.OpenStatement, "Expected opening statement token");
let result;
switch (tokens[current].type) {
case TOKEN_TYPES.Set:
++current;
result = parseSetStatement();
expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
break;
case TOKEN_TYPES.If:
++current;
result = parseIfStatement();
expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
expect(TOKEN_TYPES.EndIf, "Expected endif token");
expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
break;
case TOKEN_TYPES.For:
++current;
result = parseForStatement();
expect(TOKEN_TYPES.OpenStatement, "Expected {% token");
expect(TOKEN_TYPES.EndFor, "Expected endfor token");
expect(TOKEN_TYPES.CloseStatement, "Expected %} token");
break;
default:
throw new SyntaxError(`Unknown statement type: ${tokens[current].type}`);
}
return result;
}
function parseJinjaExpression(): Statement {
// Consume {{ }} tokens
expect(TOKEN_TYPES.OpenExpression, "Expected opening expression token");
const result = parseExpression();
expect(TOKEN_TYPES.CloseExpression, "Expected closing expression token");
return result;
}
// NOTE: `set` acts as both declaration statement and assignment expression
function parseSetStatement(): Statement {
const left = parseExpression();
if (is(TOKEN_TYPES.Equals)) {
++current;
const value = parseSetStatement();
return new SetStatement(left, value);
}
return left;
}
function parseIfStatement(): If {
const test = parseExpression();
expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
const body: Statement[] = [];
const alternate: Statement[] = [];
// Keep parsing if body until we reach the first {% elif %} or {% else %} or {% endif %}
while (
!(
tokens[current]?.type === TOKEN_TYPES.OpenStatement &&
(tokens[current + 1]?.type === TOKEN_TYPES.ElseIf ||
tokens[current + 1]?.type === TOKEN_TYPES.Else ||
tokens[current + 1]?.type === TOKEN_TYPES.EndIf)
)
) {
body.push(parseAny());
}
// Alternate branch: Check for {% elif %} or {% else %}
if (
tokens[current]?.type === TOKEN_TYPES.OpenStatement &&
tokens[current + 1]?.type !== TOKEN_TYPES.EndIf // There is some body
) {
++current; // eat {% token
if (is(TOKEN_TYPES.ElseIf)) {
expect(TOKEN_TYPES.ElseIf, "Expected elseif token");
alternate.push(parseIfStatement());
} else {
// tokens[current]?.type === TokenType.Else
expect(TOKEN_TYPES.Else, "Expected else token");
expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
// keep going until we hit {% endif %}
while (
!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type === TOKEN_TYPES.EndIf)
) {
alternate.push(parseAny());
}
}
}
return new If(test, body, alternate);
}
function parseExpressionSequence(primary = false): Statement {
const fn = primary ? parsePrimaryExpression : parseExpression;
const expressions = [fn()];
const isTuple = is(TOKEN_TYPES.Comma);
while (isTuple) {
++current; // consume comma
expressions.push(fn());
if (!is(TOKEN_TYPES.Comma)) {
break;
}
}
return isTuple ? new TupleLiteral(expressions) : expressions[0];
}
function parseForStatement(): For {
// e.g., `message` in `for message in messages`
const loopVariable = parseExpressionSequence(true); // should be an identifier
if (!(loopVariable instanceof Identifier || loopVariable instanceof TupleLiteral)) {
throw new SyntaxError(`Expected identifier/tuple for the loop variable, got ${loopVariable.type} instead`);
}
expect(TOKEN_TYPES.In, "Expected `in` keyword following loop variable");
// `messages` in `for message in messages`
const iterable = parseExpression();
expect(TOKEN_TYPES.CloseStatement, "Expected closing statement token");
// Body of for loop
const body: Statement[] = [];
// Keep going until we hit {% endfor
while (not(TOKEN_TYPES.OpenStatement, TOKEN_TYPES.EndFor)) {
body.push(parseAny());
}
return new For(loopVariable, iterable, body);
}
function parseExpression(): Statement {
// Choose parse function with lowest precedence
return parseTernaryExpression();
}
function parseTernaryExpression(): Statement {
const a = parseLogicalOrExpression();
if (is(TOKEN_TYPES.If)) {
// Ternary expression
++current; // consume if
const predicate = parseLogicalOrExpression();
expect(TOKEN_TYPES.Else, "Expected else token");
const b = parseLogicalOrExpression();
return new If(predicate, [a], [b]);
}
return a;
}
function parseLogicalOrExpression(): Statement {
let left = parseLogicalAndExpression();
while (is(TOKEN_TYPES.Or)) {
const operator = tokens[current];
++current;
const right = parseLogicalAndExpression();
left = new BinaryExpression(operator, left, right);
}
return left;
}
function parseLogicalAndExpression(): Statement {
let left = parseLogicalNegationExpression();
while (is(TOKEN_TYPES.And)) {
const operator = tokens[current];
++current;
const right = parseLogicalNegationExpression();
left = new BinaryExpression(operator, left, right);
}
return left;
}
function parseLogicalNegationExpression(): Statement {
let right: UnaryExpression | undefined;
// Try parse unary operators
while (is(TOKEN_TYPES.Not)) {
// not not ...
const operator = tokens[current];
++current;
const arg = parseLogicalNegationExpression(); // not test.x === not (test.x)
right = new UnaryExpression(operator, arg);
}
return right ?? parseComparisonExpression();
}
function parseComparisonExpression(): Statement {
// NOTE: membership has same precedence as comparison
// e.g., ('a' in 'apple' == 'b' in 'banana') evaluates as ('a' in ('apple' == ('b' in 'banana')))
let left = parseAdditiveExpression();
while (is(TOKEN_TYPES.ComparisonBinaryOperator) || is(TOKEN_TYPES.In) || is(TOKEN_TYPES.NotIn)) {
const operator = tokens[current];
++current;
const right = parseAdditiveExpression();
left = new BinaryExpression(operator, left, right);
}
return left;
}
function parseAdditiveExpression(): Statement {
let left = parseMultiplicativeExpression();
while (is(TOKEN_TYPES.AdditiveBinaryOperator)) {
const operator = tokens[current];
++current;
const right = parseMultiplicativeExpression();
left = new BinaryExpression(operator, left, right);
}
return left;
}
function parseCallMemberExpression(): Statement {
// Handle member expressions recursively
const member = parseMemberExpression(); // foo.x
if (is(TOKEN_TYPES.OpenParen)) {
// foo.x()
return parseCallExpression(member);
}
return member;
}
function parseCallExpression(callee: Statement): CallExpression {
let callExpression = new CallExpression(callee, parseArgs());
if (is(TOKEN_TYPES.OpenParen)) {
// foo.x()()
callExpression = parseCallExpression(callExpression);
}
return callExpression;
}
function parseArgs(): Statement[] {
// add (x + 5, foo())
expect(TOKEN_TYPES.OpenParen, "Expected opening parenthesis for arguments list");
const args = parseArgumentsList();
expect(TOKEN_TYPES.CloseParen, "Expected closing parenthesis for arguments list");
return args;
}
function parseArgumentsList(): Statement[] {
// comma-separated arguments list
const args = [];
while (!is(TOKEN_TYPES.CloseParen)) {
let argument = parseExpression();
if (is(TOKEN_TYPES.Equals)) {
// keyword argument
// e.g., func(x = 5, y = a or b)
++current; // consume equals
if (!(argument instanceof Identifier)) {
throw new SyntaxError(`Expected identifier for keyword argument`);
}
const value = parseExpression();
argument = new KeywordArgumentExpression(argument, value);
}
args.push(argument);
if (is(TOKEN_TYPES.Comma)) {
++current; // consume comma
}
}
return args;
}
function parseMemberExpressionArgumentsList(): Statement {
// NOTE: This also handles slice expressions colon-separated arguments list
// e.g., ['test'], [0], [:2], [1:], [1:2], [1:2:3]
const slices: (Statement | undefined)[] = [];
let isSlice = false;
while (!is(TOKEN_TYPES.CloseSquareBracket)) {
if (is(TOKEN_TYPES.Colon)) {
// A case where a default is used
// e.g., [:2] will be parsed as [undefined, 2]
slices.push(undefined);
++current; // consume colon
isSlice = true;
} else {
slices.push(parseExpression());
if (is(TOKEN_TYPES.Colon)) {
++current; // consume colon after expression, if it exists
isSlice = true;
}
}
}
if (slices.length === 0) {
// []
throw new SyntaxError(`Expected at least one argument for member/slice expression`);
}
if (isSlice) {
if (slices.length > 3) {
throw new SyntaxError(`Expected 0-3 arguments for slice expression`);
}
return new SliceExpression(...slices);
}
return slices[0] as Statement; // normal member expression
}
function parseMemberExpression(): Statement {
let object = parsePrimaryExpression();
while (is(TOKEN_TYPES.Dot) || is(TOKEN_TYPES.OpenSquareBracket)) {
const operator = tokens[current]; // . or [
++current;
let property: Statement;
const computed = operator.type !== TOKEN_TYPES.Dot;
if (computed) {
// computed (i.e., bracket notation: obj[expr])
property = parseMemberExpressionArgumentsList();
expect(TOKEN_TYPES.CloseSquareBracket, "Expected closing square bracket");
} else {
// non-computed (i.e., dot notation: obj.expr)
property = parsePrimaryExpression(); // should be an identifier
if (property.type !== "Identifier") {
throw new SyntaxError(`Expected identifier following dot operator`);
}
}
object = new MemberExpression(object, property, computed);
}
return object;
}
function parseMultiplicativeExpression(): Statement {
let left = parseTestExpression();
// Multiplicative operators have higher precedence than test expressions
// e.g., (4 * 4 is divisibleby(2)) evaluates as (4 * (4 is divisibleby(2)))
while (is(TOKEN_TYPES.MultiplicativeBinaryOperator)) {
const operator = tokens[current];
++current;
const right = parseTestExpression();
left = new BinaryExpression(operator, left, right);
}
return left;
}
function parseTestExpression(): Statement {
let operand = parseFilterExpression();
while (is(TOKEN_TYPES.Is)) {
// Support chaining tests
++current; // consume is
const negate = is(TOKEN_TYPES.Not);
if (negate) {
++current; // consume not
}
let filter = parsePrimaryExpression();
if (filter instanceof BooleanLiteral) {
// Special case: treat boolean literals as identifiers
filter = new Identifier(filter.value.toString());
}
if (!(filter instanceof Identifier)) {
throw new SyntaxError(`Expected identifier for the test`);
}
// TODO: Add support for non-identifier tests
operand = new TestExpression(operand, negate, filter);
}
return operand;
}
function parseFilterExpression(): Statement {
let operand = parseCallMemberExpression();
while (is(TOKEN_TYPES.Pipe)) {
// Support chaining filters
++current; // consume pipe
let filter = parsePrimaryExpression(); // should be an identifier
if (!(filter instanceof Identifier)) {
throw new SyntaxError(`Expected identifier for the filter`);
}
if (is(TOKEN_TYPES.OpenParen)) {
filter = parseCallExpression(filter);
}
operand = new FilterExpression(operand, filter as Identifier | CallExpression);
}
return operand;
}
function parsePrimaryExpression(): Statement {
// Primary expression: number, string, identifier, function call, parenthesized expression
const token = tokens[current];
switch (token.type) {
case TOKEN_TYPES.NumericLiteral:
++current;
return new NumericLiteral(Number(token.value));
case TOKEN_TYPES.StringLiteral:
++current;
return new StringLiteral(token.value);
case TOKEN_TYPES.BooleanLiteral:
++current;
return new BooleanLiteral(token.value === "true");
case TOKEN_TYPES.Identifier:
++current;
return new Identifier(token.value);
case TOKEN_TYPES.OpenParen: {
++current; // consume opening parenthesis
const expression = parseExpressionSequence();
if (tokens[current].type !== TOKEN_TYPES.CloseParen) {
throw new SyntaxError(`Expected closing parenthesis, got ${tokens[current].type} instead`);
}
++current; // consume closing parenthesis
return expression;
}
case TOKEN_TYPES.OpenSquareBracket: {
++current; // consume opening square bracket
const values = [];
while (!is(TOKEN_TYPES.CloseSquareBracket)) {
values.push(parseExpression());
if (is(TOKEN_TYPES.Comma)) {
++current; // consume comma
}
}
++current; // consume closing square bracket
return new ArrayLiteral(values);
}
case TOKEN_TYPES.OpenCurlyBracket: {
++current; // consume opening curly bracket
const values = new Map();
while (!is(TOKEN_TYPES.CloseCurlyBracket)) {
const key = parseExpression();
expect(TOKEN_TYPES.Colon, "Expected colon between key and value in object literal");
const value = parseExpression();
values.set(key, value);
if (is(TOKEN_TYPES.Comma)) {
++current; // consume comma
}
}
++current; // consume closing curly bracket
return new ObjectLiteral(values);
}
default:
throw new SyntaxError(`Unexpected token: ${token.type}`);
}
}
while (current < tokens.length) {
program.body.push(parseAny());
}
return program;
}
+918
View File
@@ -0,0 +1,918 @@
import type {
NumericLiteral,
StringLiteral,
BooleanLiteral,
ArrayLiteral,
Statement,
Program,
If,
For,
SetStatement,
MemberExpression,
CallExpression,
Identifier,
BinaryExpression,
FilterExpression,
TestExpression,
UnaryExpression,
SliceExpression,
KeywordArgumentExpression,
ObjectLiteral,
TupleLiteral,
} from "./ast";
import { slice, titleCase } from "./utils";
export type AnyRuntimeValue =
| NumericValue
| StringValue
| BooleanValue
| ObjectValue
| ArrayValue
| FunctionValue
| NullValue
| UndefinedValue;
/**
* Abstract base class for all Runtime values.
* Should not be instantiated directly.
*/
abstract class RuntimeValue<T> {
type = "RuntimeValue";
value: T;
/**
* A collection of built-in functions for this type.
*/
builtins = new Map<string, AnyRuntimeValue>();
/**
* Creates a new RuntimeValue.
*/
constructor(value: T = undefined as unknown as T) {
this.value = value;
}
/**
* Determines truthiness or falsiness of the runtime value.
* This function should be overridden by subclasses if it has custom truthiness criteria.
* @returns {BooleanValue} BooleanValue(true) if the value is truthy, BooleanValue(false) otherwise.
*/
__bool__(): BooleanValue {
return new BooleanValue(!!this.value);
}
}
/**
* Represents a numeric value at runtime.
*/
export class NumericValue extends RuntimeValue<number> {
override type = "NumericValue";
}
/**
* Represents a string value at runtime.
*/
export class StringValue extends RuntimeValue<string> {
override type = "StringValue";
override builtins = new Map<string, AnyRuntimeValue>([
[
"upper",
new FunctionValue(() => {
return new StringValue(this.value.toUpperCase());
}),
],
[
"lower",
new FunctionValue(() => {
return new StringValue(this.value.toLowerCase());
}),
],
[
"strip",
new FunctionValue(() => {
return new StringValue(this.value.trim());
}),
],
[
"title",
new FunctionValue(() => {
return new StringValue(titleCase(this.value));
}),
],
["length", new NumericValue(this.value.length)],
]);
}
/**
* Represents a boolean value at runtime.
*/
export class BooleanValue extends RuntimeValue<boolean> {
override type = "BooleanValue";
}
/**
* Represents an Object value at runtime.
*/
export class ObjectValue extends RuntimeValue<Map<string, AnyRuntimeValue>> {
override type = "ObjectValue";
/**
* NOTE: necessary to override since all JavaScript arrays are considered truthy,
* while only non-empty Python arrays are consider truthy.
*
* e.g.,
* - JavaScript: {} && 5 -> 5
* - Python: {} and 5 -> {}
*/
override __bool__(): BooleanValue {
return new BooleanValue(this.value.size > 0);
}
override builtins: Map<string, AnyRuntimeValue> = new Map<string, AnyRuntimeValue>([
[
"get",
new FunctionValue(([key, defaultValue]) => {
if (!(key instanceof StringValue)) {
throw new Error(`Object key must be a string: got ${key.type}`);
}
return this.value.get(key.value) ?? defaultValue ?? new NullValue();
}),
],
[
"items",
new FunctionValue(() => {
return new ArrayValue(
Array.from(this.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))
);
}),
],
]);
}
/**
* Represents an Array value at runtime.
*/
export class ArrayValue extends RuntimeValue<AnyRuntimeValue[]> {
override type = "ArrayValue";
override builtins = new Map<string, AnyRuntimeValue>([["length", new NumericValue(this.value.length)]]);
/**
* NOTE: necessary to override since all JavaScript arrays are considered truthy,
* while only non-empty Python arrays are consider truthy.
*
* e.g.,
* - JavaScript: [] && 5 -> 5
* - Python: [] and 5 -> []
*/
override __bool__(): BooleanValue {
return new BooleanValue(this.value.length > 0);
}
}
/**
* Represents a Tuple value at runtime.
* NOTE: We extend ArrayValue since JavaScript does not have a built-in Tuple type.
*/
export class TupleValue extends ArrayValue {
override type = "TupleValue";
}
/**
* Represents a Function value at runtime.
*/
export class FunctionValue extends RuntimeValue<(args: AnyRuntimeValue[], scope: Environment) => AnyRuntimeValue> {
override type = "FunctionValue";
}
/**
* Represents a Null value at runtime.
*/
export class NullValue extends RuntimeValue<null> {
override type = "NullValue";
}
/**
* Represents an Undefined value at runtime.
*/
export class UndefinedValue extends RuntimeValue<undefined> {
override type = "UndefinedValue";
}
/**
* Represents the current environment (scope) at runtime.
*/
export class Environment {
/**
* The variables declared in this environment.
*/
variables: Map<string, AnyRuntimeValue> = new Map([
[
"namespace",
new FunctionValue((args) => {
if (args.length === 0) {
return new ObjectValue(new Map());
}
if (args.length !== 1 || !(args[0] instanceof ObjectValue)) {
throw new Error("`namespace` expects either zero arguments or a single object argument");
}
return args[0];
}),
],
]);
/**
* The tests available in this environment.
*/
tests: Map<string, (...value: AnyRuntimeValue[]) => boolean> = new Map([
["boolean", (operand) => operand.type === "BooleanValue"],
["callable", (operand) => operand instanceof FunctionValue],
[
"odd",
(operand) => {
if (operand.type !== "NumericValue") {
throw new Error(`Cannot apply test "odd" to type: ${operand.type}`);
}
return (operand as NumericValue).value % 2 !== 0;
},
],
[
"even",
(operand) => {
if (operand.type !== "NumericValue") {
throw new Error(`Cannot apply test "even" to type: ${operand.type}`);
}
return (operand as NumericValue).value % 2 === 0;
},
],
["false", (operand) => operand.type === "BooleanValue" && !(operand as BooleanValue).value],
["true", (operand) => operand.type === "BooleanValue" && (operand as BooleanValue).value],
["number", (operand) => operand.type === "NumericValue"],
["integer", (operand) => operand.type === "NumericValue" && Number.isInteger((operand as NumericValue).value)],
["iterable", (operand) => operand instanceof ArrayValue || operand instanceof StringValue],
[
"lower",
(operand) => {
const str = (operand as StringValue).value;
return operand.type === "StringValue" && str === str.toLowerCase();
},
],
[
"upper",
(operand) => {
const str = (operand as StringValue).value;
return operand.type === "StringValue" && str === str.toUpperCase();
},
],
["none", (operand) => operand.type === "NullValue"],
["defined", (operand) => operand.type !== "UndefinedValue"],
["undefined", (operand) => operand.type === "UndefinedValue"],
["equalto", (a, b) => a.value === b.value],
]);
constructor(public parent?: Environment) {}
/**
* Set the value of a variable in the current environment.
*/
set(name: string, value: unknown): AnyRuntimeValue {
return this.declareVariable(name, convertToRuntimeValues(value));
}
private declareVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {
if (this.variables.has(name)) {
throw new SyntaxError(`Variable already declared: ${name}`);
}
this.variables.set(name, value);
return value;
}
// private assignVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {
// const env = this.resolve(name);
// env.variables.set(name, value);
// return value;
// }
/**
* Set variable in the current scope.
* See https://jinja.palletsprojects.com/en/3.0.x/templates/#assignments for more information.
*/
setVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {
this.variables.set(name, value);
return value;
}
/**
* Resolve the environment in which the variable is declared.
* @param {string} name The name of the variable.
* @returns {Environment} The environment in which the variable is declared.
*/
private resolve(name: string): Environment {
if (this.variables.has(name)) {
return this;
}
// Traverse scope chain
if (this.parent) {
return this.parent.resolve(name);
}
throw new Error(`Unknown variable: ${name}`);
}
lookupVariable(name: string): AnyRuntimeValue {
try {
return this.resolve(name).variables.get(name) ?? new UndefinedValue();
} catch {
return new UndefinedValue();
}
}
}
export class Interpreter {
global: Environment;
constructor(env?: Environment) {
this.global = env ?? new Environment();
}
/**
* Run the program.
*/
run(program: Program): AnyRuntimeValue {
return this.evaluate(program, this.global);
}
/**
* Evaluates expressions following the binary operation type.
*/
private evaluateBinaryExpression(node: BinaryExpression, environment: Environment): AnyRuntimeValue {
const left = this.evaluate(node.left, environment);
// Logical operators
// NOTE: Short-circuiting is handled by the `evaluate` function
switch (node.operator.value) {
case "and":
return left.__bool__().value ? this.evaluate(node.right, environment) : left;
case "or":
return left.__bool__().value ? left : this.evaluate(node.right, environment);
}
// Equality operators
const right = this.evaluate(node.right, environment);
switch (node.operator.value) {
case "==":
return new BooleanValue(left.value == right.value);
case "!=":
return new BooleanValue(left.value != right.value);
}
if (left instanceof UndefinedValue || right instanceof UndefinedValue) {
throw new Error("Cannot perform operation on undefined values");
} else if (left instanceof NullValue || right instanceof NullValue) {
throw new Error("Cannot perform operation on null values");
} else if (left instanceof NumericValue && right instanceof NumericValue) {
// Evaulate pure numeric operations with binary operators.
switch (node.operator.value) {
// Arithmetic operators
case "+":
return new NumericValue(left.value + right.value);
case "-":
return new NumericValue(left.value - right.value);
case "*":
return new NumericValue(left.value * right.value);
case "/":
return new NumericValue(left.value / right.value);
case "%":
return new NumericValue(left.value % right.value);
// Comparison operators
case "<":
return new BooleanValue(left.value < right.value);
case ">":
return new BooleanValue(left.value > right.value);
case ">=":
return new BooleanValue(left.value >= right.value);
case "<=":
return new BooleanValue(left.value <= right.value);
}
} else if (left instanceof ArrayValue && right instanceof ArrayValue) {
// Evaluate array operands with binary operator.
switch (node.operator.value) {
case "+":
return new ArrayValue(left.value.concat(right.value));
}
} else if (right instanceof ArrayValue) {
const member = right.value.find((x) => x.value === left.value) !== undefined;
switch (node.operator.value) {
case "in":
return new BooleanValue(member);
case "not in":
return new BooleanValue(!member);
}
}
if (left instanceof StringValue || right instanceof StringValue) {
// Support string concatenation as long as at least one operand is a string
switch (node.operator.value) {
case "+":
return new StringValue(left.value.toString() + right.value.toString());
}
}
if (left instanceof StringValue && right instanceof StringValue) {
switch (node.operator.value) {
case "in":
return new BooleanValue(right.value.includes(left.value));
case "not in":
return new BooleanValue(!right.value.includes(left.value));
}
}
if (left instanceof StringValue && right instanceof ObjectValue) {
switch (node.operator.value) {
case "in":
return new BooleanValue(right.value.has(left.value));
case "not in":
return new BooleanValue(!right.value.has(left.value));
}
}
throw new SyntaxError(`Unknown operator "${node.operator.value}" between ${left.type} and ${right.type}`);
}
/**
* Evaluates expressions following the filter operation type.
*/
private evaluateFilterExpression(node: FilterExpression, environment: Environment): AnyRuntimeValue {
const operand = this.evaluate(node.operand, environment);
// For now, we only support the built-in filters
// TODO: Add support for non-identifier filters
// e.g., functions which return filters: {{ numbers | select("odd") }}
// TODO: Add support for user-defined filters
// const filter = environment.lookupVariable(node.filter.value);
// if (!(filter instanceof FunctionValue)) {
// throw new Error(`Filter must be a function: got ${filter.type}`);
// }
// return filter.value([operand], environment);
// https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-filters
if (node.filter.type === "Identifier") {
const filter = node.filter as Identifier;
if (operand instanceof ArrayValue) {
switch (filter.value) {
case "list":
return operand;
case "first":
return operand.value[0];
case "last":
return operand.value[operand.value.length - 1];
case "length":
return new NumericValue(operand.value.length);
case "reverse":
return new ArrayValue(operand.value.reverse());
case "sort":
return new ArrayValue(
operand.value.sort((a, b) => {
if (a.type !== b.type) {
throw new Error(`Cannot compare different types: ${a.type} and ${b.type}`);
}
switch (a.type) {
case "NumericValue":
return (a as NumericValue).value - (b as NumericValue).value;
case "StringValue":
return (a as StringValue).value.localeCompare((b as StringValue).value);
default:
throw new Error(`Cannot compare type: ${a.type}`);
}
})
);
default:
throw new Error(`Unknown ArrayValue filter: ${filter.value}`);
}
} else if (operand instanceof StringValue) {
switch (filter.value) {
case "length":
return new NumericValue(operand.value.length);
case "upper":
return new StringValue(operand.value.toUpperCase());
case "lower":
return new StringValue(operand.value.toLowerCase());
case "title":
return new StringValue(titleCase(operand.value));
case "capitalize":
return new StringValue(operand.value.charAt(0).toUpperCase() + operand.value.slice(1));
case "trim":
return new StringValue(operand.value.trim());
default:
throw new Error(`Unknown StringValue filter: ${filter.value}`);
}
} else if (operand instanceof NumericValue) {
switch (filter.value) {
case "abs":
return new NumericValue(Math.abs(operand.value));
default:
throw new Error(`Unknown NumericValue filter: ${filter.value}`);
}
} else if (operand instanceof ObjectValue) {
switch (filter.value) {
case "items":
return new ArrayValue(
Array.from(operand.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))
);
case "length":
return new NumericValue(operand.value.size);
default:
throw new Error(`Unknown ObjectValue filter: ${filter.value}`);
}
}
throw new Error(`Cannot apply filter "${filter.value}" to type: ${operand.type}`);
} else if (node.filter.type === "CallExpression") {
const filter = node.filter as CallExpression;
if (filter.callee.type !== "Identifier") {
throw new Error(`Unknown filter: ${filter.callee.type}`);
}
const filterName = (filter.callee as Identifier).value;
if (operand instanceof ArrayValue) {
switch (filterName) {
case "selectattr": {
if (operand.value.some((x) => !(x instanceof ObjectValue))) {
throw new Error("`selectattr` can only be applied to array of objects");
}
if (filter.args.some((x) => x.type !== "StringLiteral")) {
throw new Error("arguments of `selectattr` must be strings");
}
const [attr, testName, value] = filter.args.map((x) => this.evaluate(x, environment)) as StringValue[];
let testFunction: (...x: AnyRuntimeValue[]) => boolean;
if (testName) {
// Get the test function from the environment
const test = environment.tests.get(testName.value);
if (!test) {
throw new Error(`Unknown test: ${testName.value}`);
}
testFunction = test;
} else {
// Default to truthiness of first argument
testFunction = (...x: AnyRuntimeValue[]) => x[0].__bool__().value;
}
// Filter the array using the test function
const filtered = (operand.value as ObjectValue[]).filter((item) => {
const a = item.value.get(attr.value);
if (a) {
return testFunction(a, value);
}
return false;
});
return new ArrayValue(filtered);
}
}
throw new Error(`Unknown ArrayValue filter: ${filterName}`);
} else {
throw new Error(`Cannot apply filter "${filterName}" to type: ${operand.type}`);
}
}
throw new Error(`Unknown filter: ${node.filter.type}`);
}
/**
* Evaluates expressions following the test operation type.
*/
private evaluateTestExpression(node: TestExpression, environment: Environment): BooleanValue {
// For now, we only support the built-in tests
// https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-builtin-tests
//
// TODO: Add support for non-identifier tests. e.g., divisibleby(number)
const operand = this.evaluate(node.operand, environment);
const test = environment.tests.get(node.test.value);
if (!test) {
throw new Error(`Unknown test: ${node.test.value}`);
}
const result = test(operand);
return new BooleanValue(node.negate ? !result : result);
}
/**
* Evaluates expressions following the unary operation type.
*/
private evaluateUnaryExpression(node: UnaryExpression, environment: Environment): AnyRuntimeValue {
const argument = this.evaluate(node.argument, environment);
switch (node.operator.value) {
case "not":
return new BooleanValue(!argument.value);
default:
throw new SyntaxError(`Unknown operator: ${node.operator.value}`);
}
}
private evalProgram(program: Program, environment: Environment): StringValue {
return this.evaluateBlock(program.body, environment);
}
private evaluateBlock(statements: Statement[], environment: Environment): StringValue {
// Jinja templates always evaluate to a String,
// so we accumulate the result of each statement into a final string
let result = "";
for (const statement of statements) {
const lastEvaluated = this.evaluate(statement, environment);
if (lastEvaluated.type !== "NullValue" && lastEvaluated.type !== "UndefinedValue") {
result += lastEvaluated.value;
}
}
return new StringValue(result);
}
private evaluateIdentifier(node: Identifier, environment: Environment): AnyRuntimeValue {
return environment.lookupVariable(node.value);
}
private evaluateCallExpression(expr: CallExpression, environment: Environment): AnyRuntimeValue {
// Accumulate all keyword arguments into a single object, which will be
// used as the final argument in the call function.
const args: AnyRuntimeValue[] = [];
const kwargs = new Map();
for (const argument of expr.args) {
if (argument.type === "KeywordArgumentExpression") {
const kwarg = argument as KeywordArgumentExpression;
kwargs.set(kwarg.key.value, this.evaluate(kwarg.value, environment));
} else {
args.push(this.evaluate(argument, environment));
}
}
if (kwargs.size > 0) {
args.push(new ObjectValue(kwargs));
}
const fn = this.evaluate(expr.callee, environment);
if (fn.type !== "FunctionValue") {
throw new Error(`Cannot call something that is not a function: got ${fn.type}`);
}
return (fn as FunctionValue).value(args, environment);
}
private evaluateSliceExpression(
object: AnyRuntimeValue,
expr: SliceExpression,
environment: Environment
): ArrayValue | StringValue {
if (!(object instanceof ArrayValue || object instanceof StringValue)) {
throw new Error("Slice object must be an array or string");
}
const start = this.evaluate(expr.start, environment);
const stop = this.evaluate(expr.stop, environment);
const step = this.evaluate(expr.step, environment);
// Validate arguments
if (!(start instanceof NumericValue || start instanceof UndefinedValue)) {
throw new Error("Slice start must be numeric or undefined");
}
if (!(stop instanceof NumericValue || stop instanceof UndefinedValue)) {
throw new Error("Slice stop must be numeric or undefined");
}
if (!(step instanceof NumericValue || step instanceof UndefinedValue)) {
throw new Error("Slice step must be numeric or undefined");
}
if (object instanceof ArrayValue) {
return new ArrayValue(slice(object.value, start.value, stop.value, step.value));
} else {
return new StringValue(slice(Array.from(object.value), start.value, stop.value, step.value).join(""));
}
}
private evaluateMemberExpression(expr: MemberExpression, environment: Environment): AnyRuntimeValue {
const object = this.evaluate(expr.object, environment);
let property;
if (expr.computed) {
if (expr.property.type === "SliceExpression") {
return this.evaluateSliceExpression(object, expr.property as SliceExpression, environment);
} else {
property = this.evaluate(expr.property, environment);
}
} else {
property = new StringValue((expr.property as Identifier).value);
}
let value;
if (object instanceof ObjectValue) {
if (!(property instanceof StringValue)) {
throw new Error(`Cannot access property with non-string: got ${property.type}`);
}
value = object.value.get(property.value) ?? object.builtins.get(property.value);
} else if (object instanceof ArrayValue || object instanceof StringValue) {
if (property instanceof NumericValue) {
value = object.value.at(property.value);
if (object instanceof StringValue) {
value = new StringValue(object.value.at(property.value));
}
} else if (property instanceof StringValue) {
value = object.builtins.get(property.value);
} else {
throw new Error(`Cannot access property with non-string/non-number: got ${property.type}`);
}
} else {
if (!(property instanceof StringValue)) {
throw new Error(`Cannot access property with non-string: got ${property.type}`);
}
value = object.builtins.get(property.value);
}
return value instanceof RuntimeValue ? value : new UndefinedValue();
}
private evaluateSet(node: SetStatement, environment: Environment): NullValue {
const rhs = this.evaluate(node.value, environment);
if (node.assignee.type === "Identifier") {
const variableName = (node.assignee as Identifier).value;
environment.setVariable(variableName, rhs);
} else if (node.assignee.type === "MemberExpression") {
const member = node.assignee as MemberExpression;
const object = this.evaluate(member.object, environment);
if (!(object instanceof ObjectValue)) {
throw new Error("Cannot assign to member of non-object");
}
if (member.property.type !== "Identifier") {
throw new Error("Cannot assign to member with non-identifier property");
}
object.value.set((member.property as Identifier).value, rhs);
} else {
throw new Error(`Invalid LHS inside assignment expression: ${JSON.stringify(node.assignee)}`);
}
return new NullValue();
}
private evaluateIf(node: If, environment: Environment): StringValue {
const test = this.evaluate(node.test, environment);
return this.evaluateBlock(test.__bool__().value ? node.body : node.alternate, environment);
}
private evaluateFor(node: For, environment: Environment): StringValue {
// Scope for the for loop
const scope = new Environment(environment);
const iterable = this.evaluate(node.iterable, scope);
if (!(iterable instanceof ArrayValue)) {
throw new Error(`Expected iterable type in for loop: got ${iterable.type}`);
}
let result = "";
for (let i = 0; i < iterable.value.length; ++i) {
// Update the loop variable
// TODO: Only create object once, then update value?
const loop = new Map([
["index", new NumericValue(i + 1)],
["index0", new NumericValue(i)],
["revindex", new NumericValue(iterable.value.length - i)],
["revindex0", new NumericValue(iterable.value.length - i - 1)],
["first", new BooleanValue(i === 0)],
["last", new BooleanValue(i === iterable.value.length - 1)],
["length", new NumericValue(iterable.value.length)],
["previtem", i > 0 ? iterable.value[i - 1] : new UndefinedValue()],
["nextitem", i < iterable.value.length - 1 ? iterable.value[i + 1] : new UndefinedValue()],
] as [string, AnyRuntimeValue][]);
scope.setVariable("loop", new ObjectValue(loop));
const current = iterable.value[i];
// For this iteration, set the loop variable to the current element
if (node.loopvar.type === "Identifier") {
scope.setVariable((node.loopvar as Identifier).value, current);
} else if (node.loopvar.type === "TupleLiteral") {
const loopvar = node.loopvar as TupleLiteral;
if (current.type !== "ArrayValue") {
throw new Error(`Cannot unpack non-iterable type: ${current.type}`);
}
const c = current as ArrayValue;
// check if too few or many items to unpack
if (loopvar.value.length !== c.value.length) {
throw new Error(`Too ${loopvar.value.length > c.value.length ? "few" : "many"} items to unpack`);
}
for (let j = 0; j < loopvar.value.length; ++j) {
if (loopvar.value[j].type !== "Identifier") {
throw new Error(`Cannot unpack non-identifier type: ${loopvar.value[j].type}`);
}
scope.setVariable((loopvar.value[j] as Identifier).value, c.value[j]);
}
}
// Evaluate the body of the for loop
const evaluated = this.evaluateBlock(node.body, scope);
result += evaluated.value;
}
return new StringValue(result);
}
evaluate(statement: Statement | undefined, environment: Environment): AnyRuntimeValue {
if (statement === undefined) return new UndefinedValue();
switch (statement.type) {
// Program
case "Program":
return this.evalProgram(statement as Program, environment);
// Statements
case "Set":
return this.evaluateSet(statement as SetStatement, environment);
case "If":
return this.evaluateIf(statement as If, environment);
case "For":
return this.evaluateFor(statement as For, environment);
// Expressions
case "NumericLiteral":
return new NumericValue(Number((statement as NumericLiteral).value));
case "StringLiteral":
return new StringValue((statement as StringLiteral).value);
case "BooleanLiteral":
return new BooleanValue((statement as BooleanLiteral).value);
case "ArrayLiteral":
return new ArrayValue((statement as ArrayLiteral).value.map((x) => this.evaluate(x, environment)));
case "TupleLiteral":
return new TupleValue((statement as TupleLiteral).value.map((x) => this.evaluate(x, environment)));
case "ObjectLiteral": {
const mapping = new Map();
for (const [key, value] of (statement as ObjectLiteral).value) {
const evaluatedKey = this.evaluate(key, environment);
if (!(evaluatedKey instanceof StringValue)) {
throw new Error(`Object keys must be strings: got ${evaluatedKey.type}`);
}
mapping.set(evaluatedKey.value, this.evaluate(value, environment));
}
return new ObjectValue(mapping);
}
case "Identifier":
return this.evaluateIdentifier(statement as Identifier, environment);
case "CallExpression":
return this.evaluateCallExpression(statement as CallExpression, environment);
case "MemberExpression":
return this.evaluateMemberExpression(statement as MemberExpression, environment);
case "UnaryExpression":
return this.evaluateUnaryExpression(statement as UnaryExpression, environment);
case "BinaryExpression":
return this.evaluateBinaryExpression(statement as BinaryExpression, environment);
case "FilterExpression":
return this.evaluateFilterExpression(statement as FilterExpression, environment);
case "TestExpression":
return this.evaluateTestExpression(statement as TestExpression, environment);
default:
throw new SyntaxError(`Unknown node type: ${statement.type}`);
}
}
}
/**
* Helper function to convert JavaScript values to runtime values.
*/
function convertToRuntimeValues(input: unknown): AnyRuntimeValue {
switch (typeof input) {
case "number":
return new NumericValue(input);
case "string":
return new StringValue(input);
case "boolean":
return new BooleanValue(input);
case "object":
if (input === null) {
return new NullValue();
} else if (Array.isArray(input)) {
return new ArrayValue(input.map(convertToRuntimeValues));
} else {
return new ObjectValue(
new Map(Object.entries(input).map(([key, value]) => [key, convertToRuntimeValues(value)]))
);
}
case "function":
// Wrap the user's function in a runtime function
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return new FunctionValue((args, _scope) => {
// NOTE: `_scope` is not used since it's in the global scope
const result = input(...args.map((x) => x.value)) ?? null; // map undefined -> null
return convertToRuntimeValues(result);
});
default:
throw new Error(`Cannot convert to runtime value: ${input}`);
}
}
+54
View File
@@ -0,0 +1,54 @@
/**
* Function that mimics Python's range() function.
* @param start The start value of the range.
* @param stop The stop value of the range. If not provided, start will be 0 and stop will be the provided start value.
* @param step The step value of the range. Defaults to 1.
* @returns The range of numbers.
*/
export function range(start: number, stop?: number, step = 1): number[] {
if (stop === undefined) {
stop = start;
start = 0;
}
const result: number[] = [];
for (let i = start; i < stop; i += step) {
result.push(i);
}
return result;
}
/**
* Function that mimics Python's array slicing.
* @param array The array to slice.
* @param start The start index of the slice. Defaults to 0.
* @param stop The last index of the slice. Defaults to `array.length`.
* @param step The step value of the slice. Defaults to 1.
* @returns The sliced array.
*/
export function slice<T>(array: T[], start?: number, stop?: number, step = 1): T[] {
const direction = Math.sign(step);
if (direction >= 0) {
start = (start ??= 0) < 0 ? Math.max(array.length + start, 0) : Math.min(start, array.length);
stop = (stop ??= array.length) < 0 ? Math.max(array.length + stop, 0) : Math.min(stop, array.length);
} else {
start = (start ??= array.length - 1) < 0 ? Math.max(array.length + start, -1) : Math.min(start, array.length - 1);
stop = (stop ??= -1) < -1 ? Math.max(array.length + stop, -1) : Math.min(stop, array.length - 1);
}
const result: T[] = [];
for (let i = start; direction * i < direction * stop; i += step) {
result.push(array[i]);
}
return result;
}
/**
* Function that mimics Python's string.title() function.
* @param value The string to title case.
* @returns The title cased string.
*/
export function titleCase(value: string): string {
return value.replace(/\b\w/g, (c) => c.toUpperCase());
}
+19
View File
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"lib": ["ES2022", "DOM"],
"module": "ESNext",
"moduleResolution": "node",
"target": "ESNext",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"skipLibCheck": true,
"noImplicitOverride": true,
"outDir": "./dist",
"declaration": true
},
"include": ["src", "index.ts"],
"exclude": ["dist"]
}
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+13
View File
@@ -0,0 +1,13 @@
@protobufjs/aspromise
=====================
[![npm](https://img.shields.io/npm/v/@protobufjs/aspromise.svg)](https://www.npmjs.com/package/@protobufjs/aspromise)
Returns a promise from a node-style callback function.
API
---
* **asPromise(fn: `function`, ctx: `Object`, ...params: `*`): `Promise<*>`**<br />
Returns a promise from a node-style callback function.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+13
View File
@@ -0,0 +1,13 @@
export = asPromise;
type asPromiseCallback = (error: Error | null, ...params: any[]) => {};
/**
* Returns a promise from a node-style callback function.
* @memberof util
* @param {asPromiseCallback} fn Function to call
* @param {*} ctx Function context
* @param {...*} params Function arguments
* @returns {Promise<*>} Promisified function
*/
declare function asPromise(fn: asPromiseCallback, ctx: any, ...params: any[]): Promise<any>;
+52
View File
@@ -0,0 +1,52 @@
"use strict";
module.exports = asPromise;
/**
* Callback as used by {@link util.asPromise}.
* @typedef asPromiseCallback
* @type {function}
* @param {Error|null} error Error, if any
* @param {...*} params Additional arguments
* @returns {undefined}
*/
/**
* Returns a promise from a node-style callback function.
* @memberof util
* @param {asPromiseCallback} fn Function to call
* @param {*} ctx Function context
* @param {...*} params Function arguments
* @returns {Promise<*>} Promisified function
*/
function asPromise(fn, ctx/*, varargs */) {
var params = new Array(arguments.length - 1),
offset = 0,
index = 2,
pending = true;
while (index < arguments.length)
params[offset++] = arguments[index++];
return new Promise(function executor(resolve, reject) {
params[offset] = function callback(err/*, varargs */) {
if (pending) {
pending = false;
if (err)
reject(err);
else {
var params = new Array(arguments.length - 1),
offset = 0;
while (offset < params.length)
params[offset++] = arguments[offset];
resolve.apply(null, params);
}
}
};
try {
fn.apply(ctx || null, params);
} catch (err) {
if (pending) {
pending = false;
reject(err);
}
}
});
}
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/aspromise",
"description": "Returns a promise from a node-style callback function.",
"version": "1.1.2",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+130
View File
@@ -0,0 +1,130 @@
var tape = require("tape");
var asPromise = require("..");
tape.test("aspromise", function(test) {
test.test(this.name + " - resolve", function(test) {
function fn(arg1, arg2, callback) {
test.equal(this, ctx, "function should be called with this = ctx");
test.equal(arg1, 1, "function should be called with arg1 = 1");
test.equal(arg2, 2, "function should be called with arg2 = 2");
callback(null, arg2);
}
var ctx = {};
var promise = asPromise(fn, ctx, 1, 2);
promise.then(function(arg2) {
test.equal(arg2, 2, "promise should be resolved with arg2 = 2");
test.end();
}).catch(function(err) {
test.fail("promise should not be rejected (" + err + ")");
});
});
test.test(this.name + " - reject", function(test) {
function fn(arg1, arg2, callback) {
test.equal(this, ctx, "function should be called with this = ctx");
test.equal(arg1, 1, "function should be called with arg1 = 1");
test.equal(arg2, 2, "function should be called with arg2 = 2");
callback(arg1);
}
var ctx = {};
var promise = asPromise(fn, ctx, 1, 2);
promise.then(function() {
test.fail("promise should not be resolved");
}).catch(function(err) {
test.equal(err, 1, "promise should be rejected with err = 1");
test.end();
});
});
test.test(this.name + " - resolve twice", function(test) {
function fn(arg1, arg2, callback) {
test.equal(this, ctx, "function should be called with this = ctx");
test.equal(arg1, 1, "function should be called with arg1 = 1");
test.equal(arg2, 2, "function should be called with arg2 = 2");
callback(null, arg2);
callback(null, arg1);
}
var ctx = {};
var count = 0;
var promise = asPromise(fn, ctx, 1, 2);
promise.then(function(arg2) {
test.equal(arg2, 2, "promise should be resolved with arg2 = 2");
if (++count > 1)
test.fail("promise should not be resolved twice");
test.end();
}).catch(function(err) {
test.fail("promise should not be rejected (" + err + ")");
});
});
test.test(this.name + " - reject twice", function(test) {
function fn(arg1, arg2, callback) {
test.equal(this, ctx, "function should be called with this = ctx");
test.equal(arg1, 1, "function should be called with arg1 = 1");
test.equal(arg2, 2, "function should be called with arg2 = 2");
callback(arg1);
callback(arg2);
}
var ctx = {};
var count = 0;
var promise = asPromise(fn, ctx, 1, 2);
promise.then(function() {
test.fail("promise should not be resolved");
}).catch(function(err) {
test.equal(err, 1, "promise should be rejected with err = 1");
if (++count > 1)
test.fail("promise should not be rejected twice");
test.end();
});
});
test.test(this.name + " - reject error", function(test) {
function fn(callback) {
test.ok(arguments.length === 1 && typeof callback === "function", "function should be called with just a callback");
throw 3;
}
var promise = asPromise(fn, null);
promise.then(function() {
test.fail("promise should not be resolved");
}).catch(function(err) {
test.equal(err, 3, "promise should be rejected with err = 3");
test.end();
});
});
test.test(this.name + " - reject and error", function(test) {
function fn(callback) {
callback(3);
throw 4;
}
var count = 0;
var promise = asPromise(fn, null);
promise.then(function() {
test.fail("promise should not be resolved");
}).catch(function(err) {
test.equal(err, 3, "promise should be rejected with err = 3");
if (++count > 1)
test.fail("promise should not be rejected twice");
test.end();
});
});
});
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+19
View File
@@ -0,0 +1,19 @@
@protobufjs/base64
==================
[![npm](https://img.shields.io/npm/v/@protobufjs/base64.svg)](https://www.npmjs.com/package/@protobufjs/base64)
A minimal base64 implementation for number arrays.
API
---
* **base64.length(string: `string`): `number`**<br />
Calculates the byte length of a base64 encoded string.
* **base64.encode(buffer: `Uint8Array`, start: `number`, end: `number`): `string`**<br />
Encodes a buffer to a base64 encoded string.
* **base64.decode(string: `string`, buffer: `Uint8Array`, offset: `number`): `number`**<br />
Decodes a base64 encoded string to a buffer.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+32
View File
@@ -0,0 +1,32 @@
/**
* Calculates the byte length of a base64 encoded string.
* @param {string} string Base64 encoded string
* @returns {number} Byte length
*/
export function length(string: string): number;
/**
* Encodes a buffer to a base64 encoded string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} Base64 encoded string
*/
export function encode(buffer: Uint8Array, start: number, end: number): string;
/**
* Decodes a base64 encoded string to a buffer.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Number of bytes written
* @throws {Error} If encoding is invalid
*/
export function decode(string: string, buffer: Uint8Array, offset: number): number;
/**
* Tests if the specified string appears to be base64 encoded.
* @param {string} string String to test
* @returns {boolean} `true` if it appears to be base64 encoded, otherwise false
*/
export function test(string: string): boolean;
+139
View File
@@ -0,0 +1,139 @@
"use strict";
/**
* A minimal base64 implementation for number arrays.
* @memberof util
* @namespace
*/
var base64 = exports;
/**
* Calculates the byte length of a base64 encoded string.
* @param {string} string Base64 encoded string
* @returns {number} Byte length
*/
base64.length = function length(string) {
var p = string.length;
if (!p)
return 0;
var n = 0;
while (--p % 4 > 1 && string.charAt(p) === "=")
++n;
return Math.ceil(string.length * 3) / 4 - n;
};
// Base64 encoding table
var b64 = new Array(64);
// Base64 decoding table
var s64 = new Array(123);
// 65..90, 97..122, 48..57, 43, 47
for (var i = 0; i < 64;)
s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
/**
* Encodes a buffer to a base64 encoded string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} Base64 encoded string
*/
base64.encode = function encode(buffer, start, end) {
var parts = null,
chunk = [];
var i = 0, // output index
j = 0, // goto index
t; // temporary
while (start < end) {
var b = buffer[start++];
switch (j) {
case 0:
chunk[i++] = b64[b >> 2];
t = (b & 3) << 4;
j = 1;
break;
case 1:
chunk[i++] = b64[t | b >> 4];
t = (b & 15) << 2;
j = 2;
break;
case 2:
chunk[i++] = b64[t | b >> 6];
chunk[i++] = b64[b & 63];
j = 0;
break;
}
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (j) {
chunk[i++] = b64[t];
chunk[i++] = 61;
if (j === 1)
chunk[i++] = 61;
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
};
var invalidEncoding = "invalid encoding";
/**
* Decodes a base64 encoded string to a buffer.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Number of bytes written
* @throws {Error} If encoding is invalid
*/
base64.decode = function decode(string, buffer, offset) {
var start = offset;
var j = 0, // goto index
t; // temporary
for (var i = 0; i < string.length;) {
var c = string.charCodeAt(i++);
if (c === 61 && j > 1)
break;
if ((c = s64[c]) === undefined)
throw Error(invalidEncoding);
switch (j) {
case 0:
t = c;
j = 1;
break;
case 1:
buffer[offset++] = t << 2 | (c & 48) >> 4;
t = c;
j = 2;
break;
case 2:
buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t = c;
j = 3;
break;
case 3:
buffer[offset++] = (t & 3) << 6 | c;
j = 0;
break;
}
}
if (j === 1)
throw Error(invalidEncoding);
return offset - start;
};
/**
* Tests if the specified string appears to be base64 encoded.
* @param {string} string String to test
* @returns {boolean} `true` if probably base64 encoded, otherwise false
*/
base64.test = function test(string) {
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);
};
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/base64",
"description": "A minimal base64 implementation for number arrays.",
"version": "1.1.2",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+46
View File
@@ -0,0 +1,46 @@
var tape = require("tape");
var base64 = require("..");
var strings = {
"": "",
"a": "YQ==",
"ab": "YWI=",
"abcdefg": "YWJjZGVmZw==",
"abcdefgh": "YWJjZGVmZ2g=",
"abcdefghi": "YWJjZGVmZ2hp"
};
tape.test("base64", function(test) {
Object.keys(strings).forEach(function(str) {
var enc = strings[str];
test.equal(base64.test(enc), true, "should detect '" + enc + "' to be base64 encoded");
var len = base64.length(enc);
test.equal(len, str.length, "should calculate '" + enc + "' as " + str.length + " bytes");
var buf = new Array(len);
var len2 = base64.decode(enc, buf, 0);
test.equal(len2, len, "should decode '" + enc + "' to " + len + " bytes");
test.equal(String.fromCharCode.apply(String, buf), str, "should decode '" + enc + "' to '" + str + "'");
var enc2 = base64.encode(buf, 0, buf.length);
test.equal(enc2, enc, "should encode '" + str + "' to '" + enc + "'");
});
test.throws(function() {
var buf = new Array(10);
base64.decode("YQ!", buf, 0);
}, Error, "should throw if encoding is invalid");
test.throws(function() {
var buf = new Array(10);
base64.decode("Y", buf, 0);
}, Error, "should throw if string is truncated");
test.end();
});
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+49
View File
@@ -0,0 +1,49 @@
@protobufjs/codegen
===================
[![npm](https://img.shields.io/npm/v/@protobufjs/codegen.svg)](https://www.npmjs.com/package/@protobufjs/codegen)
A minimalistic code generation utility.
API
---
* **codegen([functionParams: `string[]`], [functionName: string]): `Codegen`**<br />
Begins generating a function.
* **codegen.verbose = `false`**<br />
When set to true, codegen will log generated code to console. Useful for debugging.
Invoking **codegen** returns an appender function that appends code to the function's body and returns itself:
* **Codegen(formatString: `string`, [...formatParams: `any`]): Codegen**<br />
Appends code to the function's body. The format string can contain placeholders specifying the types of inserted format parameters:
* `%d`: Number (integer or floating point value)
* `%f`: Floating point value
* `%i`: Integer value
* `%j`: JSON.stringify'ed value
* `%s`: String value
* `%%`: Percent sign<br />
* **Codegen([scope: `Object.<string,*>`]): `Function`**<br />
Finishes the function and returns it.
* **Codegen.toString([functionNameOverride: `string`]): `string`**<br />
Returns the function as a string.
Example
-------
```js
var codegen = require("@protobufjs/codegen");
var add = codegen(["a", "b"], "add") // A function with parameters "a" and "b" named "add"
("// awesome comment") // adds the line to the function's body
("return a + b - c + %d", 1) // replaces %d with 1 and adds the line to the body
({ c: 1 }); // adds "c" with a value of 1 to the function's scope
console.log(add.toString()); // function add(a, b) { return a + b - c + 1 }
console.log(add(1, 2)); // calculates 1 + 2 - 1 + 1 = 3
```
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+31
View File
@@ -0,0 +1,31 @@
export = codegen;
/**
* Appends code to the function's body.
* @param [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any
* @param [formatParams] Format parameters
* @returns Itself or the generated function if finished
* @throws {Error} If format parameter counts do not match
*/
type Codegen = (formatStringOrScope?: (string|{ [k: string]: any }), ...formatParams: any[]) => (Codegen|Function);
/**
* Begins generating a function.
* @param functionParams Function parameter names
* @param [functionName] Function name if not anonymous
* @returns Appender that appends code to the function's body
*/
declare function codegen(functionParams: string[], functionName?: string): Codegen;
/**
* Begins generating a function.
* @param [functionName] Function name if not anonymous
* @returns Appender that appends code to the function's body
*/
declare function codegen(functionName?: string): Codegen;
declare namespace codegen {
/** When set to `true`, codegen will log generated code to console. Useful for debugging. */
let verbose: boolean;
}
+99
View File
@@ -0,0 +1,99 @@
"use strict";
module.exports = codegen;
/**
* Begins generating a function.
* @memberof util
* @param {string[]} functionParams Function parameter names
* @param {string} [functionName] Function name if not anonymous
* @returns {Codegen} Appender that appends code to the function's body
*/
function codegen(functionParams, functionName) {
/* istanbul ignore if */
if (typeof functionParams === "string") {
functionName = functionParams;
functionParams = undefined;
}
var body = [];
/**
* Appends code to the function's body or finishes generation.
* @typedef Codegen
* @type {function}
* @param {string|Object.<string,*>} [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any
* @param {...*} [formatParams] Format parameters
* @returns {Codegen|Function} Itself or the generated function if finished
* @throws {Error} If format parameter counts do not match
*/
function Codegen(formatStringOrScope) {
// note that explicit array handling below makes this ~50% faster
// finish the function
if (typeof formatStringOrScope !== "string") {
var source = toString();
if (codegen.verbose)
console.log("codegen: " + source); // eslint-disable-line no-console
source = "return " + source;
if (formatStringOrScope) {
var scopeKeys = Object.keys(formatStringOrScope),
scopeParams = new Array(scopeKeys.length + 1),
scopeValues = new Array(scopeKeys.length),
scopeOffset = 0;
while (scopeOffset < scopeKeys.length) {
scopeParams[scopeOffset] = scopeKeys[scopeOffset];
scopeValues[scopeOffset] = formatStringOrScope[scopeKeys[scopeOffset++]];
}
scopeParams[scopeOffset] = source;
return Function.apply(null, scopeParams).apply(null, scopeValues); // eslint-disable-line no-new-func
}
return Function(source)(); // eslint-disable-line no-new-func
}
// otherwise append to body
var formatParams = new Array(arguments.length - 1),
formatOffset = 0;
while (formatOffset < formatParams.length)
formatParams[formatOffset] = arguments[++formatOffset];
formatOffset = 0;
formatStringOrScope = formatStringOrScope.replace(/%([%dfijs])/g, function replace($0, $1) {
var value = formatParams[formatOffset++];
switch ($1) {
case "d": case "f": return String(Number(value));
case "i": return String(Math.floor(value));
case "j": return JSON.stringify(value);
case "s": return String(value);
}
return "%";
});
if (formatOffset !== formatParams.length)
throw Error("parameter count mismatch");
body.push(formatStringOrScope);
return Codegen;
}
function toString(functionNameOverride) {
return "function " + (functionNameOverride || functionName || "") + "(" + (functionParams && functionParams.join(",") || "") + "){\n " + body.join("\n ") + "\n}";
}
Codegen.toString = toString;
return Codegen;
}
/**
* Begins generating a function.
* @memberof util
* @function codegen
* @param {string} [functionName] Function name if not anonymous
* @returns {Codegen} Appender that appends code to the function's body
* @variation 2
*/
/**
* When set to `true`, codegen will log generated code to console. Useful for debugging.
* @name util.codegen.verbose
* @type {boolean}
*/
codegen.verbose = false;
+13
View File
@@ -0,0 +1,13 @@
{
"name": "@protobufjs/codegen",
"description": "A minimalistic code generation utility.",
"version": "2.0.4",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts"
}
+13
View File
@@ -0,0 +1,13 @@
var codegen = require("..");
// new require("benchmark").Suite().add("add", function() {
var add = codegen(["a", "b"], "add")
("// awesome comment")
("return a + b - c + %d", 1)
({ c: 1 });
if (add(1, 2) !== 3)
throw Error("failed");
// }).on("cycle", function(event) { process.stdout.write(String(event.target) + "\n"); }).run();
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+22
View File
@@ -0,0 +1,22 @@
@protobufjs/eventemitter
========================
[![npm](https://img.shields.io/npm/v/@protobufjs/eventemitter.svg)](https://www.npmjs.com/package/@protobufjs/eventemitter)
A minimal event emitter.
API
---
* **new EventEmitter()**<br />
Constructs a new event emitter instance.
* **EventEmitter#on(evt: `string`, fn: `function`, [ctx: `Object`]): `EventEmitter`**<br />
Registers an event listener.
* **EventEmitter#off([evt: `string`], [fn: `function`]): `EventEmitter`**<br />
Removes an event listener or any matching listeners if arguments are omitted.
* **EventEmitter#emit(evt: `string`, ...args: `*`): `EventEmitter`**<br />
Emits an event by calling its listeners with the specified arguments.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+43
View File
@@ -0,0 +1,43 @@
export = EventEmitter;
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
declare class EventEmitter {
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
constructor();
/**
* Registers an event listener.
* @param {string} evt Event name
* @param {function} fn Listener
* @param {*} [ctx] Listener context
* @returns {util.EventEmitter} `this`
*/
on(evt: string, fn: () => any, ctx?: any): EventEmitter;
/**
* Removes an event listener or any matching listeners if arguments are omitted.
* @param {string} [evt] Event name. Removes all listeners if omitted.
* @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
* @returns {util.EventEmitter} `this`
*/
off(evt?: string, fn?: () => any): EventEmitter;
/**
* Emits an event by calling its listeners with the specified arguments.
* @param {string} evt Event name
* @param {...*} args Arguments
* @returns {util.EventEmitter} `this`
*/
emit(evt: string, ...args: any[]): EventEmitter;
}
+76
View File
@@ -0,0 +1,76 @@
"use strict";
module.exports = EventEmitter;
/**
* Constructs a new event emitter instance.
* @classdesc A minimal event emitter.
* @memberof util
* @constructor
*/
function EventEmitter() {
/**
* Registered listeners.
* @type {Object.<string,*>}
* @private
*/
this._listeners = {};
}
/**
* Registers an event listener.
* @param {string} evt Event name
* @param {function} fn Listener
* @param {*} [ctx] Listener context
* @returns {util.EventEmitter} `this`
*/
EventEmitter.prototype.on = function on(evt, fn, ctx) {
(this._listeners[evt] || (this._listeners[evt] = [])).push({
fn : fn,
ctx : ctx || this
});
return this;
};
/**
* Removes an event listener or any matching listeners if arguments are omitted.
* @param {string} [evt] Event name. Removes all listeners if omitted.
* @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
* @returns {util.EventEmitter} `this`
*/
EventEmitter.prototype.off = function off(evt, fn) {
if (evt === undefined)
this._listeners = {};
else {
if (fn === undefined)
this._listeners[evt] = [];
else {
var listeners = this._listeners[evt];
for (var i = 0; i < listeners.length;)
if (listeners[i].fn === fn)
listeners.splice(i, 1);
else
++i;
}
}
return this;
};
/**
* Emits an event by calling its listeners with the specified arguments.
* @param {string} evt Event name
* @param {...*} args Arguments
* @returns {util.EventEmitter} `this`
*/
EventEmitter.prototype.emit = function emit(evt) {
var listeners = this._listeners[evt];
if (listeners) {
var args = [],
i = 1;
for (; i < arguments.length;)
args.push(arguments[i++]);
for (i = 0; i < listeners.length;)
listeners[i].fn.apply(listeners[i++].ctx, args);
}
return this;
};
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/eventemitter",
"description": "A minimal event emitter.",
"version": "1.1.0",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+47
View File
@@ -0,0 +1,47 @@
var tape = require("tape");
var EventEmitter = require("..");
tape.test("eventemitter", function(test) {
var ee = new EventEmitter();
var fn;
var ctx = {};
test.doesNotThrow(function() {
ee.emit("a", 1);
ee.off();
ee.off("a");
ee.off("a", function() {});
}, "should not throw if no listeners are registered");
test.equal(ee.on("a", function(arg1) {
test.equal(this, ctx, "should be called with this = ctx");
test.equal(arg1, 1, "should be called with arg1 = 1");
}, ctx), ee, "should return itself when registering events");
ee.emit("a", 1);
ee.off("a");
test.same(ee._listeners, { a: [] }, "should remove all listeners of the respective event when calling off(evt)");
ee.off();
test.same(ee._listeners, {}, "should remove all listeners when just calling off()");
ee.on("a", fn = function(arg1) {
test.equal(this, ctx, "should be called with this = ctx");
test.equal(arg1, 1, "should be called with arg1 = 1");
}, ctx).emit("a", 1);
ee.off("a", fn);
test.same(ee._listeners, { a: [] }, "should remove the exact listener when calling off(evt, fn)");
ee.on("a", function() {
test.equal(this, ee, "should be called with this = ee");
}).emit("a");
test.doesNotThrow(function() {
ee.off("a", fn);
}, "should not throw if no such listener is found");
test.end();
});
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+13
View File
@@ -0,0 +1,13 @@
@protobufjs/fetch
=================
[![npm](https://img.shields.io/npm/v/@protobufjs/fetch.svg)](https://www.npmjs.com/package/@protobufjs/fetch)
Fetches the contents of a file accross node and browsers.
API
---
* **fetch(path: `string`, [options: { binary: boolean } ], [callback: `function(error: ?Error, [contents: string])`]): `Promise<string|Uint8Array>|undefined`**
Fetches the contents of a file.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+56
View File
@@ -0,0 +1,56 @@
export = fetch;
/**
* Node-style callback as used by {@link util.fetch}.
* @typedef FetchCallback
* @type {function}
* @param {?Error} error Error, if any, otherwise `null`
* @param {string} [contents] File contents, if there hasn't been an error
* @returns {undefined}
*/
type FetchCallback = (error: Error, contents?: string) => void;
/**
* Options as used by {@link util.fetch}.
* @typedef FetchOptions
* @type {Object}
* @property {boolean} [binary=false] Whether expecting a binary response
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
*/
interface FetchOptions {
binary?: boolean;
xhr?: boolean
}
/**
* Fetches the contents of a file.
* @memberof util
* @param {string} filename File path or url
* @param {FetchOptions} options Fetch options
* @param {FetchCallback} callback Callback function
* @returns {undefined}
*/
declare function fetch(filename: string, options: FetchOptions, callback: FetchCallback): void;
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchCallback} callback Callback function
* @returns {undefined}
* @variation 2
*/
declare function fetch(path: string, callback: FetchCallback): void;
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchOptions} [options] Fetch options
* @returns {Promise<string|Uint8Array>} Promise
* @variation 3
*/
declare function fetch(path: string, options?: FetchOptions): Promise<(string|Uint8Array)>;
+115
View File
@@ -0,0 +1,115 @@
"use strict";
module.exports = fetch;
var asPromise = require("@protobufjs/aspromise"),
inquire = require("@protobufjs/inquire");
var fs = inquire("fs");
/**
* Node-style callback as used by {@link util.fetch}.
* @typedef FetchCallback
* @type {function}
* @param {?Error} error Error, if any, otherwise `null`
* @param {string} [contents] File contents, if there hasn't been an error
* @returns {undefined}
*/
/**
* Options as used by {@link util.fetch}.
* @typedef FetchOptions
* @type {Object}
* @property {boolean} [binary=false] Whether expecting a binary response
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
*/
/**
* Fetches the contents of a file.
* @memberof util
* @param {string} filename File path or url
* @param {FetchOptions} options Fetch options
* @param {FetchCallback} callback Callback function
* @returns {undefined}
*/
function fetch(filename, options, callback) {
if (typeof options === "function") {
callback = options;
options = {};
} else if (!options)
options = {};
if (!callback)
return asPromise(fetch, this, filename, options); // eslint-disable-line no-invalid-this
// if a node-like filesystem is present, try it first but fall back to XHR if nothing is found.
if (!options.xhr && fs && fs.readFile)
return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
return err && typeof XMLHttpRequest !== "undefined"
? fetch.xhr(filename, options, callback)
: err
? callback(err)
: callback(null, options.binary ? contents : contents.toString("utf8"));
});
// use the XHR version otherwise.
return fetch.xhr(filename, options, callback);
}
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchCallback} callback Callback function
* @returns {undefined}
* @variation 2
*/
/**
* Fetches the contents of a file.
* @name util.fetch
* @function
* @param {string} path File path or url
* @param {FetchOptions} [options] Fetch options
* @returns {Promise<string|Uint8Array>} Promise
* @variation 3
*/
/**/
fetch.xhr = function fetch_xhr(filename, options, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() {
if (xhr.readyState !== 4)
return undefined;
// local cors security errors return status 0 / empty string, too. afaik this cannot be
// reliably distinguished from an actually empty file for security reasons. feel free
// to send a pull request if you are aware of a solution.
if (xhr.status !== 0 && xhr.status !== 200)
return callback(Error("status " + xhr.status));
// if binary data is expected, make sure that some sort of array is returned, even if
// ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
if (options.binary) {
var buffer = xhr.response;
if (!buffer) {
buffer = [];
for (var i = 0; i < xhr.responseText.length; ++i)
buffer.push(xhr.responseText.charCodeAt(i) & 255);
}
return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer);
}
return callback(null, xhr.responseText);
};
if (options.binary) {
// ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
if ("overrideMimeType" in xhr)
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.responseType = "arraybuffer";
}
xhr.open("GET", filename);
xhr.send();
};
+25
View File
@@ -0,0 +1,25 @@
{
"name": "@protobufjs/fetch",
"description": "Fetches the contents of a file accross node and browsers.",
"version": "1.1.0",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"dependencies": {
"@protobufjs/aspromise": "^1.1.1",
"@protobufjs/inquire": "^1.1.0"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+16
View File
@@ -0,0 +1,16 @@
var tape = require("tape");
var fetch = require("..");
tape.test("fetch", function(test) {
if (typeof Promise !== "undefined") {
var promise = fetch("NOTFOUND");
promise.catch(function() {});
test.ok(promise instanceof Promise, "should return a promise if callback has been omitted");
}
// TODO - some way to test this properly?
test.end();
});
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+102
View File
@@ -0,0 +1,102 @@
@protobufjs/float
=================
[![npm](https://img.shields.io/npm/v/@protobufjs/float.svg)](https://www.npmjs.com/package/@protobufjs/float)
Reads / writes floats / doubles from / to buffers in both modern and ancient browsers. Fast.
API
---
* **writeFloatLE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br />
Writes a 32 bit float to a buffer using little endian byte order.
* **writeFloatBE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br />
Writes a 32 bit float to a buffer using big endian byte order.
* **readFloatLE(buf: `Uint8Array`, pos: `number`): `number`**<br />
Reads a 32 bit float from a buffer using little endian byte order.
* **readFloatBE(buf: `Uint8Array`, pos: `number`): `number`**<br />
Reads a 32 bit float from a buffer using big endian byte order.
* **writeDoubleLE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br />
Writes a 64 bit double to a buffer using little endian byte order.
* **writeDoubleBE(val: `number`, buf: `Uint8Array`, pos: `number`)**<br />
Writes a 64 bit double to a buffer using big endian byte order.
* **readDoubleLE(buf: `Uint8Array`, pos: `number`): `number`**<br />
Reads a 64 bit double from a buffer using little endian byte order.
* **readDoubleBE(buf: `Uint8Array`, pos: `number`): `number`**<br />
Reads a 64 bit double from a buffer using big endian byte order.
Performance
-----------
There is a simple benchmark included comparing raw read/write performance of this library (float), float's fallback for old browsers, the [ieee754](https://www.npmjs.com/package/ieee754) module and node's [buffer](https://nodejs.org/api/buffer.html). On an i7-2600k running node 6.9.1 it yields:
```
benchmarking writeFloat performance ...
float x 42,741,625 ops/sec ±1.75% (81 runs sampled)
float (fallback) x 11,272,532 ops/sec ±1.12% (85 runs sampled)
ieee754 x 8,653,337 ops/sec ±1.18% (84 runs sampled)
buffer x 12,412,414 ops/sec ±1.41% (83 runs sampled)
buffer (noAssert) x 13,471,149 ops/sec ±1.09% (84 runs sampled)
float was fastest
float (fallback) was 73.5% slower
ieee754 was 79.6% slower
buffer was 70.9% slower
buffer (noAssert) was 68.3% slower
benchmarking readFloat performance ...
float x 44,382,729 ops/sec ±1.70% (84 runs sampled)
float (fallback) x 20,925,938 ops/sec ±0.86% (87 runs sampled)
ieee754 x 17,189,009 ops/sec ±1.01% (87 runs sampled)
buffer x 10,518,437 ops/sec ±1.04% (83 runs sampled)
buffer (noAssert) x 11,031,636 ops/sec ±1.15% (87 runs sampled)
float was fastest
float (fallback) was 52.5% slower
ieee754 was 61.0% slower
buffer was 76.1% slower
buffer (noAssert) was 75.0% slower
benchmarking writeDouble performance ...
float x 38,624,906 ops/sec ±0.93% (83 runs sampled)
float (fallback) x 10,457,811 ops/sec ±1.54% (85 runs sampled)
ieee754 x 7,681,130 ops/sec ±1.11% (83 runs sampled)
buffer x 12,657,876 ops/sec ±1.03% (83 runs sampled)
buffer (noAssert) x 13,372,795 ops/sec ±0.84% (85 runs sampled)
float was fastest
float (fallback) was 73.1% slower
ieee754 was 80.1% slower
buffer was 67.3% slower
buffer (noAssert) was 65.3% slower
benchmarking readDouble performance ...
float x 40,527,888 ops/sec ±1.05% (84 runs sampled)
float (fallback) x 18,696,480 ops/sec ±0.84% (86 runs sampled)
ieee754 x 14,074,028 ops/sec ±1.04% (87 runs sampled)
buffer x 10,092,367 ops/sec ±1.15% (84 runs sampled)
buffer (noAssert) x 10,623,793 ops/sec ±0.96% (84 runs sampled)
float was fastest
float (fallback) was 53.8% slower
ieee754 was 65.3% slower
buffer was 75.1% slower
buffer (noAssert) was 73.8% slower
```
To run it yourself:
```
$> npm run bench
```
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+87
View File
@@ -0,0 +1,87 @@
"use strict";
var float = require(".."),
ieee754 = require("ieee754"),
newSuite = require("./suite");
var F32 = Float32Array;
var F64 = Float64Array;
delete global.Float32Array;
delete global.Float64Array;
var floatFallback = float({});
global.Float32Array = F32;
global.Float64Array = F64;
var buf = new Buffer(8);
newSuite("writeFloat")
.add("float", function() {
float.writeFloatLE(0.1, buf, 0);
})
.add("float (fallback)", function() {
floatFallback.writeFloatLE(0.1, buf, 0);
})
.add("ieee754", function() {
ieee754.write(buf, 0.1, 0, true, 23, 4);
})
.add("buffer", function() {
buf.writeFloatLE(0.1, 0);
})
.add("buffer (noAssert)", function() {
buf.writeFloatLE(0.1, 0, true);
})
.run();
newSuite("readFloat")
.add("float", function() {
float.readFloatLE(buf, 0);
})
.add("float (fallback)", function() {
floatFallback.readFloatLE(buf, 0);
})
.add("ieee754", function() {
ieee754.read(buf, 0, true, 23, 4);
})
.add("buffer", function() {
buf.readFloatLE(0);
})
.add("buffer (noAssert)", function() {
buf.readFloatLE(0, true);
})
.run();
newSuite("writeDouble")
.add("float", function() {
float.writeDoubleLE(0.1, buf, 0);
})
.add("float (fallback)", function() {
floatFallback.writeDoubleLE(0.1, buf, 0);
})
.add("ieee754", function() {
ieee754.write(buf, 0.1, 0, true, 52, 8);
})
.add("buffer", function() {
buf.writeDoubleLE(0.1, 0);
})
.add("buffer (noAssert)", function() {
buf.writeDoubleLE(0.1, 0, true);
})
.run();
newSuite("readDouble")
.add("float", function() {
float.readDoubleLE(buf, 0);
})
.add("float (fallback)", function() {
floatFallback.readDoubleLE(buf, 0);
})
.add("ieee754", function() {
ieee754.read(buf, 0, true, 52, 8);
})
.add("buffer", function() {
buf.readDoubleLE(0);
})
.add("buffer (noAssert)", function() {
buf.readDoubleLE(0, true);
})
.run();
+46
View File
@@ -0,0 +1,46 @@
"use strict";
module.exports = newSuite;
var benchmark = require("benchmark"),
chalk = require("chalk");
var padSize = 27;
function newSuite(name) {
var benches = [];
return new benchmark.Suite(name)
.on("add", function(event) {
benches.push(event.target);
})
.on("start", function() {
process.stdout.write("benchmarking " + name + " performance ...\n\n");
})
.on("cycle", function(event) {
process.stdout.write(String(event.target) + "\n");
})
.on("complete", function() {
if (benches.length > 1) {
var fastest = this.filter("fastest"), // eslint-disable-line no-invalid-this
fastestHz = getHz(fastest[0]);
process.stdout.write("\n" + chalk.white(pad(fastest[0].name, padSize)) + " was " + chalk.green("fastest") + "\n");
benches.forEach(function(bench) {
if (fastest.indexOf(bench) === 0)
return;
var hz = hz = getHz(bench);
var percent = (1 - hz / fastestHz) * 100;
process.stdout.write(chalk.white(pad(bench.name, padSize)) + " was " + chalk.red(percent.toFixed(1) + "% slower") + "\n");
});
}
process.stdout.write("\n");
});
}
function getHz(bench) {
return 1 / (bench.stats.mean + bench.stats.moe);
}
function pad(str, len, l) {
while (str.length < len)
str = l ? str + " " : " " + str;
return str;
}
+83
View File
@@ -0,0 +1,83 @@
/**
* Writes a 32 bit float to a buffer using little endian byte order.
* @name writeFloatLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeFloatLE(val: number, buf: Uint8Array, pos: number): void;
/**
* Writes a 32 bit float to a buffer using big endian byte order.
* @name writeFloatBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeFloatBE(val: number, buf: Uint8Array, pos: number): void;
/**
* Reads a 32 bit float from a buffer using little endian byte order.
* @name readFloatLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readFloatLE(buf: Uint8Array, pos: number): number;
/**
* Reads a 32 bit float from a buffer using big endian byte order.
* @name readFloatBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readFloatBE(buf: Uint8Array, pos: number): number;
/**
* Writes a 64 bit double to a buffer using little endian byte order.
* @name writeDoubleLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeDoubleLE(val: number, buf: Uint8Array, pos: number): void;
/**
* Writes a 64 bit double to a buffer using big endian byte order.
* @name writeDoubleBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
export function writeDoubleBE(val: number, buf: Uint8Array, pos: number): void;
/**
* Reads a 64 bit double from a buffer using little endian byte order.
* @name readDoubleLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readDoubleLE(buf: Uint8Array, pos: number): number;
/**
* Reads a 64 bit double from a buffer using big endian byte order.
* @name readDoubleBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
export function readDoubleBE(buf: Uint8Array, pos: number): number;
+335
View File
@@ -0,0 +1,335 @@
"use strict";
module.exports = factory(factory);
/**
* Reads / writes floats / doubles from / to buffers.
* @name util.float
* @namespace
*/
/**
* Writes a 32 bit float to a buffer using little endian byte order.
* @name util.float.writeFloatLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Writes a 32 bit float to a buffer using big endian byte order.
* @name util.float.writeFloatBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Reads a 32 bit float from a buffer using little endian byte order.
* @name util.float.readFloatLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Reads a 32 bit float from a buffer using big endian byte order.
* @name util.float.readFloatBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Writes a 64 bit double to a buffer using little endian byte order.
* @name util.float.writeDoubleLE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Writes a 64 bit double to a buffer using big endian byte order.
* @name util.float.writeDoubleBE
* @function
* @param {number} val Value to write
* @param {Uint8Array} buf Target buffer
* @param {number} pos Target buffer offset
* @returns {undefined}
*/
/**
* Reads a 64 bit double from a buffer using little endian byte order.
* @name util.float.readDoubleLE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
/**
* Reads a 64 bit double from a buffer using big endian byte order.
* @name util.float.readDoubleBE
* @function
* @param {Uint8Array} buf Source buffer
* @param {number} pos Source buffer offset
* @returns {number} Value read
*/
// Factory function for the purpose of node-based testing in modified global environments
function factory(exports) {
// float: typed array
if (typeof Float32Array !== "undefined") (function() {
var f32 = new Float32Array([ -0 ]),
f8b = new Uint8Array(f32.buffer),
le = f8b[3] === 128;
function writeFloat_f32_cpy(val, buf, pos) {
f32[0] = val;
buf[pos ] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
}
function writeFloat_f32_rev(val, buf, pos) {
f32[0] = val;
buf[pos ] = f8b[3];
buf[pos + 1] = f8b[2];
buf[pos + 2] = f8b[1];
buf[pos + 3] = f8b[0];
}
/* istanbul ignore next */
exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
/* istanbul ignore next */
exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;
function readFloat_f32_cpy(buf, pos) {
f8b[0] = buf[pos ];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
return f32[0];
}
function readFloat_f32_rev(buf, pos) {
f8b[3] = buf[pos ];
f8b[2] = buf[pos + 1];
f8b[1] = buf[pos + 2];
f8b[0] = buf[pos + 3];
return f32[0];
}
/* istanbul ignore next */
exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
/* istanbul ignore next */
exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;
// float: ieee754
})(); else (function() {
function writeFloat_ieee754(writeUint, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0)
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos);
else if (isNaN(val))
writeUint(2143289344, buf, pos);
else if (val > 3.4028234663852886e+38) // +-Infinity
writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
else if (val < 1.1754943508222875e-38) // denormal
writeUint((sign << 31 | Math.round(val / 1.401298464324817e-45)) >>> 0, buf, pos);
else {
var exponent = Math.floor(Math.log(val) / Math.LN2),
mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
}
}
exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);
function readFloat_ieee754(readUint, buf, pos) {
var uint = readUint(buf, pos),
sign = (uint >> 31) * 2 + 1,
exponent = uint >>> 23 & 255,
mantissa = uint & 8388607;
return exponent === 255
? mantissa
? NaN
: sign * Infinity
: exponent === 0 // denormal
? sign * 1.401298464324817e-45 * mantissa
: sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
}
exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);
})();
// double: typed array
if (typeof Float64Array !== "undefined") (function() {
var f64 = new Float64Array([-0]),
f8b = new Uint8Array(f64.buffer),
le = f8b[7] === 128;
function writeDouble_f64_cpy(val, buf, pos) {
f64[0] = val;
buf[pos ] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
buf[pos + 4] = f8b[4];
buf[pos + 5] = f8b[5];
buf[pos + 6] = f8b[6];
buf[pos + 7] = f8b[7];
}
function writeDouble_f64_rev(val, buf, pos) {
f64[0] = val;
buf[pos ] = f8b[7];
buf[pos + 1] = f8b[6];
buf[pos + 2] = f8b[5];
buf[pos + 3] = f8b[4];
buf[pos + 4] = f8b[3];
buf[pos + 5] = f8b[2];
buf[pos + 6] = f8b[1];
buf[pos + 7] = f8b[0];
}
/* istanbul ignore next */
exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
/* istanbul ignore next */
exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;
function readDouble_f64_cpy(buf, pos) {
f8b[0] = buf[pos ];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
f8b[4] = buf[pos + 4];
f8b[5] = buf[pos + 5];
f8b[6] = buf[pos + 6];
f8b[7] = buf[pos + 7];
return f64[0];
}
function readDouble_f64_rev(buf, pos) {
f8b[7] = buf[pos ];
f8b[6] = buf[pos + 1];
f8b[5] = buf[pos + 2];
f8b[4] = buf[pos + 3];
f8b[3] = buf[pos + 4];
f8b[2] = buf[pos + 5];
f8b[1] = buf[pos + 6];
f8b[0] = buf[pos + 7];
return f64[0];
}
/* istanbul ignore next */
exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
/* istanbul ignore next */
exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;
// double: ieee754
})(); else (function() {
function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0) {
writeUint(0, buf, pos + off0);
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + off1);
} else if (isNaN(val)) {
writeUint(0, buf, pos + off0);
writeUint(2146959360, buf, pos + off1);
} else if (val > 1.7976931348623157e+308) { // +-Infinity
writeUint(0, buf, pos + off0);
writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
} else {
var mantissa;
if (val < 2.2250738585072014e-308) { // denormal
mantissa = val / 5e-324;
writeUint(mantissa >>> 0, buf, pos + off0);
writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
} else {
var exponent = Math.floor(Math.log(val) / Math.LN2);
if (exponent === 1024)
exponent = 1023;
mantissa = val * Math.pow(2, -exponent);
writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
}
}
}
exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);
function readDouble_ieee754(readUint, off0, off1, buf, pos) {
var lo = readUint(buf, pos + off0),
hi = readUint(buf, pos + off1);
var sign = (hi >> 31) * 2 + 1,
exponent = hi >>> 20 & 2047,
mantissa = 4294967296 * (hi & 1048575) + lo;
return exponent === 2047
? mantissa
? NaN
: sign * Infinity
: exponent === 0 // denormal
? sign * 5e-324 * mantissa
: sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
}
exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);
})();
return exports;
}
// uint helpers
function writeUintLE(val, buf, pos) {
buf[pos ] = val & 255;
buf[pos + 1] = val >>> 8 & 255;
buf[pos + 2] = val >>> 16 & 255;
buf[pos + 3] = val >>> 24;
}
function writeUintBE(val, buf, pos) {
buf[pos ] = val >>> 24;
buf[pos + 1] = val >>> 16 & 255;
buf[pos + 2] = val >>> 8 & 255;
buf[pos + 3] = val & 255;
}
function readUintLE(buf, pos) {
return (buf[pos ]
| buf[pos + 1] << 8
| buf[pos + 2] << 16
| buf[pos + 3] << 24) >>> 0;
}
function readUintBE(buf, pos) {
return (buf[pos ] << 24
| buf[pos + 1] << 16
| buf[pos + 2] << 8
| buf[pos + 3]) >>> 0;
}
+26
View File
@@ -0,0 +1,26 @@
{
"name": "@protobufjs/float",
"description": "Reads / writes floats / doubles from / to buffers in both modern and ancient browsers.",
"version": "1.0.2",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"dependencies": {},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"benchmark": "^2.1.4",
"chalk": "^1.1.3",
"ieee754": "^1.1.8",
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js",
"bench": "node bench"
}
}
+100
View File
@@ -0,0 +1,100 @@
var tape = require("tape");
var float = require("..");
tape.test("float", function(test) {
// default
test.test(test.name + " - typed array", function(test) {
runTest(float, test);
});
// ieee754
test.test(test.name + " - fallback", function(test) {
var F32 = global.Float32Array,
F64 = global.Float64Array;
delete global.Float32Array;
delete global.Float64Array;
runTest(float({}), test);
global.Float32Array = F32;
global.Float64Array = F64;
});
});
function runTest(float, test) {
var common = [
0,
-0,
Infinity,
-Infinity,
0.125,
1024.5,
-4096.5,
NaN
];
test.test(test.name + " - using 32 bits", function(test) {
common.concat([
3.4028234663852886e+38,
1.1754943508222875e-38,
1.1754946310819804e-39
])
.forEach(function(value) {
var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString();
test.ok(
checkValue(value, 4, float.readFloatLE, float.writeFloatLE, Buffer.prototype.writeFloatLE),
"should write and read back " + strval + " (32 bit LE)"
);
test.ok(
checkValue(value, 4, float.readFloatBE, float.writeFloatBE, Buffer.prototype.writeFloatBE),
"should write and read back " + strval + " (32 bit BE)"
);
});
test.end();
});
test.test(test.name + " - using 64 bits", function(test) {
common.concat([
1.7976931348623157e+308,
2.2250738585072014e-308,
2.2250738585072014e-309
])
.forEach(function(value) {
var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString();
test.ok(
checkValue(value, 8, float.readDoubleLE, float.writeDoubleLE, Buffer.prototype.writeDoubleLE),
"should write and read back " + strval + " (64 bit LE)"
);
test.ok(
checkValue(value, 8, float.readDoubleBE, float.writeDoubleBE, Buffer.prototype.writeDoubleBE),
"should write and read back " + strval + " (64 bit BE)"
);
});
test.end();
});
test.end();
}
function checkValue(value, size, read, write, write_comp) {
var buffer = new Buffer(size);
write(value, buffer, 0);
var value_comp = read(buffer, 0);
var strval = value === 0 && 1 / value < 0 ? "-0" : value.toString();
if (value !== value) {
if (value_comp === value_comp)
return false;
} else if (value_comp !== value)
return false;
var buffer_comp = new Buffer(size);
write_comp.call(buffer_comp, value, 0);
for (var i = 0; i < size; ++i)
if (buffer[i] !== buffer_comp[i]) {
console.error(">", buffer, buffer_comp);
return false;
}
return true;
}
+3
View File
@@ -0,0 +1,3 @@
npm-debug.*
node_modules/
coverage/
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+13
View File
@@ -0,0 +1,13 @@
@protobufjs/inquire
===================
[![npm](https://img.shields.io/npm/v/@protobufjs/inquire.svg)](https://www.npmjs.com/package/@protobufjs/inquire)
Requires a module only if available and hides the require call from bundlers.
API
---
* **inquire(moduleName: `string`): `?Object`**<br />
Requires a module only if available.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+9
View File
@@ -0,0 +1,9 @@
export = inquire;
/**
* Requires a module only if available.
* @memberof util
* @param {string} moduleName Module to require
* @returns {?Object} Required module if available and not empty, otherwise `null`
*/
declare function inquire(moduleName: string): Object;
+17
View File
@@ -0,0 +1,17 @@
"use strict";
module.exports = inquire;
/**
* Requires a module only if available.
* @memberof util
* @param {string} moduleName Module to require
* @returns {?Object} Required module if available and not empty, otherwise `null`
*/
function inquire(moduleName) {
try {
var mod = eval("quire".replace(/^/,"re"))(moduleName); // eslint-disable-line no-eval
if (mod && (mod.length || Object.keys(mod).length))
return mod;
} catch (e) {} // eslint-disable-line no-empty
return null;
}
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/inquire",
"description": "Requires a module only if available and hides the require call from bundlers.",
"version": "1.1.0",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = [1];
+1
View File
@@ -0,0 +1 @@
module.exports = [];
+1
View File
@@ -0,0 +1 @@
module.exports = {};
+1
View File
@@ -0,0 +1 @@
module.exports = { a: 1 };
+20
View File
@@ -0,0 +1,20 @@
var tape = require("tape");
var inquire = require("..");
tape.test("inquire", function(test) {
test.equal(inquire("buffer").Buffer, Buffer, "should be able to require \"buffer\"");
test.equal(inquire("%invalid"), null, "should not be able to require \"%invalid\"");
test.equal(inquire("./tests/data/emptyObject"), null, "should return null when requiring a module exporting an empty object");
test.equal(inquire("./tests/data/emptyArray"), null, "should return null when requiring a module exporting an empty array");
test.same(inquire("./tests/data/object"), { a: 1 }, "should return the object if a non-empty object");
test.same(inquire("./tests/data/array"), [ 1 ], "should return the module if a non-empty array");
test.end();
});
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+19
View File
@@ -0,0 +1,19 @@
@protobufjs/path
================
[![npm](https://img.shields.io/npm/v/@protobufjs/path.svg)](https://www.npmjs.com/package/@protobufjs/path)
A minimal path module to resolve Unix, Windows and URL paths alike.
API
---
* **path.isAbsolute(path: `string`): `boolean`**<br />
Tests if the specified path is absolute.
* **path.normalize(path: `string`): `string`**<br />
Normalizes the specified path.
* **path.resolve(originPath: `string`, includePath: `string`, [alreadyNormalized=false: `boolean`]): `string`**<br />
Resolves the specified include path against the specified origin path.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+22
View File
@@ -0,0 +1,22 @@
/**
* Tests if the specified path is absolute.
* @param {string} path Path to test
* @returns {boolean} `true` if path is absolute
*/
export function isAbsolute(path: string): boolean;
/**
* Normalizes the specified path.
* @param {string} path Path to normalize
* @returns {string} Normalized path
*/
export function normalize(path: string): string;
/**
* Resolves the specified include path against the specified origin path.
* @param {string} originPath Path to the origin file
* @param {string} includePath Include path relative to origin path
* @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized
* @returns {string} Path to the include file
*/
export function resolve(originPath: string, includePath: string, alreadyNormalized?: boolean): string;
+65
View File
@@ -0,0 +1,65 @@
"use strict";
/**
* A minimal path module to resolve Unix, Windows and URL paths alike.
* @memberof util
* @namespace
*/
var path = exports;
var isAbsolute =
/**
* Tests if the specified path is absolute.
* @param {string} path Path to test
* @returns {boolean} `true` if path is absolute
*/
path.isAbsolute = function isAbsolute(path) {
return /^(?:\/|\w+:)/.test(path);
};
var normalize =
/**
* Normalizes the specified path.
* @param {string} path Path to normalize
* @returns {string} Normalized path
*/
path.normalize = function normalize(path) {
path = path.replace(/\\/g, "/")
.replace(/\/{2,}/g, "/");
var parts = path.split("/"),
absolute = isAbsolute(path),
prefix = "";
if (absolute)
prefix = parts.shift() + "/";
for (var i = 0; i < parts.length;) {
if (parts[i] === "..") {
if (i > 0 && parts[i - 1] !== "..")
parts.splice(--i, 2);
else if (absolute)
parts.splice(i, 1);
else
++i;
} else if (parts[i] === ".")
parts.splice(i, 1);
else
++i;
}
return prefix + parts.join("/");
};
/**
* Resolves the specified include path against the specified origin path.
* @param {string} originPath Path to the origin file
* @param {string} includePath Include path relative to origin path
* @param {boolean} [alreadyNormalized=false] `true` if both paths are already known to be normalized
* @returns {string} Path to the include file
*/
path.resolve = function resolve(originPath, includePath, alreadyNormalized) {
if (!alreadyNormalized)
includePath = normalize(includePath);
if (isAbsolute(includePath))
return includePath;
if (!alreadyNormalized)
originPath = normalize(originPath);
return (originPath = originPath.replace(/(?:\/|^)[^/]+$/, "")).length ? normalize(originPath + "/" + includePath) : includePath;
};
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/path",
"description": "A minimal path module to resolve Unix, Windows and URL paths alike.",
"version": "1.1.2",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+60
View File
@@ -0,0 +1,60 @@
var tape = require("tape");
var path = require("..");
tape.test("path", function(test) {
test.ok(path.isAbsolute("X:\\some\\path\\file.js"), "should identify absolute windows paths");
test.ok(path.isAbsolute("/some/path/file.js"), "should identify absolute unix paths");
test.notOk(path.isAbsolute("some\\path\\file.js"), "should identify relative windows paths");
test.notOk(path.isAbsolute("some/path/file.js"), "should identify relative unix paths");
var paths = [
{
actual: "X:\\some\\..\\.\\path\\\\file.js",
normal: "X:/path/file.js",
resolve: {
origin: "X:/path/origin.js",
expected: "X:/path/file.js"
}
}, {
actual: "some\\..\\.\\path\\\\file.js",
normal: "path/file.js",
resolve: {
origin: "X:/path/origin.js",
expected: "X:/path/path/file.js"
}
}, {
actual: "/some/.././path//file.js",
normal: "/path/file.js",
resolve: {
origin: "/path/origin.js",
expected: "/path/file.js"
}
}, {
actual: "some/.././path//file.js",
normal: "path/file.js",
resolve: {
origin: "",
expected: "path/file.js"
}
}, {
actual: ".././path//file.js",
normal: "../path/file.js"
}, {
actual: "/.././path//file.js",
normal: "/path/file.js"
}
];
paths.forEach(function(p) {
test.equal(path.normalize(p.actual), p.normal, "should normalize " + p.actual);
if (p.resolve) {
test.equal(path.resolve(p.resolve.origin, p.actual), p.resolve.expected, "should resolve " + p.actual);
test.equal(path.resolve(p.resolve.origin, p.normal, true), p.resolve.expected, "should resolve " + p.normal + " (already normalized)");
}
});
test.end();
});
+3
View File
@@ -0,0 +1,3 @@
npm-debug.*
node_modules/
coverage/
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+13
View File
@@ -0,0 +1,13 @@
@protobufjs/pool
================
[![npm](https://img.shields.io/npm/v/@protobufjs/pool.svg)](https://www.npmjs.com/package/@protobufjs/pool)
A general purpose buffer pool.
API
---
* **pool(alloc: `function(size: number): Uint8Array`, slice: `function(this: Uint8Array, start: number, end: number): Uint8Array`, [size=8192: `number`]): `function(size: number): Uint8Array`**<br />
Creates a pooled allocator.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+32
View File
@@ -0,0 +1,32 @@
export = pool;
/**
* An allocator as used by {@link util.pool}.
* @typedef PoolAllocator
* @type {function}
* @param {number} size Buffer size
* @returns {Uint8Array} Buffer
*/
type PoolAllocator = (size: number) => Uint8Array;
/**
* A slicer as used by {@link util.pool}.
* @typedef PoolSlicer
* @type {function}
* @param {number} start Start offset
* @param {number} end End offset
* @returns {Uint8Array} Buffer slice
* @this {Uint8Array}
*/
type PoolSlicer = (this: Uint8Array, start: number, end: number) => Uint8Array;
/**
* A general purpose buffer pool.
* @memberof util
* @function
* @param {PoolAllocator} alloc Allocator
* @param {PoolSlicer} slice Slicer
* @param {number} [size=8192] Slab size
* @returns {PoolAllocator} Pooled allocator
*/
declare function pool(alloc: PoolAllocator, slice: PoolSlicer, size?: number): PoolAllocator;
+48
View File
@@ -0,0 +1,48 @@
"use strict";
module.exports = pool;
/**
* An allocator as used by {@link util.pool}.
* @typedef PoolAllocator
* @type {function}
* @param {number} size Buffer size
* @returns {Uint8Array} Buffer
*/
/**
* A slicer as used by {@link util.pool}.
* @typedef PoolSlicer
* @type {function}
* @param {number} start Start offset
* @param {number} end End offset
* @returns {Uint8Array} Buffer slice
* @this {Uint8Array}
*/
/**
* A general purpose buffer pool.
* @memberof util
* @function
* @param {PoolAllocator} alloc Allocator
* @param {PoolSlicer} slice Slicer
* @param {number} [size=8192] Slab size
* @returns {PoolAllocator} Pooled allocator
*/
function pool(alloc, slice, size) {
var SIZE = size || 8192;
var MAX = SIZE >>> 1;
var slab = null;
var offset = SIZE;
return function pool_alloc(size) {
if (size < 1 || size > MAX)
return alloc(size);
if (offset + size > SIZE) {
slab = alloc(SIZE);
offset = 0;
}
var buf = slice.call(slab, offset, offset += size);
if (offset & 7) // align to 32 bit
offset = (offset | 7) + 1;
return buf;
};
}
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/pool",
"description": "A general purpose buffer pool.",
"version": "1.1.0",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+33
View File
@@ -0,0 +1,33 @@
var tape = require("tape");
var pool = require("..");
if (typeof Uint8Array !== "undefined")
tape.test("pool", function(test) {
var alloc = pool(function(size) { return new Uint8Array(size); }, Uint8Array.prototype.subarray);
var buf1 = alloc(0);
test.equal(buf1.length, 0, "should allocate a buffer of size 0");
var buf2 = alloc(1);
test.equal(buf2.length, 1, "should allocate a buffer of size 1 (initializes slab)");
test.notEqual(buf2.buffer, buf1.buffer, "should not reference the same backing buffer if previous buffer had size 0");
test.equal(buf2.byteOffset, 0, "should allocate at byteOffset 0 when using a new slab");
buf1 = alloc(1);
test.equal(buf1.buffer, buf2.buffer, "should reference the same backing buffer when allocating a chunk fitting into the slab");
test.equal(buf1.byteOffset, 8, "should align slices to 32 bit and this allocate at byteOffset 8");
var buf3 = alloc(4097);
test.notEqual(buf3.buffer, buf2.buffer, "should not reference the same backing buffer when allocating a buffer larger than half the backing buffer's size");
buf2 = alloc(4096);
test.equal(buf2.buffer, buf1.buffer, "should reference the same backing buffer when allocating a buffer smaller or equal than half the backing buffer's size");
buf1 = alloc(4096);
test.notEqual(buf1.buffer, buf2.buffer, "should not reference the same backing buffer when the slab is exhausted (initializes new slab)");
test.end();
});
+3
View File
@@ -0,0 +1,3 @@
npm-debug.*
node_modules/
coverage/
+26
View File
@@ -0,0 +1,26 @@
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of its author, nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+20
View File
@@ -0,0 +1,20 @@
@protobufjs/utf8
================
[![npm](https://img.shields.io/npm/v/@protobufjs/utf8.svg)](https://www.npmjs.com/package/@protobufjs/utf8)
A minimal UTF8 implementation for number arrays.
API
---
* **utf8.length(string: `string`): `number`**<br />
Calculates the UTF8 byte length of a string.
* **utf8.read(buffer: `Uint8Array`, start: `number`, end: `number`): `string`**<br />
Reads UTF8 bytes as a string.
* **utf8.write(string: `string`, buffer: `Uint8Array`, offset: `number`): `number`**<br />
Writes a string as UTF8 bytes.
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
+24
View File
@@ -0,0 +1,24 @@
/**
* Calculates the UTF8 byte length of a string.
* @param {string} string String
* @returns {number} Byte length
*/
export function length(string: string): number;
/**
* Reads UTF8 bytes as a string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} String read
*/
export function read(buffer: Uint8Array, start: number, end: number): string;
/**
* Writes a string as UTF8 bytes.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Bytes written
*/
export function write(string: string, buffer: Uint8Array, offset: number): number;
+105
View File
@@ -0,0 +1,105 @@
"use strict";
/**
* A minimal UTF8 implementation for number arrays.
* @memberof util
* @namespace
*/
var utf8 = exports;
/**
* Calculates the UTF8 byte length of a string.
* @param {string} string String
* @returns {number} Byte length
*/
utf8.length = function utf8_length(string) {
var len = 0,
c = 0;
for (var i = 0; i < string.length; ++i) {
c = string.charCodeAt(i);
if (c < 128)
len += 1;
else if (c < 2048)
len += 2;
else if ((c & 0xFC00) === 0xD800 && (string.charCodeAt(i + 1) & 0xFC00) === 0xDC00) {
++i;
len += 4;
} else
len += 3;
}
return len;
};
/**
* Reads UTF8 bytes as a string.
* @param {Uint8Array} buffer Source buffer
* @param {number} start Source start
* @param {number} end Source end
* @returns {string} String read
*/
utf8.read = function utf8_read(buffer, start, end) {
var len = end - start;
if (len < 1)
return "";
var parts = null,
chunk = [],
i = 0, // char offset
t; // temporary
while (start < end) {
t = buffer[start++];
if (t < 128)
chunk[i++] = t;
else if (t > 191 && t < 224)
chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
else if (t > 239 && t < 365) {
t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000;
chunk[i++] = 0xD800 + (t >> 10);
chunk[i++] = 0xDC00 + (t & 1023);
} else
chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
};
/**
* Writes a string as UTF8 bytes.
* @param {string} string Source string
* @param {Uint8Array} buffer Destination buffer
* @param {number} offset Destination offset
* @returns {number} Bytes written
*/
utf8.write = function utf8_write(string, buffer, offset) {
var start = offset,
c1, // character 1
c2; // character 2
for (var i = 0; i < string.length; ++i) {
c1 = string.charCodeAt(i);
if (c1 < 128) {
buffer[offset++] = c1;
} else if (c1 < 2048) {
buffer[offset++] = c1 >> 6 | 192;
buffer[offset++] = c1 & 63 | 128;
} else if ((c1 & 0xFC00) === 0xD800 && ((c2 = string.charCodeAt(i + 1)) & 0xFC00) === 0xDC00) {
c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF);
++i;
buffer[offset++] = c1 >> 18 | 240;
buffer[offset++] = c1 >> 12 & 63 | 128;
buffer[offset++] = c1 >> 6 & 63 | 128;
buffer[offset++] = c1 & 63 | 128;
} else {
buffer[offset++] = c1 >> 12 | 224;
buffer[offset++] = c1 >> 6 & 63 | 128;
buffer[offset++] = c1 & 63 | 128;
}
}
return offset - start;
};
+21
View File
@@ -0,0 +1,21 @@
{
"name": "@protobufjs/utf8",
"description": "A minimal UTF8 implementation for number arrays.",
"version": "1.1.0",
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>",
"repository": {
"type": "git",
"url": "https://github.com/dcodeIO/protobuf.js.git"
},
"license": "BSD-3-Clause",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"istanbul": "^0.4.5",
"tape": "^4.6.3"
},
"scripts": {
"test": "tape tests/*.js",
"coverage": "istanbul cover node_modules/tape/bin/tape tests/*.js"
}
}
+216
View File
@@ -0,0 +1,216 @@
UTF-8 encoded sample plain-text file
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25 CC BY
The ASCII compatible UTF-8 encoding used in this plain-text file
is defined in Unicode, ISO 10646-1, and RFC 2279.
Using Unicode/UTF-8, you can write in emails and source code things such as
Mathematics and sciences:
∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
⎪⎢⎜│a²+b³ ⎟⎥⎪
∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪
⎪⎢⎜⎷ c₈ ⎟⎥⎪
ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬
⎪⎢⎜ ∞ ⎟⎥⎪
⊥ < a ≠ b ≡ c ≤ d ≪ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪
⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭
Linguistics and dictionaries:
ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
APL:
((VV)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
Nicer typography in plain text files:
╔══════════════════════════════════════════╗
║ ║
║ • single and “double” quotes ║
║ ║
║ • Curly apostrophes: “Weve been here” ║
║ ║
║ • Latin-1 apostrophe and accents: '´` ║
║ ║
║ • deutsche „Anführungszeichen“ ║
║ ║
║ • †, ‡, ‰, •, 34, —, 5/+5, ™, … ║
║ ║
║ • ASCII safety test: 1lI|, 0OD, 8B ║
║ ╭─────────╮ ║
║ • the euro symbol: │ 14.95 € │ ║
║ ╰─────────╯ ║
╚══════════════════════════════════════════╝
Combining characters:
STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
Greek (in Polytonic):
The Greek anthem:
Σὲ γνωρίζω ἀπὸ τὴν κόψη
τοῦ σπαθιοῦ τὴν τρομερή,
σὲ γνωρίζω ἀπὸ τὴν ὄψη
ποὺ μὲ βία μετράει τὴ γῆ.
᾿Απ᾿ τὰ κόκκαλα βγαλμένη
τῶν ῾Ελλήνων τὰ ἱερά
καὶ σὰν πρῶτα ἀνδρειωμένη
χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
From a speech of Demosthenes in the 4th century BC:
Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
Georgian:
From a Unicode conference invitation:
გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
Russian:
From a Unicode conference invitation:
Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
Конференция соберет широкий круг экспертов по вопросам глобального
Интернета и Unicode, локализации и интернационализации, воплощению и
применению Unicode в различных операционных системах и программных
приложениях, шрифтах, верстке и многоязычных компьютерных системах.
Thai (UCS Level 2):
Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
classic 'San Gua'):
[----------------------------|------------------------]
๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
(The above is a two-column text. If combining characters are handled
correctly, the lines of the second column should be aligned with the
| character above.)
Ethiopian:
Proverbs in the Amharic language:
ሰማይ አይታረስ ንጉሥ አይከሰስ።
ብላ ካለኝ እንደአባቴ በቆመጠኝ።
ጌጥ ያለቤቱ ቁምጥና ነው።
ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
የአፍ ወለምታ በቅቤ አይታሽም።
አይጥ በበላ ዳዋ ተመታ።
ሲተረጉሙ ይደረግሙ።
ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
ድር ቢያብር አንበሳ ያስር።
ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
ሥራ ከመፍታት ልጄን ላፋታት።
ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
ተንጋሎ ቢተፉ ተመልሶ ባፉ።
ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
እግርህን በፍራሽህ ልክ ዘርጋ።
Runes:
ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
(Old English, which transcribed into Latin reads 'He cwaeth that he
bude thaem lande northweardum with tha Westsae.' and means 'He said
that he lived in the northern land near the Western Sea.')
Braille:
⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
(The first couple of paragraphs of "A Christmas Carol" by Dickens)
Compact font selection example text:
ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
–—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi⑀₂ἠḂӥẄɐː⍎אԱა
Greetings in various languages:
Hello world, Καλημέρα κόσμε, コンニチハ
Box drawing alignment tests: █
╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
▝▀▘▙▄▟
Surrogates:
𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕 𠴕 𠵼 𠵿 𠸎 𠸏 𠹷 𠺝 𠺢 𠻗 𠻹 𠻺 𠼭 𠼮 𠽌 𠾴 𠾼 𠿪 𡁜 𡁯 𡁵 𡁶 𡁻 𡃁
𡃉 𡇙 𢃇 𢞵 𢫕 𢭃 𢯊 𢱑 𢱕 𢳂 𢴈 𢵌 𢵧 𢺳 𣲷 𤓓 𤶸 𤷪 𥄫 𦉘 𦟌 𦧲 𦧺 𧨾 𨅝 𨈇 𨋢 𨳊 𨳍 𨳒 𩶘
+57
View File
@@ -0,0 +1,57 @@
var tape = require("tape");
var utf8 = require("..");
var data = require("fs").readFileSync(require.resolve("./data/utf8.txt")),
dataStr = data.toString("utf8");
tape.test("utf8", function(test) {
test.test(test.name + " - length", function(test) {
test.equal(utf8.length(""), 0, "should return a byte length of zero for an empty string");
test.equal(utf8.length(dataStr), Buffer.byteLength(dataStr), "should return the same byte length as node buffers");
test.end();
});
test.test(test.name + " - read", function(test) {
var comp = utf8.read([], 0, 0);
test.equal(comp, "", "should decode an empty buffer to an empty string");
comp = utf8.read(data, 0, data.length);
test.equal(comp, data.toString("utf8"), "should decode to the same byte data as node buffers");
var longData = Buffer.concat([data, data, data, data]);
comp = utf8.read(longData, 0, longData.length);
test.equal(comp, longData.toString("utf8"), "should decode to the same byte data as node buffers (long)");
var chunkData = new Buffer(data.toString("utf8").substring(0, 8192));
comp = utf8.read(chunkData, 0, chunkData.length);
test.equal(comp, chunkData.toString("utf8"), "should decode to the same byte data as node buffers (chunk size)");
test.end();
});
test.test(test.name + " - write", function(test) {
var buf = new Buffer(0);
test.equal(utf8.write("", buf, 0), 0, "should encode an empty string to an empty buffer");
var len = utf8.length(dataStr);
buf = new Buffer(len);
test.equal(utf8.write(dataStr, buf, 0), len, "should encode to exactly " + len + " bytes");
test.equal(buf.length, data.length, "should encode to a buffer length equal to that of node buffers");
for (var i = 0; i < buf.length; ++i) {
if (buf[i] !== data[i]) {
test.fail("should encode to the same buffer data as node buffers (offset " + i + ")");
return;
}
}
test.pass("should encode to the same buffer data as node buffers");
test.end();
});
});
Generated Vendored Executable
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
Generated Vendored Executable
+16
View File
@@ -0,0 +1,16 @@
# Installation
> `npm install --save @types/long`
# Summary
This package contains type definitions for long.js (https://github.com/dcodeIO/long.js).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/long.
### Additional Details
* Last updated: Tue, 26 Apr 2022 19:31:52 GMT
* Dependencies: none
* Global values: `Long`
# Credits
These definitions were written by [Peter Kooijmans](https://github.com/peterkooijmans).
Generated Vendored Executable
+389
View File
@@ -0,0 +1,389 @@
// Type definitions for long.js 4.0.0
// Project: https://github.com/dcodeIO/long.js
// Definitions by: Peter Kooijmans <https://github.com/peterkooijmans>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// Definitions by: Denis Cappellin <https://github.com/cappellin>
export = Long;
export as namespace Long;
declare const Long: Long.LongConstructor;
type Long = Long.Long;
declare namespace Long {
interface LongConstructor {
/**
* Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as signed integers. See the from* functions below for more convenient ways of constructing Longs.
*/
new( low: number, high?: number, unsigned?: boolean ): Long;
prototype: Long;
/**
* Maximum unsigned value.
*/
MAX_UNSIGNED_VALUE: Long;
/**
* Maximum signed value.
*/
MAX_VALUE: Long;
/**
* Minimum signed value.
*/
MIN_VALUE: Long;
/**
* Signed negative one.
*/
NEG_ONE: Long;
/**
* Signed one.
*/
ONE: Long;
/**
* Unsigned one.
*/
UONE: Long;
/**
* Unsigned zero.
*/
UZERO: Long;
/**
* Signed zero
*/
ZERO: Long;
/**
* Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is assumed to use 32 bits.
*/
fromBits( lowBits:number, highBits:number, unsigned?:boolean ): Long;
/**
* Returns a Long representing the given 32 bit integer value.
*/
fromInt( value: number, unsigned?: boolean ): Long;
/**
* Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
*/
fromNumber( value: number, unsigned?: boolean ): Long;
/**
* Returns a Long representation of the given string, written using the specified radix.
*/
fromString( str: string, unsigned?: boolean | number, radix?: number ): Long;
/**
* Creates a Long from its byte representation.
*/
fromBytes( bytes: number[], unsigned?: boolean, le?: boolean ): Long;
/**
* Creates a Long from its little endian byte representation.
*/
fromBytesLE( bytes: number[], unsigned?: boolean ): Long;
/**
* Creates a Long from its little endian byte representation.
*/
fromBytesBE( bytes: number[], unsigned?: boolean ): Long;
/**
* Tests if the specified object is a Long.
*/
isLong( obj: any ): obj is Long;
/**
* Converts the specified value to a Long.
*/
fromValue( val: Long | number | string | {low: number, high: number, unsigned: boolean}, unsigned?: boolean ): Long;
}
interface Long
{
/**
* The high 32 bits as a signed value.
*/
high: number;
/**
* The low 32 bits as a signed value.
*/
low: number;
/**
* Whether unsigned or not.
*/
unsigned: boolean;
/**
* Returns the sum of this and the specified Long.
*/
add( addend: number | Long | string ): Long;
/**
* Returns the bitwise AND of this Long and the specified.
*/
and( other: Long | number | string ): Long;
/**
* Compares this Long's value with the specified's.
*/
compare( other: Long | number | string ): number;
/**
* Compares this Long's value with the specified's.
*/
comp( other: Long | number | string ): number;
/**
* Returns this Long divided by the specified.
*/
divide( divisor: Long | number | string ): Long;
/**
* Returns this Long divided by the specified.
*/
div( divisor: Long | number | string ): Long;
/**
* Tests if this Long's value equals the specified's.
*/
equals( other: Long | number | string ): boolean;
/**
* Tests if this Long's value equals the specified's.
*/
eq( other: Long | number | string ): boolean;
/**
* Gets the high 32 bits as a signed integer.
*/
getHighBits(): number;
/**
* Gets the high 32 bits as an unsigned integer.
*/
getHighBitsUnsigned(): number;
/**
* Gets the low 32 bits as a signed integer.
*/
getLowBits(): number;
/**
* Gets the low 32 bits as an unsigned integer.
*/
getLowBitsUnsigned(): number;
/**
* Gets the number of bits needed to represent the absolute value of this Long.
*/
getNumBitsAbs(): number;
/**
* Tests if this Long's value is greater than the specified's.
*/
greaterThan( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is greater than the specified's.
*/
gt( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is greater than or equal the specified's.
*/
greaterThanOrEqual( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is greater than or equal the specified's.
*/
gte( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is even.
*/
isEven(): boolean;
/**
* Tests if this Long's value is negative.
*/
isNegative(): boolean;
/**
* Tests if this Long's value is odd.
*/
isOdd(): boolean;
/**
* Tests if this Long's value is positive.
*/
isPositive(): boolean;
/**
* Tests if this Long's value equals zero.
*/
isZero(): boolean;
/**
* Tests if this Long's value is less than the specified's.
*/
lessThan( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is less than the specified's.
*/
lt( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is less than or equal the specified's.
*/
lessThanOrEqual( other: Long | number | string ): boolean;
/**
* Tests if this Long's value is less than or equal the specified's.
*/
lte( other: Long | number | string ): boolean;
/**
* Returns this Long modulo the specified.
*/
modulo( other: Long | number | string ): Long;
/**
* Returns this Long modulo the specified.
*/
mod( other: Long | number | string ): Long;
/**
* Returns the product of this and the specified Long.
*/
multiply( multiplier: Long | number | string ): Long;
/**
* Returns the product of this and the specified Long.
*/
mul( multiplier: Long | number | string ): Long;
/**
* Negates this Long's value.
*/
negate(): Long;
/**
* Negates this Long's value.
*/
neg(): Long;
/**
* Returns the bitwise NOT of this Long.
*/
not(): Long;
/**
* Tests if this Long's value differs from the specified's.
*/
notEquals( other: Long | number | string ): boolean;
/**
* Tests if this Long's value differs from the specified's.
*/
neq( other: Long | number | string ): boolean;
/**
* Returns the bitwise OR of this Long and the specified.
*/
or( other: Long | number | string ): Long;
/**
* Returns this Long with bits shifted to the left by the given amount.
*/
shiftLeft( numBits: number | Long ): Long;
/**
* Returns this Long with bits shifted to the left by the given amount.
*/
shl( numBits: number | Long ): Long;
/**
* Returns this Long with bits arithmetically shifted to the right by the given amount.
*/
shiftRight( numBits: number | Long ): Long;
/**
* Returns this Long with bits arithmetically shifted to the right by the given amount.
*/
shr( numBits: number | Long ): Long;
/**
* Returns this Long with bits logically shifted to the right by the given amount.
*/
shiftRightUnsigned( numBits: number | Long ): Long;
/**
* Returns this Long with bits logically shifted to the right by the given amount.
*/
shru( numBits: number | Long ): Long;
/**
* Returns the difference of this and the specified Long.
*/
subtract( subtrahend: number | Long | string ): Long;
/**
* Returns the difference of this and the specified Long.
*/
sub( subtrahend: number | Long |string ): Long;
/**
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
*/
toInt(): number;
/**
* Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
*/
toNumber(): number;
/**
* Converts this Long to its byte representation.
*/
toBytes( le?: boolean ): number[];
/**
* Converts this Long to its little endian byte representation.
*/
toBytesLE(): number[];
/**
* Converts this Long to its big endian byte representation.
*/
toBytesBE(): number[];
/**
* Converts this Long to signed.
*/
toSigned(): Long;
/**
* Converts the Long to a string written in the specified radix.
*/
toString( radix?: number ): string;
/**
* Converts this Long to unsigned.
*/
toUnsigned(): Long;
/**
* Returns the bitwise XOR of this Long and the given one.
*/
xor( other: Long | number | string ): Long;
}
}
Generated Vendored Executable
+25
View File
@@ -0,0 +1,25 @@
{
"name": "@types/long",
"version": "4.0.2",
"description": "TypeScript definitions for long.js",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/long",
"license": "MIT",
"contributors": [
{
"name": "Peter Kooijmans",
"url": "https://github.com/peterkooijmans",
"githubUsername": "peterkooijmans"
}
],
"main": "",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/long"
},
"scripts": {},
"dependencies": {},
"typesPublisherContentHash": "ce51a9fcaeb3f15cee5396e1c4f4b5ca2986a066f9bbe885a51dcdc6dbb22fd5",
"typeScriptVersion": "3.9"
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
+15
View File
@@ -0,0 +1,15 @@
# Installation
> `npm install --save @types/node`
# Summary
This package contains type definitions for node (https://nodejs.org/).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node.
### Additional Details
* Last updated: Tue, 15 Jul 2025 07:04:18 GMT
* Dependencies: [undici-types](https://npmjs.com/package/undici-types)
# Credits
These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [David Junger](https://github.com/touffy), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Sebastian Silbermann](https://github.com/eps1lon), [Wilco Bakker](https://github.com/WilcoBakker), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), [Dmitry Semigradsky](https://github.com/Semigradsky), [René](https://github.com/Renegade334), and [Yagiz Nizipli](https://github.com/anonrig).
+1056
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
declare module "assert/strict" {
import { strict } from "node:assert";
export = strict;
}
declare module "node:assert/strict" {
import { strict } from "node:assert";
export = strict;
}
+623
View File
@@ -0,0 +1,623 @@
/**
* We strongly discourage the use of the `async_hooks` API.
* Other APIs that can cover most of its use cases include:
*
* * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v24.x/api/async_context.html#class-asynclocalstorage) tracks async context
* * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v24.x/api/process.html#processgetactiveresourcesinfo) tracks active resources
*
* The `node:async_hooks` module provides an API to track asynchronous resources.
* It can be accessed using:
*
* ```js
* import async_hooks from 'node:async_hooks';
* ```
* @experimental
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/async_hooks.js)
*/
declare module "async_hooks" {
/**
* ```js
* import { executionAsyncId } from 'node:async_hooks';
* import fs from 'node:fs';
*
* console.log(executionAsyncId()); // 1 - bootstrap
* const path = '.';
* fs.open(path, 'r', (err, fd) => {
* console.log(executionAsyncId()); // 6 - open()
* });
* ```
*
* The ID returned from `executionAsyncId()` is related to execution timing, not
* causality (which is covered by `triggerAsyncId()`):
*
* ```js
* const server = net.createServer((conn) => {
* // Returns the ID of the server, not of the new connection, because the
* // callback runs in the execution scope of the server's MakeCallback().
* async_hooks.executionAsyncId();
*
* }).listen(port, () => {
* // Returns the ID of a TickObject (process.nextTick()) because all
* // callbacks passed to .listen() are wrapped in a nextTick().
* async_hooks.executionAsyncId();
* });
* ```
*
* Promise contexts may not get precise `executionAsyncIds` by default.
* See the section on [promise execution tracking](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html#promise-execution-tracking).
* @since v8.1.0
* @return The `asyncId` of the current execution context. Useful to track when something calls.
*/
function executionAsyncId(): number;
/**
* Resource objects returned by `executionAsyncResource()` are most often internal
* Node.js handle objects with undocumented APIs. Using any functions or properties
* on the object is likely to crash your application and should be avoided.
*
* Using `executionAsyncResource()` in the top-level execution context will
* return an empty object as there is no handle or request object to use,
* but having an object representing the top-level can be helpful.
*
* ```js
* import { open } from 'node:fs';
* import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';
*
* console.log(executionAsyncId(), executionAsyncResource()); // 1 {}
* open(new URL(import.meta.url), 'r', (err, fd) => {
* console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap
* });
* ```
*
* This can be used to implement continuation local storage without the
* use of a tracking `Map` to store the metadata:
*
* ```js
* import { createServer } from 'node:http';
* import {
* executionAsyncId,
* executionAsyncResource,
* createHook,
* } from 'node:async_hooks';
* const sym = Symbol('state'); // Private symbol to avoid pollution
*
* createHook({
* init(asyncId, type, triggerAsyncId, resource) {
* const cr = executionAsyncResource();
* if (cr) {
* resource[sym] = cr[sym];
* }
* },
* }).enable();
*
* const server = createServer((req, res) => {
* executionAsyncResource()[sym] = { state: req.url };
* setTimeout(function() {
* res.end(JSON.stringify(executionAsyncResource()[sym]));
* }, 100);
* }).listen(3000);
* ```
* @since v13.9.0, v12.17.0
* @return The resource representing the current execution. Useful to store data within the resource.
*/
function executionAsyncResource(): object;
/**
* ```js
* const server = net.createServer((conn) => {
* // The resource that caused (or triggered) this callback to be called
* // was that of the new connection. Thus the return value of triggerAsyncId()
* // is the asyncId of "conn".
* async_hooks.triggerAsyncId();
*
* }).listen(port, () => {
* // Even though all callbacks passed to .listen() are wrapped in a nextTick()
* // the callback itself exists because the call to the server's .listen()
* // was made. So the return value would be the ID of the server.
* async_hooks.triggerAsyncId();
* });
* ```
*
* Promise contexts may not get valid `triggerAsyncId`s by default. See
* the section on [promise execution tracking](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html#promise-execution-tracking).
* @return The ID of the resource responsible for calling the callback that is currently being executed.
*/
function triggerAsyncId(): number;
interface HookCallbacks {
/**
* Called when a class is constructed that has the possibility to emit an asynchronous event.
* @param asyncId A unique ID for the async resource
* @param type The type of the async resource
* @param triggerAsyncId The unique ID of the async resource in whose execution context this async resource was created
* @param resource Reference to the resource representing the async operation, needs to be released during destroy
*/
init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void;
/**
* When an asynchronous operation is initiated or completes a callback is called to notify the user.
* The before callback is called just before said callback is executed.
* @param asyncId the unique identifier assigned to the resource about to execute the callback.
*/
before?(asyncId: number): void;
/**
* Called immediately after the callback specified in `before` is completed.
*
* If an uncaught exception occurs during execution of the callback, then `after` will run after the `'uncaughtException'` event is emitted or a `domain`'s handler runs.
* @param asyncId the unique identifier assigned to the resource which has executed the callback.
*/
after?(asyncId: number): void;
/**
* Called when a promise has resolve() called. This may not be in the same execution id
* as the promise itself.
* @param asyncId the unique id for the promise that was resolve()d.
*/
promiseResolve?(asyncId: number): void;
/**
* Called after the resource corresponding to asyncId is destroyed
* @param asyncId a unique ID for the async resource
*/
destroy?(asyncId: number): void;
}
interface AsyncHook {
/**
* Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
*/
enable(): this;
/**
* Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
*/
disable(): this;
}
/**
* Registers functions to be called for different lifetime events of each async
* operation.
*
* The callbacks `init()`/`before()`/`after()`/`destroy()` are called for the
* respective asynchronous event during a resource's lifetime.
*
* All callbacks are optional. For example, if only resource cleanup needs to
* be tracked, then only the `destroy` callback needs to be passed. The
* specifics of all functions that can be passed to `callbacks` is in the `Hook Callbacks` section.
*
* ```js
* import { createHook } from 'node:async_hooks';
*
* const asyncHook = createHook({
* init(asyncId, type, triggerAsyncId, resource) { },
* destroy(asyncId) { },
* });
* ```
*
* The callbacks will be inherited via the prototype chain:
*
* ```js
* class MyAsyncCallbacks {
* init(asyncId, type, triggerAsyncId, resource) { }
* destroy(asyncId) {}
* }
*
* class MyAddedCallbacks extends MyAsyncCallbacks {
* before(asyncId) { }
* after(asyncId) { }
* }
*
* const asyncHook = async_hooks.createHook(new MyAddedCallbacks());
* ```
*
* Because promises are asynchronous resources whose lifecycle is tracked
* via the async hooks mechanism, the `init()`, `before()`, `after()`, and`destroy()` callbacks _must not_ be async functions that return promises.
* @since v8.1.0
* @param callbacks The `Hook Callbacks` to register
* @return Instance used for disabling and enabling hooks
*/
function createHook(callbacks: HookCallbacks): AsyncHook;
interface AsyncResourceOptions {
/**
* The ID of the execution context that created this async event.
* @default executionAsyncId()
*/
triggerAsyncId?: number | undefined;
/**
* Disables automatic `emitDestroy` when the object is garbage collected.
* This usually does not need to be set (even if `emitDestroy` is called
* manually), unless the resource's `asyncId` is retrieved and the
* sensitive API's `emitDestroy` is called with it.
* @default false
*/
requireManualDestroy?: boolean | undefined;
}
/**
* The class `AsyncResource` is designed to be extended by the embedder's async
* resources. Using this, users can easily trigger the lifetime events of their
* own resources.
*
* The `init` hook will trigger when an `AsyncResource` is instantiated.
*
* The following is an overview of the `AsyncResource` API.
*
* ```js
* import { AsyncResource, executionAsyncId } from 'node:async_hooks';
*
* // AsyncResource() is meant to be extended. Instantiating a
* // new AsyncResource() also triggers init. If triggerAsyncId is omitted then
* // async_hook.executionAsyncId() is used.
* const asyncResource = new AsyncResource(
* type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false },
* );
*
* // Run a function in the execution context of the resource. This will
* // * establish the context of the resource
* // * trigger the AsyncHooks before callbacks
* // * call the provided function `fn` with the supplied arguments
* // * trigger the AsyncHooks after callbacks
* // * restore the original execution context
* asyncResource.runInAsyncScope(fn, thisArg, ...args);
*
* // Call AsyncHooks destroy callbacks.
* asyncResource.emitDestroy();
*
* // Return the unique ID assigned to the AsyncResource instance.
* asyncResource.asyncId();
*
* // Return the trigger ID for the AsyncResource instance.
* asyncResource.triggerAsyncId();
* ```
*/
class AsyncResource {
/**
* AsyncResource() is meant to be extended. Instantiating a
* new AsyncResource() also triggers init. If triggerAsyncId is omitted then
* async_hook.executionAsyncId() is used.
* @param type The type of async event.
* @param triggerAsyncId The ID of the execution context that created
* this async event (default: `executionAsyncId()`), or an
* AsyncResourceOptions object (since v9.3.0)
*/
constructor(type: string, triggerAsyncId?: number | AsyncResourceOptions);
/**
* Binds the given function to the current execution context.
* @since v14.8.0, v12.19.0
* @param fn The function to bind to the current execution context.
* @param type An optional name to associate with the underlying `AsyncResource`.
*/
static bind<Func extends (this: ThisArg, ...args: any[]) => any, ThisArg>(
fn: Func,
type?: string,
thisArg?: ThisArg,
): Func;
/**
* Binds the given function to execute to this `AsyncResource`'s scope.
* @since v14.8.0, v12.19.0
* @param fn The function to bind to the current `AsyncResource`.
*/
bind<Func extends (...args: any[]) => any>(fn: Func): Func;
/**
* Call the provided function with the provided arguments in the execution context
* of the async resource. This will establish the context, trigger the AsyncHooks
* before callbacks, call the function, trigger the AsyncHooks after callbacks, and
* then restore the original execution context.
* @since v9.6.0
* @param fn The function to call in the execution context of this async resource.
* @param thisArg The receiver to be used for the function call.
* @param args Optional arguments to pass to the function.
*/
runInAsyncScope<This, Result>(
fn: (this: This, ...args: any[]) => Result,
thisArg?: This,
...args: any[]
): Result;
/**
* Call all `destroy` hooks. This should only ever be called once. An error will
* be thrown if it is called more than once. This **must** be manually called. If
* the resource is left to be collected by the GC then the `destroy` hooks will
* never be called.
* @return A reference to `asyncResource`.
*/
emitDestroy(): this;
/**
* @return The unique `asyncId` assigned to the resource.
*/
asyncId(): number;
/**
* @return The same `triggerAsyncId` that is passed to the `AsyncResource` constructor.
*/
triggerAsyncId(): number;
}
interface AsyncLocalStorageOptions {
/**
* The default value to be used when no store is provided.
*/
defaultValue?: any;
/**
* A name for the `AsyncLocalStorage` value.
*/
name?: string | undefined;
}
/**
* This class creates stores that stay coherent through asynchronous operations.
*
* While you can create your own implementation on top of the `node:async_hooks` module, `AsyncLocalStorage` should be preferred as it is a performant and memory
* safe implementation that involves significant optimizations that are non-obvious
* to implement.
*
* The following example uses `AsyncLocalStorage` to build a simple logger
* that assigns IDs to incoming HTTP requests and includes them in messages
* logged within each request.
*
* ```js
* import http from 'node:http';
* import { AsyncLocalStorage } from 'node:async_hooks';
*
* const asyncLocalStorage = new AsyncLocalStorage();
*
* function logWithId(msg) {
* const id = asyncLocalStorage.getStore();
* console.log(`${id !== undefined ? id : '-'}:`, msg);
* }
*
* let idSeq = 0;
* http.createServer((req, res) => {
* asyncLocalStorage.run(idSeq++, () => {
* logWithId('start');
* // Imagine any chain of async operations here
* setImmediate(() => {
* logWithId('finish');
* res.end();
* });
* });
* }).listen(8080);
*
* http.get('http://localhost:8080');
* http.get('http://localhost:8080');
* // Prints:
* // 0: start
* // 0: finish
* // 1: start
* // 1: finish
* ```
*
* Each instance of `AsyncLocalStorage` maintains an independent storage context.
* Multiple instances can safely exist simultaneously without risk of interfering
* with each other's data.
* @since v13.10.0, v12.17.0
*/
class AsyncLocalStorage<T> {
/**
* Creates a new instance of `AsyncLocalStorage`. Store is only provided within a
* `run()` call or after an `enterWith()` call.
*/
constructor(options?: AsyncLocalStorageOptions);
/**
* Binds the given function to the current execution context.
* @since v19.8.0
* @param fn The function to bind to the current execution context.
* @return A new function that calls `fn` within the captured execution context.
*/
static bind<Func extends (...args: any[]) => any>(fn: Func): Func;
/**
* Captures the current execution context and returns a function that accepts a
* function as an argument. Whenever the returned function is called, it
* calls the function passed to it within the captured context.
*
* ```js
* const asyncLocalStorage = new AsyncLocalStorage();
* const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot());
* const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore()));
* console.log(result); // returns 123
* ```
*
* AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple
* async context tracking purposes, for example:
*
* ```js
* class Foo {
* #runInAsyncScope = AsyncLocalStorage.snapshot();
*
* get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); }
* }
*
* const foo = asyncLocalStorage.run(123, () => new Foo());
* console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123
* ```
* @since v19.8.0
* @return A new function with the signature `(fn: (...args) : R, ...args) : R`.
*/
static snapshot(): <R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs) => R;
/**
* Disables the instance of `AsyncLocalStorage`. All subsequent calls
* to `asyncLocalStorage.getStore()` will return `undefined` until `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()` is called again.
*
* When calling `asyncLocalStorage.disable()`, all current contexts linked to the
* instance will be exited.
*
* Calling `asyncLocalStorage.disable()` is required before the `asyncLocalStorage` can be garbage collected. This does not apply to stores
* provided by the `asyncLocalStorage`, as those objects are garbage collected
* along with the corresponding async resources.
*
* Use this method when the `asyncLocalStorage` is not in use anymore
* in the current process.
* @since v13.10.0, v12.17.0
* @experimental
*/
disable(): void;
/**
* Returns the current store.
* If called outside of an asynchronous context initialized by
* calling `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()`, it
* returns `undefined`.
* @since v13.10.0, v12.17.0
*/
getStore(): T | undefined;
/**
* The name of the `AsyncLocalStorage` instance if provided.
* @since v24.0.0
*/
readonly name: string;
/**
* Runs a function synchronously within a context and returns its
* return value. The store is not accessible outside of the callback function.
* The store is accessible to any asynchronous operations created within the
* callback.
*
* The optional `args` are passed to the callback function.
*
* If the callback function throws an error, the error is thrown by `run()` too.
* The stacktrace is not impacted by this call and the context is exited.
*
* Example:
*
* ```js
* const store = { id: 2 };
* try {
* asyncLocalStorage.run(store, () => {
* asyncLocalStorage.getStore(); // Returns the store object
* setTimeout(() => {
* asyncLocalStorage.getStore(); // Returns the store object
* }, 200);
* throw new Error();
* });
* } catch (e) {
* asyncLocalStorage.getStore(); // Returns undefined
* // The error will be caught here
* }
* ```
* @since v13.10.0, v12.17.0
*/
run<R>(store: T, callback: () => R): R;
run<R, TArgs extends any[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R;
/**
* Runs a function synchronously outside of a context and returns its
* return value. The store is not accessible within the callback function or
* the asynchronous operations created within the callback. Any `getStore()` call done within the callback function will always return `undefined`.
*
* The optional `args` are passed to the callback function.
*
* If the callback function throws an error, the error is thrown by `exit()` too.
* The stacktrace is not impacted by this call and the context is re-entered.
*
* Example:
*
* ```js
* // Within a call to run
* try {
* asyncLocalStorage.getStore(); // Returns the store object or value
* asyncLocalStorage.exit(() => {
* asyncLocalStorage.getStore(); // Returns undefined
* throw new Error();
* });
* } catch (e) {
* asyncLocalStorage.getStore(); // Returns the same object or value
* // The error will be caught here
* }
* ```
* @since v13.10.0, v12.17.0
* @experimental
*/
exit<R, TArgs extends any[]>(callback: (...args: TArgs) => R, ...args: TArgs): R;
/**
* Transitions into the context for the remainder of the current
* synchronous execution and then persists the store through any following
* asynchronous calls.
*
* Example:
*
* ```js
* const store = { id: 1 };
* // Replaces previous store with the given store object
* asyncLocalStorage.enterWith(store);
* asyncLocalStorage.getStore(); // Returns the store object
* someAsyncOperation(() => {
* asyncLocalStorage.getStore(); // Returns the same object
* });
* ```
*
* This transition will continue for the _entire_ synchronous execution.
* This means that if, for example, the context is entered within an event
* handler subsequent event handlers will also run within that context unless
* specifically bound to another context with an `AsyncResource`. That is why `run()` should be preferred over `enterWith()` unless there are strong reasons
* to use the latter method.
*
* ```js
* const store = { id: 1 };
*
* emitter.on('my-event', () => {
* asyncLocalStorage.enterWith(store);
* });
* emitter.on('my-event', () => {
* asyncLocalStorage.getStore(); // Returns the same object
* });
*
* asyncLocalStorage.getStore(); // Returns undefined
* emitter.emit('my-event');
* asyncLocalStorage.getStore(); // Returns the same object
* ```
* @since v13.11.0, v12.17.0
* @experimental
*/
enterWith(store: T): void;
}
/**
* @since v17.2.0, v16.14.0
* @return A map of provider types to the corresponding numeric id.
* This map contains all the event types that might be emitted by the `async_hooks.init()` event.
*/
namespace asyncWrapProviders {
const NONE: number;
const DIRHANDLE: number;
const DNSCHANNEL: number;
const ELDHISTOGRAM: number;
const FILEHANDLE: number;
const FILEHANDLECLOSEREQ: number;
const FIXEDSIZEBLOBCOPY: number;
const FSEVENTWRAP: number;
const FSREQCALLBACK: number;
const FSREQPROMISE: number;
const GETADDRINFOREQWRAP: number;
const GETNAMEINFOREQWRAP: number;
const HEAPSNAPSHOT: number;
const HTTP2SESSION: number;
const HTTP2STREAM: number;
const HTTP2PING: number;
const HTTP2SETTINGS: number;
const HTTPINCOMINGMESSAGE: number;
const HTTPCLIENTREQUEST: number;
const JSSTREAM: number;
const JSUDPWRAP: number;
const MESSAGEPORT: number;
const PIPECONNECTWRAP: number;
const PIPESERVERWRAP: number;
const PIPEWRAP: number;
const PROCESSWRAP: number;
const PROMISE: number;
const QUERYWRAP: number;
const SHUTDOWNWRAP: number;
const SIGNALWRAP: number;
const STATWATCHER: number;
const STREAMPIPE: number;
const TCPCONNECTWRAP: number;
const TCPSERVERWRAP: number;
const TCPWRAP: number;
const TTYWRAP: number;
const UDPSENDWRAP: number;
const UDPWRAP: number;
const SIGINTWATCHDOG: number;
const WORKER: number;
const WORKERHEAPSNAPSHOT: number;
const WRITEWRAP: number;
const ZLIB: number;
const CHECKPRIMEREQUEST: number;
const PBKDF2REQUEST: number;
const KEYPAIRGENREQUEST: number;
const KEYGENREQUEST: number;
const KEYEXPORTREQUEST: number;
const CIPHERREQUEST: number;
const DERIVEBITSREQUEST: number;
const HASHREQUEST: number;
const RANDOMBYTESREQUEST: number;
const RANDOMPRIMEREQUEST: number;
const SCRYPTREQUEST: number;
const SIGNREQUEST: number;
const TLSWRAP: number;
const VERIFYREQUEST: number;
}
}
declare module "node:async_hooks" {
export * from "async_hooks";
}

Some files were not shown because too many files have changed in this diff Show More