{
    "!name": "ecmascript",
    "!stdProto": {
        "Object": {
            "toString": "fn() -> string",
            "toLocaleString": "fn() -> string",
            "valueOf": "fn() -> number",
            "hasOwnProperty": "fn(prop: string) -> bool",
            "propertyIsEnumerable": "fn(prop: string) -> bool",
            "isPrototypeOf": "fn(obj: ?) -> bool"
        },
        "Function": {
            "apply": "fn(this: ?, args: [?])",
            "call": "fn(this: ?, args?: ?) -> !this.!ret",
            "bind": "fn(this: ?, args?: ?) -> !custom:Function_bind"
        },
        "Array":{
            "length": "number",
            "concat": "fn(other: [?]) -> !this",
            "join": "fn(separator?: string) -> string",
            "splice": "fn(pos: number, amount: number, newelt?: ?) -> [?]",
            "pop": "fn() -> !this.<i>",
            "push": "fn(newelt: ?) -> number",
            "shift": "fn() -> !this.<i>",
            "unshift": "fn(newelt: ?) -> number",
            "slice": "fn(from?: number, to?: number) -> !this",
            "reverse": "fn()",
            "sort": "fn(compare?: fn(a: ?, b: ?) -> number)",
            "indexOf": "fn(elt: ?, from?: number) -> number",
            "lastIndexOf": "fn(elt: ?, from?: number) -> number",
            "every": "fn(test: fn(elt: ?, i: number, array: +Array) -> bool, context?: ?) -> bool",
            "some": "fn(test: fn(elt: ?, i: number, array: +Array) -> bool, context?: ?) -> bool",
            "filter": "fn(test: fn(elt: ?, i: number, array: +Array) -> bool, context?: ?) -> !this",
            "forEach": "fn(f: fn(elt: ?, i: number, array: +Array), context?: ?)",
            "map": "fn(f: fn(elt: ?, i: number, array: +Array) -> ?, context?: ?) -> [!0.!ret]",
            "reduce": "fn(combine: fn(sum: ?, elt: ?, i: number, array: +Array) -> ?, init?: ?) -> !0.!ret",
            "reduceRight": "fn(combine: fn(sum: ?, elt: ?, i: number, array: +Array) -> ?, init?: ?) -> !0.!ret",
            "copyWithin": "fn(target: number, start: number, end?: number) -> !this",
            "entries": "fn() -> ?",
            "fill": "fn(value: ?, start?: number, end?: number) -> !this",
            "find": "fn(callback: fn(element: ?, index: number, array: [?]) -> bool, thisArg?: ?) -> !this.<i>",
            "findIndex": "fn(callback: fn(element: ?, index: number, array: [?]), thisArg?: ?) -> number",
            "keys": "fn() -> ?",
            "values": "fn() -> ?",
            "includes": "fn(value: ?, fromIndex?: number) -> bool"
        },
        "String" :{
            "length": "number",
            "charAt": "fn(i: number) -> string",
            "charCodeAt": "fn(i: number) -> number",
            "indexOf": "fn(char: string, from?: number) -> number",
            "lastIndexOf": "fn(char: string, from?: number) -> number",
            "substring": "fn(from: number, to?: number) -> string",
            "substr": "fn(from: number, length?: number) -> string",
            "slice": "fn(from: number, to?: number) -> string",
            "padStart": "fn(targetLength: number, padString?: string) -> string",
            "padEnd": "fn(targetLength: number, padString?: string) -> string",
            "trim": "fn() -> string",
            "trimStart": "fn() -> string",
            "trimLeft": "fn() -> string",
            "trimEnd": "fn() -> string",
            "trimRight": "fn() -> string",
            "toUpperCase": "fn() -> string",
            "toLowerCase": "fn() -> string",
            "toLocaleUpperCase": "fn() -> string",
            "toLocaleLowerCase": "fn() -> string",
            "split": "fn(pattern?: string|+RegExp, limit?: number) -> [string]",
            "concat": "fn(other: string) -> string",
            "localeCompare": "fn(other: string) -> number",
            "match": "fn(pattern: +RegExp) -> [string]",
            "replace": "fn(pattern: string|+RegExp, replacement: string) -> string",
            "search": "fn(pattern: +RegExp) -> number",
            "codePointAt": "fn(pos: number) -> number",
            "endsWith": "fn(searchString: string, position?: number) -> bool",
            "includes": "fn(searchString: string, position?: number) -> bool",
            "normalize": "fn(form: string) -> string",
            "repeat": "fn(count: number) -> string",
            "startsWith": "fn(searchString: string, position?: number) -> bool"
        },
        "Number" : {
            "toString": "fn(radix?: number) -> string",
            "toFixed": "fn(digits: number) -> string",
            "toExponential": "fn(digits: number) -> string",
            "toPrecision": "fn(digits: number) -> string"
        },
        "Boolean" : {
        },
        "RegExp" : {
            "exec": "fn(input: string) -> [string]",
            "test": "fn(input: string) -> bool",
            "global": "bool",
            "ignoreCase": "bool",
            "multiline": "bool",
            "source": "string",
            "lastIndex": "number",
            "flags": "string",
            "sticky": "bool",
            "unicode": "bool"
        },
        "Symbol": {
        }
    },
    "!define": {
        "DefError": {
            "!type": "fn(message: string)",
            "prototype": {
                "name": "string",
                "message": "string"
            }
        },
        "TypedArray": {
            "!type": "fn(size: number)",
            "from": "fn(arrayLike: ?, mapFn?: fn(elt: ?, i: number) -> number, thisArg?: ?) -> +TypedArray",
            "of": "fn(elements: number) -> +TypedArray",
            "BYTES_PER_ELEMENT": "number",
            "name": "string",
            "prototype": {
                "buffer": "+ArrayBuffer",
                "byteLength": "number",
                "byteOffset": "number",
                "copyWithin": "fn(target: number, start: number, end?: number) -> ?",
                "entries": "fn() -> ?",
                "every": "fn(callback: fn(element: number, index: number, array: +TypedArray) -> bool, thisArg?: ?) -> bool",
                "fill": "fn(value: number, start?: number, end?: number)",
                "filter": "fn(test: fn(element: number, i: number) -> bool, context?: ?) -> !this",
                "find": "fn(callback: fn(element: number, index: number, array: +TypedArray) -> bool, thisArg?: ?) -> number",
                "findIndex": "fn(callback: fn(element: number, index: number, array: +TypedArray) -> bool, thisArg?: ?) -> number",
                "forEach": "fn(callback: fn(value: number, key: number, array: +TypedArray), thisArg?: ?)",
                "indexOf": "fn(searchElement: number, fromIndex?: number) -> number",
                "join": "fn(separator?: string) -> string",
                "keys": "fn() -> ?",
                "lastIndexOf": "fn(searchElement: number, fromIndex?: number) -> number",
                "length": "number",
                "map": "fn(f: fn(element: number, i: number) -> number, context?: ?) -> +TypedArray",
                "reduce": "fn(combine: fn(sum: ?, elt: number, i: number) -> ?, init?: ?) -> ?",
                "reduceRight": "fn(combine: fn(sum: ?, elt: number, i: number) -> ?, init?: ?) -> ?",
                "reverse": "fn()",
                "set": "fn(array: [number], offset?: number)",
                "slice": "fn(from: number, to?: number) -> +TypedArray",
                "some": "fn(test: fn(elt: number, i: number) -> bool, context?: ?) -> bool",
                "sort": "fn(compare?: fn(a: number, b: number) -> number)",
                "subarray": "fn(begin?: number, end?: number) -> +TypedArray",
                "values": "fn() -> ?"
            }
        }
    },
    "!root": {
        "Infinity": "number",
        "undefined": "undefined",
        "NaN": "number",
        "Object": {
            "!type": "fn()",
            "getPrototypeOf": "fn(obj: ?) -> ?",
            "create": "fn(proto: ?) -> +Object",
            "defineProperty": "fn(obj: ?, prop: string, desc: propertyDescriptor) -> !custom:Object_defineProperty",
            "defineProperties": "fn(obj: ?, props: ?) -> !custom:Object_defineProperties",
            "getOwnPropertyDescriptor": "fn(obj: ?, prop: string) -> propertyDescriptor",
            "keys": "fn(obj: ?) -> [string]",
            "getOwnPropertyNames": "fn(obj: ?) -> [string]",
            "seal": "fn(obj: ?)",
            "isSealed": "fn(obj: ?) -> bool",
            "freeze": "fn(obj: ?) -> !0",
            "isFrozen": "fn(obj: ?) -> bool",
            "preventExtensions": "fn(obj: ?)",
            "isExtensible": "fn(obj: ?) -> bool",
            "assign": "fn(target: ?, source: ?, source?: ?) -> !0",
            "getOwnPropertySymbols": "fn(obj: ?) -> !custom:getOwnPropertySymbols",
            "is": "fn(value1: ?, value2: ?) -> bool",
            "setPrototypeOf": "fn(obj: ?, prototype: ?)",
            "prototype": "Object"
        },
        "Function": {
            "!type": "fn(body: string) -> fn()",
            "prototype": "Function"
        },
        "Array": {
            "!type": "fn(size: number) -> !custom:Array_ctor",
            "isArray": "fn(value: ?) -> bool",
            "from": "fn(arrayLike: ?, mapFn?: fn(elt: ?, i: number) -> ?, thisArg?: ?) -> [!0.<i>]",
            "of": "fn(elementN: ?) -> [!0]",
            "prototype": "Array"
        },
        "String": {
            "!type": "fn(value: ?) -> string",
            "fromCharCode": "fn(code: number) -> string",
            "fromCodePoint": "fn(point: number, point?: number) -> string",
            "raw": "fn(template: [string], substitutions: ?, templateString: ?) -> string",
            "prototype": "String"
        },
        "Number": {
            "!type": "fn(value: ?) -> number",
            "MAX_VALUE": "number",
            "MIN_VALUE": "number",
            "POSITIVE_INFINITY": "number",
            "NEGATIVE_INFINITY": "number",
            "prototype": "Number",
            "EPSILON": "number",
            "MAX_SAFE_INTEGER": "number",
            "MIN_SAFE_INTEGER": "number",
            "isFinite": "fn(testValue: ?) -> bool",
            "isInteger": "fn(testValue: ?) -> bool",
            "isNaN": "fn(testValue: ?) -> bool",
            "isSafeInteger": "fn(testValue: ?) -> bool",
            "parseFloat": "fn(string: string) -> number",
            "parseInt": "fn(string: string, radix?: number) -> number"
        },
        "Boolean": {
            "!type": "fn(value: ?) -> bool",
            "prototype": "Boolean"
        },
        "RegExp": {
            "!type": "fn(source: string, flags?: string)",
            "prototype": "RegExp"
        },
        "Date": {
            "!type": "fn(ms: number)",
            "parse": "fn(source: string) -> +Date",
            "UTC": "fn(year: number, month: number, date: number, hour?: number, min?: number, sec?: number, ms?: number) -> number",
            "now": "fn() -> number",
            "prototype": {
                "toUTCString": "fn() -> string",
                "toISOString": "fn() -> string",
                "toDateString": "fn() -> string",
                "toGMTString": "fn() -> string",
                "toTimeString": "fn() -> string",
                "toLocaleDateString": "fn() -> string",
                "toLocaleFormat": "fn(formatString: string) -> string",
                "toLocaleString": "fn(locales?: string, options?: ?) -> string",
                "toLocaleTimeString": "fn() -> string",
                "toSource": "fn() -> string",
                "toString": "fn() -> string",
                "valueOf": "fn() -> number",
                "getTime": "fn() -> number",
                "getFullYear": "fn() -> number",
                "getYear": "fn() -> number",
                "getMonth": "fn() -> number",
                "getUTCMonth": "fn() -> number",
                "getDate": "fn() -> number",
                "getUTCDate": "fn() -> number",
                "getDay": "fn() -> number",
                "getUTCDay": "fn() -> number",
                "getUTCFullYear": "fn() -> number",
                "getHours": "fn() -> number",
                "getUTCHours": "fn() -> number",
                "getMinutes": "fn() -> number",
                "getUTCMinutes": "fn() -> number",
                "getSeconds": "fn() -> number",
                "getUTCSeconds": "fn() -> number",
                "getMilliseconds": "fn() -> number",
                "getUTCMilliseconds": "fn() -> number",
                "getTimezoneOffset": "fn() -> number",
                "setTime": "fn(timeValue: number) -> number",
                "setFullYear": "fn(year: number) -> number",
                "setUTCFullYear": "fn(year: number) -> number",
                "setYear": "fn(yearValue: number) -> number",
                "setMonth": "fn(month: number) -> number",
                "setUTCMonth": "fn(month: number) -> number",
                "setDate": "fn(day: number) -> number",
                "setUTCDate": "fn(day: number) -> number",
                "setHours": "fn(hour: number) -> number",
                "setUTCHours": "fn(hour: number) -> number",
                "setMinutes": "fn(min: number) -> number",
                "setUTCMinutes": "fn(min: number) -> number",
                "setSeconds": "fn(sec: number) -> number",
                "setUTCSeconds": "fn(sec: number) -> number",
                "setMilliseconds": "fn(ms: number) -> number",
                "setUTCMilliseconds": "fn(ms: number) -> number",
                "toJSON": "fn() -> string"
            }
        },
        "Error": "DefError",
        "SyntaxError": "DefError",
        "ReferenceError": "DefError",
        "URIError": "DefError",
        "EvalError": "DefError",
        "RangeError": "DefError",
        "TypeError": "DefError",
        "parseInt": "fn(string: string, radix?: number) -> number",
        "parseFloat": "fn(string: string) -> number",
        "isNaN": "fn(value: number) -> bool",
        "isFinite": "fn(value: number) -> bool",
        "eval": "fn(code: string) -> ?",
        "encodeURI": "fn(uri: string) -> string",
        "encodeURIComponent": "fn(uri: string) -> string",
        "decodeURI": "fn(uri: string) -> string",
        "decodeURIComponent": "fn(uri: string) -> string",
        "Math": {
            "E": "number",
            "LN2": "number",
            "LN10": "number",
            "LOG2E": "number",
            "LOG10E": "number",
            "SQRT1_2": "number",
            "SQRT2": "number",
            "PI": "number",
            "abs": "fn(x: number) -> number",
            "cos": "fn(x: number) -> number",
            "sin": "fn(x: number) -> number",
            "tan": "fn(x: number) -> number",
            "acos": "fn(x: number) -> number",
            "asin": "fn(x: number) -> number",
            "atan": "fn(x: number) -> number",
            "atan2": "fn(y:number, x:number) -> number",
            "ceil": "fn(x: number) -> number",
            "floor": "fn(x: number) -> number",
            "round": "fn(x: number) -> number",
            "exp": "fn(x: number) -> number",
            "log": "fn(x: number) -> number",
            "sqrt": "fn(x: number) -> number",
            "pow": "fn(base:number, exponent:number) -> number",
            "max": "fn(number, number) -> number",
            "min": "fn(number, number) -> number",
            "random": "fn() -> number",
            "acosh": "fn(x: number) -> number",
            "asinh": "fn(x: number) -> number",
            "atanh": "fn(x: number) -> number",
            "cbrt": "fn(x: number) -> number",
            "clz32": "fn(x: number) -> number",
            "cosh": "fn(x: number) -> number",
            "expm1": "fn(x: number) -> number",
            "fround": "fn(x: number) -> number",
            "hypot": "fn(value: number) -> number",
            "imul": "fn(a:number, b:number) -> number",
            "log10": "fn(x: number) -> number",
            "log1p": "fn(x: number) -> number",
            "log2": "fn(x: number) -> number",
            "sign": "fn(x: number) -> number",
            "sinh": "fn(x: number) -> number",
            "tanh": "fn(x: number) -> number",
            "trunc": "fn(x: number) -> number"
        },
        "JSON": {
            "parse": "fn(json: string, reviver?: fn(key: string, value: ?) -> ?) -> ?",
            "stringify": "fn(value: ?, replacer?: fn(key: string, value: ?) -> ?, space?: string|number) -> string"
        },
        "ArrayBuffer": {
            "!type": "fn(length: number)",
            "isView": "fn(arg: +ArrayBuffer) -> bool",
            "prototype": {
                "byteLength": "number",
                "slice": "fn(begin: number, end?: number) -> +ArrayBuffer"
            }
        },
        "DataView": {
            "!type": "fn(buffer: +ArrayBuffer, byteOffset?: number, byteLength?: number)",
            "prototype": {
                "buffer": "+ArrayBuffer",
                "byteLength": "number",
                "byteOffset": "number",
                "getFloat32": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getFloat64": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getInt16": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getInt32": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getInt8": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getUint16": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getUint32": "fn(byteOffset: number, littleEndian?: bool) -> number",
                "getUint8": "fn(byteOffset: number) -> number",
                "setFloat32": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setFloat64": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setInt16": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setInt32": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setInt8": "fn(byteOffset: number, value: number)",
                "setUint16": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setUint32": "fn(byteOffset: number, value: number, littleEndian?: bool)",
                "setUint8": "fn(byteOffset: number, value: number)"
            }
        },
        "Float32Array": "TypedArray",
        "Float64Array": "TypedArray",
        "Int16Array": "TypedArray",
        "Int32Array": "TypedArray",
        "Int8Array": "TypedArray",
        "Map": {
            "!type": "fn(iterable?: [?])",
            "prototype": {
                "clear": "fn()",
                "delete": "fn(key: ?)",
                "entries": "fn() -> ?",
                "forEach": "fn(callback: fn(value: ?, key: ?, map: +Map), thisArg?: ?)",
                "get": "fn(key: ?) -> !this.:value",
                "has": "fn(key: ?) -> bool",
                "keys": "fn() -> ?",
                "set": "fn(key: ?, value: ?) -> !this",
                "size": "number",
                "values": "fn() -> ?"
            }
        },
        "Promise": {
            "!type": "fn(executor: fn(resolve: fn(value: ?), reject: fn(reason: ?))) -> !custom:Promise_ctor",
            "all": "fn(iterable: [+Promise]) -> ?",
            "race": "fn(iterable: [+Promise]) -> !0.<i>",
            "reject": "Promise_reject",
            "resolve": "fn(value: ?) -> !custom:Promise_resolve",
            "prototype": "Promise.prototype"
        },
        "Proxy": {
            "!type": "fn(target: ?, handler: Proxy_handler)",
            "revocable": "fn(target: ?, handler: Proxy_handler) -> Proxy_revocable"

        },
        "Reflect": {
            "apply": "fn(target: fn(), thisArg?: ?, argumentList?: [?]) -> !0.!ret",
            "construct": "fn(target: fn(), argumentList?: [?]) -> ?",
            "defineProperty": "fn(target: ?, property: string, descriptor: propertyDescriptor) -> bool",
            "deleteProperty": "fn(target: ?, property: string) -> bool",
            "enumerate": "fn(target: ?) -> ?",
            "get": "fn(target: ?, property: string) -> ?",
            "getOwnPropertyDescriptor": "fn(target: ?, property: string) -> ?",
            "getPrototypeOf": "fn(target: ?) -> ?",
            "has": "fn(target: ?, property: string) -> bool",
            "isExtensible": "fn(target: ?) -> bool",
            "ownKeys": "fn(target: ?) -> [string]",
            "preventExtensions": "fn(target: ?) -> bool",
            "set": "fn(target: ?, property: string, value: ?) -> bool",
            "setPrototypeOf": "fn(target: ?, prototype: ?) -> bool"
        },
        "Set": {
            "!type": "fn(iterable?: [?])",
            "prototype": {
                "add": "fn(value: ?) -> !this",
                "clear": "fn()",
                "delete": "fn(value: ?) -> bool",
                "entries": "fn() -> ?",
                "forEach": "fn(callback: fn(value: ?, value2: ?, set: +Set), thisArg?: ?)",
                "has": "fn(value: ?) -> bool",
                "keys": "fn() -> ?",
                "size": "number",
                "values": "fn() -> ?"
            }
        },
        "Symbol": {
            "!type": "fn(description?: string) -> symbol",
            "for": "fn(key: string) -> symbol",
            "keyFor": "fn(sym: symbol) -> string",
            "hasInstance": "symbol",
            "isConcatSpreadable": "symbol",
            "iterator": "symbol",
            "asyncIterator": "symbol",
            "match": "symbol",
            "replace": "symbol",
            "search": "symbol",
            "species": "symbol",
            "split": "symbol",
            "toStringTag": "symbol",
            "unscopables": "symbol",
            "prototype": "Symbol"
        },
        "Uint16Array": "TypedArray",
        "Uint32Array": "TypedArray",
        "Uint8Array": "TypedArray",
        "Uint8ClampedArray": "TypedArray",
        "WeakMap": {
            "!type": "fn(iterable?: [?])",
            "prototype": {
                "delete": "fn(key: ?) -> bool",
                "get": "fn(key: ?) -> !this.:value",
                "has": "fn(key: ?) -> bool",
                "set": "fn(key: ?, value: ?)"
            }
        },
        "WeakSet": {
            "!type": "fn(iterable?: [?])",
            "prototype": {
                "add": "fn(value: ?)",
                "delete": "fn(value: ?) -> bool",
                "has": "fn(value: ?) -> bool"
            }
        },
        "console": {
            "log": "fn(string: string)",
            "clear": "fn()"
        },
        "XMLHttpRequest": {
            "!type": "fn()",
            "prototype": {
                "abort": "fn()",
                "getAllResponseHeaders": "fn() -> string",
                "getResponseHeader":  "fn(header: string) -> string",
                "open": "fn(method: string, url: string, async?: bool, user?: string, password?: string)",
                "send": "fn(data?: string)",
                "setRequestHeader": "fn(header: string, value: string)",
                "onabort":  "fn()",
                "onerror":  "fn()",
                "onload":  "fn()",
                "onloadstart":  "fn()",
                "onloadend":  "fn()",
                "onreadystatechange":  "fn()",
                "readyState": "number",
                "responseText": "string",
                "responseType": "string",
                "status": "string",
                "statusText": "string",
                "UNSENT": "number",
                "OPENED": "number",
                "HEADERS_RECEIVED": "number",
                "LOADING": "number",
                "DONE": "number"
            }
        },
        "Headers": {
            "!type": "fn(init?: object)",
            "prototype": {
                "append": "fn(name: string, value: string)",
                "delete": "fn(name: string)",
                "get": "fn(name: string)",
                "getAll": "fn(name: string)",
                "has": "fn(name: string)",
                "set": "fn(name: string, value: string)"
            }
          },
        "Request": {
            "!type": "fn(input: string, init?: object)",
            "prototype": {
                "bodyUsed": "bool",
                "cache": "string",
                "context": "string",
                "credentials": "string",
                "headers": "+Headers",
                "integrity": "string",
                "method": "string",
                "mode": "string",
                "redirect": "string",
                "referrer": "string",
                "referrerPolicy": "string",
                "url": "string",
                "clone":"fn()",
                "arrayBuffer": "fn() -> +Promise[:t=+ArrayBuffer]",
                 "blob": "fn() -> +Promise[:t=+Blob]",
                "formData": "fn() -> +Promise[:t=+FormData]",
                "json": "fn() -> +Promise[:t=?]",
                "text": "fn() -> +Promise[:t=string]"
            }
        },
        "Response": {
            "!type": "fn(body: object, init?: object)",
            "prototype": {
                "type": "string",
                "url": "string",
                "status": "number",
                "ok": "bool",
                "statusText": "string",
                "headers": "+Headers",
                "bodyUsed": "bool",
                "clone": "fn() -> +Response",
                "error": "fn() -> +Response",
                "redirect": "fn(url: string, status?: number) -> +Response",
               "json": "fn() -> +Promise[:t=?]",
               "text":  "fn() -> +Promise[:t=string]"
            }
        },
        "fetch": "fn(url: string|+Request, init?: object) -> +Promise[:t=+Response]"
    }
}