const core = globalThis.Deno.core;
const ops = core.ops;
let logDebug = false;
let logSource = "JS";
function spanned(name, f) {
if (!ops.op_make_span) {
return f();
}
const span = ops.op_make_span(name, false);
try {
return f();
} finally {
ops.op_exit_span(span);
}
}
const unstableDenoProps = new Set([
"AtomicOperation",
"DatagramConn",
"Kv",
"KvListIterator",
"KvU64",
"UnixConnectOptions",
"UnixListenOptions",
"listen",
"listenDatagram",
"openKv",
"connectQuic",
"listenQuic",
"QuicBidirectionalStream",
"QuicConn",
"QuicListener",
"QuicReceiveStream",
"QuicSendStream",
]);
const unstableMsgSuggestion =
"If not, try changing the 'lib' compiler option to include 'deno.unstable' " +
"or add a triple-slash directive to the top of your entrypoint (main file): " +
'/// <reference lib="deno.unstable" />';
function isCreateSourceFileOptions(value) {
return value != null && typeof value === "object" &&
"languageVersion" in value;
}
export function getCreateSourceFileOptions(versionOrOptions) {
return isCreateSourceFileOptions(versionOrOptions)
? versionOrOptions
: { languageVersion: versionOrOptions ?? ts.ScriptTarget.ESNext };
}
export function setLogDebug(debug, source) {
logDebug = debug;
if (source) {
logSource = source;
}
}
export function printStderr(msg) {
core.print(msg, true);
}
export function debug(...args) {
if (logDebug) {
const stringifiedArgs = args.map((arg) =>
typeof arg === "string" ? arg : JSON.stringify(arg)
).join(" ");
printStderr(`DEBUG ${logSource} - ${stringifiedArgs}\n`);
}
}
export function error(...args) {
const stringifiedArgs = args.map((arg) =>
typeof arg === "string" || arg instanceof Error
? String(arg)
: JSON.stringify(arg)
).join(" ");
printStderr(`ERROR ${logSource} = ${stringifiedArgs}\n`);
}
export class AssertionError extends Error {
constructor(msg) {
super(msg);
this.name = "AssertionError";
}
}
export function assert(cond, msg = "Assertion failed.") {
if (!cond) {
throw new AssertionError(msg);
}
}
export const SOURCE_FILE_CACHE = new Map();
export const SCRIPT_SNAPSHOT_CACHE = new Map();
export const SOURCE_REF_COUNTS = new Map();
export const SCRIPT_VERSION_CACHE = new Map();
export const IS_NODE_SOURCE_FILE_CACHE = new Map();
let projectVersionCache = null;
export const PROJECT_VERSION_CACHE = {
get: () => projectVersionCache,
set: (version) => {
projectVersionCache = version;
},
};
let lastRequestMethod = null;
export const LAST_REQUEST_METHOD = {
get: () => lastRequestMethod,
set: (method) => {
lastRequestMethod = method;
},
};
let lastRequestCompilerOptionsKey = null;
export const LAST_REQUEST_COMPILER_OPTIONS_KEY = {
get: () => lastRequestCompilerOptionsKey,
set: (key) => {
lastRequestCompilerOptionsKey = key;
},
};
let lastRequestNotebookUri = null;
export const LAST_REQUEST_NOTEBOOK_URI = {
get: () => lastRequestNotebookUri,
set: (notebookUri) => {
lastRequestNotebookUri = notebookUri;
},
};
function isNodeSourceFile(sourceFile) {
const fileName = sourceFile.fileName;
let isNodeSourceFile = IS_NODE_SOURCE_FILE_CACHE.get(fileName);
if (isNodeSourceFile == null) {
const result = ops.op_is_node_file(fileName);
isNodeSourceFile = (result);
IS_NODE_SOURCE_FILE_CACHE.set(fileName, isNodeSourceFile);
}
return isNodeSourceFile;
}
ts.deno.setIsNodeSourceFileCallback(isNodeSourceFile);
function formatMessage(msg, code) {
switch (code) {
case 2304: {
if (msg === "Cannot find name 'Deno'.") {
msg += " Do you need to change your target library? " +
"Try changing the 'lib' compiler option to include 'deno.ns' " +
"or add a triple-slash directive to the top of your entrypoint " +
'(main file): /// <reference lib="deno.ns" />';
}
return msg;
}
case 2339: {
const property = getProperty();
if (property && unstableDenoProps.has(property)) {
return `${msg} 'Deno.${property}' is an unstable API. ${unstableMsgSuggestion}`;
}
return msg;
}
default: {
const property = getProperty();
if (property && unstableDenoProps.has(property)) {
const suggestion = getMsgSuggestion();
if (suggestion) {
return `${msg} 'Deno.${property}' is an unstable API. Did you mean '${suggestion}'? ${unstableMsgSuggestion}`;
}
}
return msg;
}
}
function getProperty() {
return /Property '([^']+)' does not exist on type 'typeof Deno'/
.exec(msg)?.[1];
}
function getMsgSuggestion() {
return / Did you mean '([^']+)'\?/.exec(msg)?.[1];
}
}
function fromRelatedInformation({
start,
length,
file,
messageText: msgText,
...ri
}) {
let messageText;
let messageChain;
if (typeof msgText === "object") {
messageChain = msgText;
} else {
messageText = formatMessage(msgText, ri.code);
}
if (start !== undefined && length !== undefined && file) {
let startPos = file.getLineAndCharacterOfPosition(start);
let endPos = file.getLineAndCharacterOfPosition(start + length);
const lineStarts = file.getLineStarts();
let sourceLine = file.getFullText().slice(
lineStarts[startPos.line],
lineStarts[startPos.line + 1],
).trimEnd();
const originalFileName = file.fileName;
const fileName = ops.op_remap_specifier
? (ops.op_remap_specifier(file.fileName) ?? file.fileName)
: file.fileName;
if (
fileName.endsWith(".wasm") && originalFileName.endsWith(".wasm.d.mts")
) {
startPos = endPos = { line: 0, character: 0 };
sourceLine = undefined;
}
return {
start: startPos,
end: endPos,
fileName,
messageChain,
messageText,
sourceLine,
...ri,
};
} else {
return {
messageChain,
messageText,
...ri,
};
}
}
export function fromTypeScriptDiagnostics(diagnostics) {
return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {
const value = fromRelatedInformation(diag);
value.relatedInformation = ri ? ri.map(fromRelatedInformation) : undefined;
value.source = source;
return value;
});
}
export const ASSETS_URL_PREFIX = "asset:///";
const CACHE_URL_PREFIX = "cache:///";
const TSC_CONSTANTS = ops.op_tsc_constants();
const IGNORED_DIAGNOSTICS = TSC_CONSTANTS.ignoredDiagnosticCodes;
const TYPES_NODE_IGNORABLE_NAMES = new Set(
TSC_CONSTANTS.typesNodeIgnorableNames,
);
const NODE_ONLY_GLOBALS = new Set(TSC_CONSTANTS.nodeOnlyGlobals);
export class OperationCanceledError extends Error {
}
class CancellationToken {
isCancellationRequested() {
return ops.op_is_cancelled();
}
throwIfCancellationRequested() {
if (this.isCancellationRequested()) {
throw new OperationCanceledError();
}
}
}
export const LANGUAGE_SERVICE_ENTRIES = {
byCompilerOptionsKey: new Map(),
byNotebookUri: new Map(),
};
let SCRIPT_NAMES_CACHE = null;
export function clearScriptNamesCache() {
SCRIPT_NAMES_CACHE = null;
}
const hostImpl = {
fileExists(specifier) {
if (logDebug) {
debug(`host.fileExists("${specifier}")`);
}
return false;
},
readFile(specifier) {
if (logDebug) {
debug(`host.readFile("${specifier}")`);
}
return ops.op_load(specifier)?.data;
},
getCancellationToken() {
return new CancellationToken();
},
getProjectVersion() {
const cachedProjectVersion = PROJECT_VERSION_CACHE.get();
if (
cachedProjectVersion
) {
debug(`getProjectVersion cache hit : ${cachedProjectVersion}`);
return cachedProjectVersion;
}
const projectVersion = ops.op_project_version();
PROJECT_VERSION_CACHE.set(projectVersion);
debug(`getProjectVersion cache miss : ${projectVersion}`);
return projectVersion;
},
toPath(fileName) {
return ts.toPath(
fileName,
this.getCurrentDirectory(),
this.getCanonicalFileName.bind(this),
);
},
watchNodeModulesForPackageJsonChanges() {
return { close() {} };
},
getSourceFile(
specifier,
languageVersion,
_onError,
_shouldCreateNewSourceFile,
) {
if (logDebug) {
debug(
`host.getSourceFile("${specifier}", ${
ts.ScriptTarget[
getCreateSourceFileOptions(languageVersion).languageVersion
]
})`,
);
}
let sourceFile = SOURCE_FILE_CACHE.get(specifier);
if (sourceFile) {
return sourceFile;
}
const fileInfo = ops.op_load(specifier);
if (!fileInfo) {
return undefined;
}
const { data, scriptKind, version, isCjs } = fileInfo;
assert(
data != null,
`"data" is unexpectedly null for "${specifier}".`,
);
sourceFile = ts.createSourceFile(
specifier,
data,
{
...getCreateSourceFileOptions(languageVersion),
impliedNodeFormat: isCjs
? ts.ModuleKind.CommonJS
: ts.ModuleKind.ESNext,
jsDocParsingMode: ts.JSDocParsingMode.ParseForTypeErrors,
},
false,
scriptKind,
);
sourceFile.moduleName = specifier;
sourceFile.version = version;
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
sourceFile.version = "1";
}
SOURCE_FILE_CACHE.set(specifier, sourceFile);
SCRIPT_VERSION_CACHE.set(specifier, version);
return sourceFile;
},
getDefaultLibFileName() {
return `${ASSETS_URL_PREFIX}lib.esnext.d.ts`;
},
getDefaultLibLocation() {
return ASSETS_URL_PREFIX;
},
writeFile(fileName, data, _writeByteOrderMark, _onError, _sourceFiles) {
if (logDebug) {
debug(`host.writeFile("${fileName}")`);
}
return ops.op_emit(
data,
fileName,
);
},
getCurrentDirectory() {
if (logDebug) {
debug(`host.getCurrentDirectory()`);
}
return CACHE_URL_PREFIX;
},
getCanonicalFileName(fileName) {
return fileName;
},
useCaseSensitiveFileNames() {
return true;
},
getNewLine() {
return "\n";
},
resolveTypeReferenceDirectiveReferences(
typeDirectiveReferences,
containingFilePath,
_redirectedReference,
options,
containingSourceFile,
_reusedNames,
) {
const isCjs =
containingSourceFile?.impliedNodeFormat === ts.ModuleKind.CommonJS;
const toResolve = typeDirectiveReferences.map((arg) => {
const fileReference = typeof arg === "string"
? {
pos: -1,
end: -1,
fileName: arg,
}
: arg;
return [
fileReference.resolutionMode == null
? isCjs
: fileReference.resolutionMode === ts.ModuleKind.CommonJS,
fileReference.fileName,
];
});
const resolved = ops.op_resolve(
containingFilePath,
toResolve,
);
const result = resolved.map((item) => {
if (item && item[1]) {
const [resolvedFileName, extension] = item;
return {
resolvedTypeReferenceDirective: {
primary: true,
resolvedFileName,
extension,
isExternalLibraryImport: false,
},
};
} else {
return {
resolvedTypeReferenceDirective: undefined,
};
}
});
if (logDebug) {
debug(
"resolveTypeReferenceDirectiveReferences ",
typeDirectiveReferences,
containingFilePath,
options,
containingSourceFile?.fileName,
" => ",
result,
);
}
return result;
},
resolveModuleNameLiterals(
moduleLiterals,
base,
_redirectedReference,
compilerOptions,
containingSourceFile,
_reusedNames,
) {
const specifiers = moduleLiterals.map((literal) => {
const rawKind = getModuleLiteralImportKind(literal);
let lookupSpecifier = literal.text;
if (rawKind != null) {
if (( (literal)).__originalText == null) {
( (literal)).__originalText = literal.text;
literal.text = appendRawImportFragment(literal.text, rawKind);
}
lookupSpecifier = ( (literal)).__originalText;
}
return [
ts.getModeForUsageLocation(
containingSourceFile,
literal,
compilerOptions,
) === ts.ModuleKind.CommonJS,
lookupSpecifier,
];
});
if (logDebug) {
debug(`host.resolveModuleNames()`);
debug(` base: ${base}`);
debug(` specifiers: ${specifiers.map((s) => s[1]).join(", ")}`);
}
const resolved = ops.op_resolve(
base,
specifiers,
);
if (resolved) {
const result = resolved.map((item, i) => {
if (item) {
let [resolvedFileName, extension] = item;
const rawKind = getModuleLiteralImportKind(moduleLiterals[i]);
if (rawKind != null) {
resolvedFileName = appendRawImportFragment(
resolvedFileName,
rawKind,
);
extension = ts.Extension.Ts;
}
if (extension) {
return {
resolvedModule: {
resolvedFileName,
extension,
isExternalLibraryImport: false,
},
};
}
}
return {
resolvedModule: undefined,
};
});
result.length = specifiers.length;
return result;
} else {
return new Array(specifiers.length);
}
},
createHash(data) {
return ops.op_create_hash(data);
},
getCompilationSettings() {
if (logDebug) {
debug("host.getCompilationSettings()");
}
const lastRequestCompilerOptionsKey = LAST_REQUEST_COMPILER_OPTIONS_KEY
.get();
if (lastRequestCompilerOptionsKey == null) {
throw new Error(`No compiler options key was set.`);
}
const compilerOptions = LANGUAGE_SERVICE_ENTRIES.byCompilerOptionsKey.get(
lastRequestCompilerOptionsKey,
)?.compilerOptions;
if (!compilerOptions) {
throw new Error(
`Couldn't find language service entry for key: ${lastRequestCompilerOptionsKey}`,
);
}
return compilerOptions;
},
getScriptFileNames() {
if (logDebug) {
debug("host.getScriptFileNames()");
}
if (!SCRIPT_NAMES_CACHE) {
const { byCompilerOptionsKey, byNotebookUri } = ops.op_script_names();
SCRIPT_NAMES_CACHE = {
byCompilerOptionsKey: new Map(Object.entries(byCompilerOptionsKey)),
byNotebookUri: new Map(Object.entries(byNotebookUri)),
};
}
const lastRequestCompilerOptionsKey = LAST_REQUEST_COMPILER_OPTIONS_KEY
.get();
const lastRequestNotebookUri = LAST_REQUEST_NOTEBOOK_URI.get();
return (lastRequestNotebookUri
? SCRIPT_NAMES_CACHE.byNotebookUri.get(lastRequestNotebookUri)
: null) ??
(lastRequestCompilerOptionsKey
? SCRIPT_NAMES_CACHE.byCompilerOptionsKey.get(
lastRequestCompilerOptionsKey,
)
: null) ??
[];
},
getScriptVersion(specifier) {
if (logDebug) {
debug(`host.getScriptVersion("${specifier}")`);
}
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
return "1";
}
if (SCRIPT_VERSION_CACHE.has(specifier)) {
return SCRIPT_VERSION_CACHE.get(specifier);
}
const scriptVersion = ops.op_script_version(specifier);
SCRIPT_VERSION_CACHE.set(specifier, scriptVersion);
return scriptVersion;
},
getScriptSnapshot(specifier) {
if (logDebug) {
debug(`host.getScriptSnapshot("${specifier}")`);
}
if (specifier.startsWith(ASSETS_URL_PREFIX)) {
const sourceFile = this.getSourceFile(
specifier,
ts.ScriptTarget.ESNext,
);
if (sourceFile) {
return ts.ScriptSnapshot.fromString(sourceFile.text);
}
}
let scriptSnapshot = SCRIPT_SNAPSHOT_CACHE.get(specifier);
if (scriptSnapshot == undefined) {
const fileInfo = ops.op_load(specifier);
if (!fileInfo) {
return undefined;
}
scriptSnapshot = ts.ScriptSnapshot.fromString(fileInfo.data);
scriptSnapshot.isCjs = fileInfo.isCjs;
scriptSnapshot.isClassicScript = fileInfo.isClassicScript;
SCRIPT_SNAPSHOT_CACHE.set(specifier, scriptSnapshot);
SCRIPT_VERSION_CACHE.set(specifier, fileInfo.version);
}
return scriptSnapshot;
},
getNearestAncestorDirectoryWithPackageJson() {
return undefined;
},
};
const excluded = new Set([
"getScriptVersion",
"fileExists",
"getScriptSnapshot",
"getCompilationSettings",
"getCurrentDirectory",
"useCaseSensitiveFileNames",
"getModuleSpecifierCache",
"getGlobalTypingsCacheLocation",
"getSourceFile",
]);
export const host = {
log(msg) {
ops.op_log_event(msg);
},
};
for (const [key, value] of Object.entries(hostImpl)) {
if (typeof value === "function" && !excluded.has(key)) {
host[key] = (...args) => {
return spanned(key, () => value.bind(host)(...args));
};
} else {
host[key] = value;
}
}
ts.setLocalizedDiagnosticMessages((() => {
const nodeMessage = "Cannot find name '{0}'."; const jqueryMessage =
"Cannot find name '{0}'. Did you mean to import jQuery? Try adding `import $ from \"npm:jquery\";`.";
return {
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashno_2580":
nodeMessage,
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashno_2591":
nodeMessage,
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slash_2581":
jqueryMessage,
"Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slash_2592":
jqueryMessage,
"Module_0_was_resolved_to_1_but_allowArbitraryExtensions_is_not_set_6263":
"Module '{0}' was resolved to '{1}', but importing these modules is not supported.",
};
})());
export function filterMapDiagnostic(diagnostic) {
if (IGNORED_DIAGNOSTICS.includes(diagnostic.code)) {
return false;
}
if (
diagnostic.code === 6053 &&
(diagnostic.file == null || !isNodeSourceFile(diagnostic.file))
) {
return false;
}
const isClassicScript = !diagnostic.file?.["externalModuleIndicator"];
if (isClassicScript) {
if (diagnostic.code == 1375 || diagnostic.code == 1431) {
return false;
}
}
if (diagnostic.code === 1203) {
diagnostic.category = ts.DiagnosticCategory.Warning;
if (typeof diagnostic.messageText === "string") {
const message =
" This will start erroring in a future version of Deno 2 " +
"in order to align with TypeScript.";
if (!diagnostic.messageText.endsWith(message)) {
diagnostic.messageText += message;
}
}
}
return true;
}
ts.deno.setNodeOnlyGlobalNames(
NODE_ONLY_GLOBALS,
);
const setTypesNodeIgnorableNames = TYPES_NODE_IGNORABLE_NAMES;
ts.deno.setTypesNodeIgnorableNames(setTypesNodeIgnorableNames);
function getModuleLiteralImportKind(node) {
const parent = node.parent;
if (!parent) {
return undefined;
}
if (ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent)) {
const elements = parent.attributes?.elements;
if (!elements) {
return undefined;
}
for (const element of elements) {
const value = getRawImportAttributeValue(element);
if (value) {
return value;
}
}
return undefined;
} else if (ts.isCallExpression(parent)) {
if (
parent.expression.kind !== ts.SyntaxKind.ImportKeyword ||
parent.arguments.length <= 1 ||
parent.arguments[0].kind !== ts.SyntaxKind.StringLiteral ||
parent.arguments[1].kind !== ts.SyntaxKind.ObjectLiteralExpression
) {
return undefined;
}
const ole = (parent.arguments[1]);
const withExpr = ole.properties.find((p) =>
ts.isPropertyAssignment(p) && isStrOrIdentWithText(p.name, "with")
);
if (!withExpr) {
return undefined;
}
const withInitializer =
( (withExpr)).initializer;
if (!ts.isObjectLiteralExpression(withInitializer)) {
return undefined;
}
const typeProp = withInitializer.properties.find((p) =>
ts.isPropertyAssignment(p) && isStrOrIdentWithText(p.name, "type")
);
if (!typeProp) {
return undefined;
}
const typeInitializer =
( (typeProp)).initializer;
return getRawTypeValue(typeInitializer);
} else {
return undefined;
}
}
function appendRawImportFragment(specifier, rawKind) {
const fragmentIndex = specifier.indexOf("#");
if (fragmentIndex === -1) {
specifier += `#denoRawImport=${rawKind}.ts`;
} else if (
!specifier.substring(fragmentIndex).includes(
`denoRawImport=${rawKind}.ts`,
)
) {
specifier += `&denoRawImport=${rawKind}.ts`;
}
return specifier;
}
function getRawImportAttributeValue(node) {
if (!isStrOrIdentWithText(node.name, "type")) {
return undefined;
}
return getRawTypeValue(node.value);
}
function getRawTypeValue(node) {
return ts.isStringLiteral(node) &&
(node.text === "bytes" || node.text === "text")
? node.text
: undefined;
}
function isStrOrIdentWithText(node, text) {
if (ts.isStringLiteral(node)) {
return node.text === text;
} else if (ts.isIdentifier(node)) {
return node.escapedText === text;
} else {
return false;
}
}