refactor(core): zero circulars + esm ready (#10770)

This commit is contained in:
Nathan Walker
2025-09-18 17:03:23 -07:00
committed by GitHub
parent 1e54baf198
commit c2ff8c1ae7
306 changed files with 9136 additions and 9889 deletions

View File

@ -0,0 +1,38 @@
export type ModuleListProvider = () => string[];
let appForModuleResolverCallback: () => void;
export function prepareAppForModuleResolver(callback: () => void) {
appForModuleResolverCallback = callback;
}
export function initAppForModuleResolver() {
if (appForModuleResolverCallback) {
appForModuleResolverCallback();
appForModuleResolverCallback = undefined;
}
}
export interface ModuleNameResolverType {
resolveModuleName(path: string, ext: string): string;
clearCache(): void;
}
let resolverInstance: ModuleNameResolverType;
export function getResolveInstance() {
return resolverInstance;
}
/**
* Used to set a global singular instance of ModuleNameResolver
* @param resolver instance
*/
export function _setResolver(resolver: ModuleNameResolverType) {
resolverInstance = resolver;
}
export function clearResolverCache() {
if (resolverInstance) {
resolverInstance.clearCache();
}
}

View File

@ -1,24 +0,0 @@
/**
* Provides ModuleNameResolver class used for loading files based on device capabilities.
*/ /** */
import { PlatformContext } from './qualifier-matcher';
export { PlatformContext } from './qualifier-matcher';
export type ModuleListProvider = () => string[];
export class ModuleNameResolver {
constructor(context: PlatformContext, moduleListProvider?: ModuleListProvider);
resolveModuleName(path: string, ext: string): string;
clearCache(): void;
}
export function resolveModuleName(path: string, ext: string): string;
export function clearCache(): void;
/**
* Used to set a global singular instance of ModuleNameResolver
* @param resolver instance
*/
export function _setResolver(resolver: ModuleNameResolver);

View File

@ -1,21 +1,18 @@
import { Screen, Device } from '../platform';
import { PlatformContext, findMatch, stripQualifiers } from './qualifier-matcher';
import { registerModulesFromFileSystem } from './non-bundle-workflow-compat';
import { Trace } from '../trace';
import { Application } from '../application';
import { ModuleNameResolverType, ModuleListProvider, initAppForModuleResolver, getResolveInstance, _setResolver } from './helpers';
export type { PlatformContext } from './qualifier-matcher';
export type ModuleListProvider = () => string[];
export class ModuleNameResolver {
export class ModuleNameResolver implements ModuleNameResolverType {
private _cache = {};
constructor(private context: PlatformContext, private moduleListProvider: ModuleListProvider = global.getRegisteredModules) {
Application.on('livesync', (args) => clearCache());
Application.on('orientationChanged', (args) => {
resolverInstance = undefined;
});
constructor(
private context: PlatformContext,
private moduleListProvider: ModuleListProvider = global.getRegisteredModules,
) {
initAppForModuleResolver();
}
public resolveModuleName(path: string, ext: string): string {
@ -46,34 +43,32 @@ export class ModuleNameResolver {
const candidates = this.getCandidates(path, ext);
result = findMatch(path, ext, candidates, this.context);
return result;
}
private getCandidates(path: string, ext: string): Array<string> {
const candidates = this.moduleListProvider().filter((moduleName) => moduleName.startsWith(path) && (!ext || moduleName.endsWith(ext)));
return candidates;
}
}
let resolverInstance: ModuleNameResolver;
export function resolveModuleName(path: string, ext: string): string {
if (global.__snapshot) {
return resolveModuleSnapshot(path, ext);
}
if (!resolverInstance) {
resolverInstance = new ModuleNameResolver({
width: Screen.mainScreen.widthDIPs,
height: Screen.mainScreen.heightDIPs,
os: Device.os,
deviceType: Device.deviceType,
});
if (!getResolveInstance()) {
_setResolver(
new ModuleNameResolver({
width: Screen.mainScreen.widthDIPs,
height: Screen.mainScreen.heightDIPs,
os: Device.os,
deviceType: Device.deviceType,
}),
);
}
return resolverInstance.resolveModuleName(path, ext);
return getResolveInstance().resolveModuleName(path, ext);
}
function resolveModuleSnapshot(path, ext) {
@ -89,13 +84,3 @@ function resolveModuleSnapshot(path, ext) {
deviceType: 'Phone',
}).resolveModuleName(path, ext);
}
export function clearCache() {
if (resolverInstance) {
resolverInstance.clearCache();
}
}
export function _setResolver(resolver: ModuleNameResolver) {
resolverInstance = resolver;
}

View File

@ -1,5 +1,4 @@
import { Application } from '../application';
import * as fs from '../file-system';
import { knownFolders, File, path, Folder } from '../file-system';
import { Trace } from '../trace';
const cache = new Set<string>();
@ -20,13 +19,13 @@ function register(name: string, loader: (name?: string) => void) {
}
}
function processFile(file: fs.File) {
const filePathRelativeToApp = file.path.substr(fs.knownFolders.currentApp().path.length + 1);
function processFile(file: File) {
const filePathRelativeToApp = file.path.substring(knownFolders.currentApp().path.length + 1);
const loadContent = () => file.readTextSync();
switch (file.extension.toLocaleLowerCase()) {
case '.js': {
const noExtPath = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - '.js'.length);
case 'js': {
const noExtPath = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - '.js'.length);
register(filePathRelativeToApp, function () {
return global.require(file.path);
@ -37,11 +36,23 @@ function processFile(file: fs.File) {
break;
}
case '.css':
case 'mjs': {
const noExtPath = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - '.mjs'.length);
register(filePathRelativeToApp, function () {
return global.require(file.path);
});
register(noExtPath, function () {
return global.require(file.path);
});
break;
}
case 'css':
register(filePathRelativeToApp, loadContent);
break;
case '.xml':
case 'xml':
register(filePathRelativeToApp, loadContent);
break;
}
@ -49,8 +60,8 @@ function processFile(file: fs.File) {
if (file.name === 'package.json') {
const json = global.require(file.path);
if (json.main) {
const name = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - 'package.json'.length - 1);
const requirePath = fs.path.join(file.parent.path, json.main);
const name = filePathRelativeToApp.substring(0, filePathRelativeToApp.length - 'package.json'.length - 1);
const requirePath = path.join(file.parent.path, json.main);
register(name, () => global.require(requirePath));
}
@ -73,11 +84,11 @@ function processFolder(path: string): boolean {
let folderEmpty = true;
if (fs.Folder.exists(path)) {
const folder = fs.Folder.fromPath(path);
if (Folder.exists(path)) {
const folder = Folder.fromPath(path);
folder.eachEntity((file) => {
if (file instanceof fs.File) {
if (file instanceof File) {
processFile(file);
folderEmpty = false;
}
@ -100,15 +111,15 @@ export function registerModulesFromFileSystem(moduleName: string) {
let folderProcessed = false;
let parentFolderProcessed = false;
// moduleName is a folder with package.json
const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
if (fs.Folder.exists(path)) {
folderProcessed = processFolder(path);
const filePath = path.join(knownFolders.currentApp().path, moduleName);
if (Folder.exists(filePath)) {
folderProcessed = processFolder(filePath);
}
// moduleName is file - load all files in its parent folder
const parentName = moduleName.substr(0, moduleName.lastIndexOf(fs.path.separator));
const parentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, parentName);
if (fs.Folder.exists(parentFolderPath)) {
const parentName = moduleName.substring(0, moduleName.lastIndexOf(path.separator));
const parentFolderPath = path.join(knownFolders.currentApp().path, parentName);
if (Folder.exists(parentFolderPath)) {
parentFolderProcessed = processFolder(parentFolderPath);
}
@ -120,15 +131,15 @@ export function registerModulesFromFileSystem(moduleName: string) {
}
// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
const tnsModulesPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', moduleName);
if (fs.Folder.exists(tnsModulesPath)) {
const tnsModulesPath = path.join(knownFolders.currentApp().path, 'tns_modules', moduleName);
if (Folder.exists(tnsModulesPath)) {
processFolder(tnsModulesPath);
}
// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
if (parentName) {
const tnsParentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', parentName);
if (fs.Folder.exists(tnsParentFolderPath)) {
const tnsParentFolderPath = path.join(knownFolders.currentApp().path, 'tns_modules', parentName);
if (Folder.exists(tnsParentFolderPath)) {
processFolder(tnsParentFolderPath);
}
}
@ -136,7 +147,7 @@ export function registerModulesFromFileSystem(moduleName: string) {
function initialize() {
if (!initialized) {
Application.on('livesync', (args) => cache.clear());
// Application.on('livesync', (args) => cache.clear());
initialized = true;
}
}

View File

@ -1,17 +0,0 @@
/**
* Provides ModuleNameResolver class used for loading files based on device capabilities.
*/
/**
* Used with qualifier matchers and module resolution
*/
export interface PlatformContext {
width: number;
height: number;
os: string;
deviceType: string;
}
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string;
export function stripQualifiers(path: string): string;

View File

@ -27,7 +27,7 @@ const minWidthHeightQualifier: QualifierSpec = {
return path.match(new RegExp(`.${MIN_WH}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_WH.length + 1));
const numVal = parseInt(value.substring(MIN_WH.length + 1));
if (isNaN(numVal)) {
return -1;
}
@ -49,7 +49,7 @@ const minWidthQualifier: QualifierSpec = {
return path.match(new RegExp(`.${MIN_W}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_W.length + 1));
const numVal = parseInt(value.substring(MIN_W.length + 1));
if (isNaN(numVal)) {
return -1;
}
@ -71,7 +71,7 @@ const minHeightQualifier: QualifierSpec = {
return path.match(new RegExp(`.${MIN_H}\\d+`, 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const numVal = parseInt(value.substr(MIN_H.length + 1));
const numVal = parseInt(value.substring(MIN_H.length + 1));
if (isNaN(numVal)) {
return -1;
}
@ -93,7 +93,7 @@ const platformQualifier: QualifierSpec = {
return path.match(new RegExp('\\.android|\\.ios', 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
const val = value.substring(1);
return val === context.os.toLowerCase() ? 1 : -1;
},
@ -107,7 +107,7 @@ const orientationQualifier: QualifierSpec = {
return path.match(new RegExp('\\.land|\\.port', 'g'));
},
getMatchValue(value: string, context: PlatformContext): number {
const val = value.substr(1);
const val = value.substring(1);
const isLandscape: number = context.width > context.height ? 1 : -1;
return val === 'land' ? isLandscape : -isLandscape;