chore: cleanup

This commit is contained in:
Nathan Walker
2025-07-19 01:18:12 -07:00
parent 2fb70c1f10
commit 248a85f6e0
15 changed files with 439 additions and 417 deletions

View File

@ -14,6 +14,7 @@ import type { AndroidApplication as AndroidApplicationType, iOSApplication as iO
import type { ApplicationEventData, CssChangedEventData, DiscardedErrorEventData, FontScaleChangedEventData, InitRootViewEventData, LaunchEventData, LoadAppCSSEventData, NativeScriptError, OrientationChangedEventData, SystemAppearanceChangedEventData, UnhandledErrorEventData } from './application-interfaces'; import type { ApplicationEventData, CssChangedEventData, DiscardedErrorEventData, FontScaleChangedEventData, InitRootViewEventData, LaunchEventData, LoadAppCSSEventData, NativeScriptError, OrientationChangedEventData, SystemAppearanceChangedEventData, UnhandledErrorEventData } from './application-interfaces';
import { readyInitAccessibilityCssHelper, readyInitFontScale } from '../accessibility/accessibility-common'; import { readyInitAccessibilityCssHelper, readyInitFontScale } from '../accessibility/accessibility-common';
import { getAppMainEntry, isAppInBackground, setAppInBackground, setAppMainEntry } from './helpers-common'; import { getAppMainEntry, isAppInBackground, setAppInBackground, setAppMainEntry } from './helpers-common';
import { getNativeScriptGlobals } from '../globals/global-utils';
// prettier-ignore // prettier-ignore
const ORIENTATION_CSS_CLASSES = [ const ORIENTATION_CSS_CLASSES = [
@ -28,7 +29,7 @@ const SYSTEM_APPEARANCE_CSS_CLASSES = [
`${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.dark}`, `${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.dark}`,
]; ];
const globalEvents = global.NativeScriptGlobals.events; const globalEvents = getNativeScriptGlobals().events;
// helper interface to correctly type Application event handlers // helper interface to correctly type Application event handlers
interface ApplicationEvents { interface ApplicationEvents {
@ -161,7 +162,7 @@ export class ApplicationCommon {
* @internal - should not be constructed by the user. * @internal - should not be constructed by the user.
*/ */
constructor() { constructor() {
global.NativeScriptGlobals.appInstanceReady = true; getNativeScriptGlobals().appInstanceReady = true;
global.__onUncaughtError = (error: NativeScriptError) => { global.__onUncaughtError = (error: NativeScriptError) => {
this.notify({ this.notify({
@ -507,7 +508,7 @@ export class ApplicationCommon {
} }
hasLaunched(): boolean { hasLaunched(): boolean {
return global.NativeScriptGlobals && global.NativeScriptGlobals.launched; return getNativeScriptGlobals().launched;
} }
private _systemAppearance: 'dark' | 'light' | null; private _systemAppearance: 'dark' | 'light' | null;

View File

@ -42,6 +42,7 @@ import {
} from '../accessibility/accessibility-common'; } from '../accessibility/accessibility-common';
import { androidGetForegroundActivity, androidGetStartActivity, androidPendingReceiverRegistrations, androidRegisterBroadcastReceiver, androidRegisteredReceivers, androidSetForegroundActivity, androidSetStartActivity, androidUnregisterBroadcastReceiver, applyContentDescription } from './helpers'; import { androidGetForegroundActivity, androidGetStartActivity, androidPendingReceiverRegistrations, androidRegisterBroadcastReceiver, androidRegisteredReceivers, androidSetForegroundActivity, androidSetStartActivity, androidUnregisterBroadcastReceiver, applyContentDescription } from './helpers';
import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common'; import { getImageFetcher, getNativeApp, getRootView, initImageCache, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setNativeApp, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
import { getNativeScriptGlobals } from '../globals/global-utils';
declare class NativeScriptLifecycleCallbacks extends android.app.Application.ActivityLifecycleCallbacks {} declare class NativeScriptLifecycleCallbacks extends android.app.Application.ActivityLifecycleCallbacks {}
@ -1364,9 +1365,9 @@ function onLiveSync(args): void {
} }
} }
global.NativeScriptGlobals.events.on('livesync', onLiveSync); getNativeScriptGlobals().events.on('livesync', onLiveSync);
global.NativeScriptGlobals.addEventWiring(() => { getNativeScriptGlobals().addEventWiring(() => {
Application.android.on('activityStarted', (args: any) => { Application.android.on('activityStarted', (args: any) => {
if (!getImageFetcher()) { if (!getImageFetcher()) {
initImageCache(args.activity); initImageCache(args.activity);
@ -1376,7 +1377,7 @@ global.NativeScriptGlobals.addEventWiring(() => {
}); });
}); });
global.NativeScriptGlobals.addEventWiring(() => { getNativeScriptGlobals().addEventWiring(() => {
Application.android.on('activityStopped', (args) => { Application.android.on('activityStopped', (args) => {
if (getImageFetcher()) { if (getImageFetcher()) {
getImageFetcher().closeCache(); getImageFetcher().closeCache();

View File

@ -1,4 +1,4 @@
import { parse } from 'css-tree'; import * as cssTree from 'css-tree';
function mapSelectors(selector: string): string[] { function mapSelectors(selector: string): string[] {
if (!selector) { if (!selector) {
@ -129,7 +129,7 @@ function transformAst(node, css, type = null) {
export function cssTreeParse(css, source): any { export function cssTreeParse(css, source): any {
const errors = []; const errors = [];
const ast = parse(css, { const ast = cssTree.parse(css, {
parseValue: false, parseValue: false,
parseAtrulePrelude: false, parseAtrulePrelude: false,
parseRulePrelude: false, parseRulePrelude: false,

View File

@ -1,6 +1,5 @@
import { encoding as textEncoding } from '../text'; import { encoding as textEncoding } from '../text';
import { ios as iosUtils } from '../utils'; import { iOSNativeHelper } from '../utils';
import { getFileExtension } from '../utils/utils-shared';
// TODO: Implement all the APIs receiving callback using async blocks // TODO: Implement all the APIs receiving callback using async blocks
// TODO: Check whether we need try/catch blocks for the iOS implementation // TODO: Check whether we need try/catch blocks for the iOS implementation
@ -258,7 +257,7 @@ export class FileSystemAccess {
} }
public getCurrentAppPath(): string { public getCurrentAppPath(): string {
return iosUtils.getCurrentAppPath(); return iOSNativeHelper.getCurrentAppPath();
} }
public copy = this.copySync.bind(this); public copy = this.copySync.bind(this);
@ -612,8 +611,24 @@ export class FileSystemAccess {
return url.path; return url.path;
} }
// TODO: This method is the same as in the iOS implementation.
// Make it in a separate file / module so it can be reused from both implementations.
public getFileExtension(path: string): string { public getFileExtension(path: string): string {
return getFileExtension(path); // TODO [For Panata]: The definitions currently specify "any" as a return value of this method
//const nsString = Foundation.NSString.stringWithString(path);
//const extension = nsString.pathExtension();
//if (extension && extension.length > 0) {
// extension = extension.concat(".", extension);
//}
//return extension;
const dotIndex = path.lastIndexOf('.');
if (dotIndex && dotIndex >= 0 && dotIndex < path.length) {
return path.substring(dotIndex);
}
return '';
} }
private deleteEntity(path: string, onError?: (error: any) => any) { private deleteEntity(path: string, onError?: (error: any) => any) {
@ -685,7 +700,7 @@ export class FileSystemAccess {
} }
public joinPaths(paths: string[]): string { public joinPaths(paths: string[]): string {
return iosUtils.joinPaths(...paths); return iOSNativeHelper.joinPaths(...paths);
} }
} }

View File

@ -1,7 +1,6 @@
import * as definition from './fps-native';
import { SDK_VERSION } from '../utils/constants'; import { SDK_VERSION } from '../utils/constants';
export class FPSCallback implements definition.FPSCallback { export class FPSCallback {
private impl: android.view.Choreographer.FrameCallback | ((nanos: number) => void); private impl: android.view.Choreographer.FrameCallback | ((nanos: number) => void);
private onFrame: (currentTimeMillis: number) => void; private onFrame: (currentTimeMillis: number) => void;

View File

@ -1,5 +1,3 @@
import * as definition from './fps-native';
@NativeClass @NativeClass
class FrameHandlerImpl extends NSObject { class FrameHandlerImpl extends NSObject {
private _owner: WeakRef<FPSCallback>; private _owner: WeakRef<FPSCallback>;
@ -23,7 +21,7 @@ class FrameHandlerImpl extends NSObject {
}; };
} }
export class FPSCallback implements definition.FPSCallback { export class FPSCallback {
public running: boolean; public running: boolean;
private onFrame: Function; private onFrame: Function;
private displayLink: CADisplayLink; private displayLink: CADisplayLink;

View File

@ -26,7 +26,7 @@ declare interface NativeScriptError extends Error {
//Augment the NodeJS global type with our own extensions //Augment the NodeJS global type with our own extensions
declare module globalThis { declare module globalThis {
var NativeScriptHasInitGlobal: boolean; var NativeScriptHasPolyfilled: boolean;
var NativeScriptGlobals: { var NativeScriptGlobals: {
/** /**
* Global framework event handling * Global framework event handling

View File

@ -0,0 +1,74 @@
import { Observable } from '../data/observable';
import { trace as profilingTrace, time, uptime, level as profilingLevel } from '../profiling';
console.log('here in globals/global-utils!');
/**
* Manages internal framework global state
*/
export class NativeScriptGlobalState {
events: Observable;
launched = false;
// used by various classes to setup callbacks to wire up global app event handling when the app instance is ready
appEventWiring: Array<any>;
private _appInstanceReady = false;
private _setLaunched: () => void;
constructor() {
// console.log('creating NativeScriptGlobals...')
this.events = new Observable();
this._setLaunched = this._setLaunchedFn.bind(this);
this.events.on('launch', this._setLaunched);
if (profilingLevel() > 0) {
this.events.on('displayed', () => {
const duration = uptime();
const end = time();
const start = end - duration;
profilingTrace(`Displayed in ${duration.toFixed(2)}ms`, start, end);
});
}
}
get appInstanceReady() {
return this._appInstanceReady;
}
set appInstanceReady(value: boolean) {
this._appInstanceReady = value;
// app instance ready, wire up any app events waiting in startup queue
if (this.appEventWiring && this.appEventWiring.length) {
for (const callback of this.appEventWiring) {
callback();
}
// cleanup
this.appEventWiring = null;
}
}
/**
* Ability for classes to initialize app event handling early even before the app instance is ready during boot cycle avoiding boot race conditions
* @param callback wire up any global event handling inside the callback
*/
addEventWiring(callback: () => void) {
if (this._appInstanceReady) {
callback();
} else {
if (!this.appEventWiring) {
this.appEventWiring = [];
}
this.appEventWiring.push(callback);
}
}
private _setLaunchedFn() {
// console.log('NativeScriptGlobals launch fired!');
this.launched = true;
this.events.off('launch', this._setLaunched);
this._setLaunched = null;
}
}
export function getNativeScriptGlobals() {
if (!global.NativeScriptGlobals) {
// init global state handler
global.NativeScriptGlobals = new NativeScriptGlobalState();
}
return global.NativeScriptGlobals;
}

View File

@ -1,6 +1,4 @@
import tslib from 'tslib'; import tslib from 'tslib';
import { Observable } from '../data/observable';
import { trace as profilingTrace, time, uptime, level as profilingLevel } from '../profiling';
import * as timer from '../timer'; import * as timer from '../timer';
import * as animationFrame from '../animation-frame'; import * as animationFrame from '../animation-frame';
import * as mediaQueryList from '../media-query-list'; import * as mediaQueryList from '../media-query-list';
@ -50,108 +48,9 @@ interface ExtensionMap {
[originalFileExtension: string]: string; [originalFileExtension: string]: string;
} }
function registerOnGlobalContext(moduleName: string, exportName: string): void { // ts-helpers
Object.defineProperty(global, exportName, { // Required by V8 snapshot generator
get: function () { if (!global.__extends) {
// We do not need to cache require() call since it is already cached in the runtime.
const m = global.loadModule(moduleName);
// Redefine the property to make sure the above code is executed only once.
const resolvedValue = m[exportName];
Object.defineProperty(global, exportName, {
value: resolvedValue,
configurable: true,
writable: true,
});
return resolvedValue;
},
configurable: true,
});
}
/**
* Manages internal framework global state
*/
export class NativeScriptGlobalState {
events: Observable;
launched = false;
// used by various classes to setup callbacks to wire up global app event handling when the app instance is ready
appEventWiring: Array<any>;
private _appInstanceReady = false;
private _setLaunched: () => void;
constructor() {
// console.log('creating NativeScriptGlobals...')
this.events = new Observable();
this._setLaunched = this._setLaunchedFn.bind(this);
this.events.on('launch', this._setLaunched);
if (profilingLevel() > 0) {
this.events.on('displayed', () => {
const duration = uptime();
const end = time();
const start = end - duration;
profilingTrace(`Displayed in ${duration.toFixed(2)}ms`, start, end);
});
}
}
get appInstanceReady() {
return this._appInstanceReady;
}
set appInstanceReady(value: boolean) {
this._appInstanceReady = value;
// app instance ready, wire up any app events waiting in startup queue
if (this.appEventWiring && this.appEventWiring.length) {
for (const callback of this.appEventWiring) {
callback();
}
// cleanup
this.appEventWiring = null;
}
}
/**
* Ability for classes to initialize app event handling early even before the app instance is ready during boot cycle avoiding boot race conditions
* @param callback wire up any global event handling inside the callback
*/
addEventWiring(callback: () => void) {
if (this._appInstanceReady) {
callback();
} else {
if (!this.appEventWiring) {
this.appEventWiring = [];
}
this.appEventWiring.push(callback);
}
}
private _setLaunchedFn() {
// console.log('NativeScriptGlobals launch fired!');
this.launched = true;
this.events.off('launch', this._setLaunched);
this._setLaunched = null;
}
}
export function installPolyfills(moduleName: string, exportNames: string[]) {
if (global.__snapshot) {
const loadedModule = global.loadModule(moduleName);
exportNames.forEach((exportName) => (global[exportName] = loadedModule[exportName]));
} else {
exportNames.forEach((exportName) => registerOnGlobalContext(moduleName, exportName));
}
}
export function initGlobal() {
if (!global.NativeScriptHasInitGlobal) {
global.NativeScriptHasInitGlobal = true;
// init global state handler
global.NativeScriptGlobals = new NativeScriptGlobalState();
// ts-helpers
// Required by V8 snapshot generator
if (!global.__extends) {
global.__extends = function (d, b) { global.__extends = function (d, b) {
for (const p in b) { for (const p in b) {
if (b.hasOwnProperty(p)) { if (b.hasOwnProperty(p)) {
@ -163,12 +62,12 @@ export function initGlobal() {
} }
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
}; };
} }
// Bind the tslib helpers to global scope. // Bind the tslib helpers to global scope.
// This is needed when we don't use importHelpers, which // This is needed when we don't use importHelpers, which
// breaks extending native-classes // breaks extending native-classes
for (const fnName of Object.getOwnPropertyNames(tslib)) { for (const fnName of Object.getOwnPropertyNames(tslib)) {
if (typeof tslib[fnName] !== 'function') { if (typeof tslib[fnName] !== 'function') {
continue; continue;
} }
@ -179,12 +78,10 @@ export function initGlobal() {
} }
global[fnName] = tslib[fnName]; global[fnName] = tslib[fnName];
} }
// module helpers // module helpers
const modules: Map<string, { moduleId: string; loader: ModuleLoader }> = new Map<string, { moduleId: string; loader: ModuleLoader }>(); const defaultExtensionMap: ExtensionMap = {
const modulesLoadedForUI = new Set<string>();
const defaultExtensionMap: ExtensionMap = {
'.js': '.js', '.js': '.js',
'.ts': '.js', '.ts': '.js',
'.kt': '.js', '.kt': '.js',
@ -193,28 +90,28 @@ export function initGlobal() {
'.less': '.css', '.less': '.css',
'.sass': '.css', '.sass': '.css',
'.xml': '.xml', '.xml': '.xml',
}; };
// Cast to <any> because moduleResolvers is read-only in definitions // Cast to <any> because moduleResolvers is read-only in definitions
global.moduleResolvers = [global.require]; global.moduleResolvers = [global.require];
global.registerModule = function (name: string, loader: ModuleLoader): void { global.registerModule = function (name: string, loader: ModuleLoader): void {
modules.set(name, { loader, moduleId: name }); modules.set(name, { loader, moduleId: name });
}; };
global._unregisterModule = function _unregisterModule(name: string): void { global._unregisterModule = function _unregisterModule(name: string): void {
modules.delete(name); modules.delete(name);
}; };
global._isModuleLoadedForUI = function _isModuleLoadedForUI(moduleName: string): boolean { global._isModuleLoadedForUI = function _isModuleLoadedForUI(moduleName: string): boolean {
return modulesLoadedForUI.has(moduleName); return modulesLoadedForUI.has(moduleName);
}; };
global.registerWebpackModules = function registerWebpackModules(context: Context, extensionMap: ExtensionMap = {}) { global.registerWebpackModules = function registerWebpackModules(context: Context, extensionMap: ExtensionMap = {}) {
context.keys().forEach((moduleId) => { context.keys().forEach((moduleId) => {
const extDotIndex = moduleId.lastIndexOf('.'); const extDotIndex = moduleId.lastIndexOf('.');
const base = moduleId.substr(0, extDotIndex); const base = moduleId.substring(0, extDotIndex);
const originalExt = moduleId.substr(extDotIndex); const originalExt = moduleId.substring(extDotIndex);
const registerExt = extensionMap[originalExt] || defaultExtensionMap[originalExt] || originalExt; const registerExt = extensionMap[originalExt] || defaultExtensionMap[originalExt] || originalExt;
// We prefer source files for webpack scenarios before compilation leftovers, // We prefer source files for webpack scenarios before compilation leftovers,
@ -235,11 +132,11 @@ export function initGlobal() {
if (registerName.startsWith('./') && registerName.endsWith('.js')) { if (registerName.startsWith('./') && registerName.endsWith('.js')) {
const jsNickNames = [ const jsNickNames = [
// This is extremely short version like "main-page" that was promoted to be used with global.registerModule("module-name", loaderFunc); // This is extremely short version like "main-page" that was promoted to be used with global.registerModule("module-name", loaderFunc);
registerName.substr(2, registerName.length - 5), registerName.substring(2, registerName.length - 5),
// This is for supporting module names like "./main/main-page" // This is for supporting module names like "./main/main-page"
registerName.substr(0, registerName.length - 3), registerName.substring(0, registerName.length - 3),
// This is for supporting module names like "main/main-page.js" // This is for supporting module names like "main/main-page.js"
registerName.substr(2), registerName.substring(2),
]; ];
jsNickNames.forEach((jsNickName) => { jsNickNames.forEach((jsNickName) => {
@ -250,7 +147,7 @@ export function initGlobal() {
} else if (registerName.startsWith('./')) { } else if (registerName.startsWith('./')) {
const moduleNickNames = [ const moduleNickNames = [
// This is for supporting module names like "main/main-page.xml" // This is for supporting module names like "main/main-page.xml"
registerName.substr(2), registerName.substring(2),
]; ];
moduleNickNames.forEach((moduleNickName) => { moduleNickNames.forEach((moduleNickName) => {
@ -264,13 +161,93 @@ export function initGlobal() {
registerWithName(registerName); registerWithName(registerName);
} }
}); });
}; };
global.moduleExists = function moduleExists(name: string): boolean { global.moduleExists = function moduleExists(name: string): boolean {
return modules.has(name); return modules.has(name);
};
global.getRegisteredModules = function getRegisteredModules(): string[] {
return Array.from(modules.keys());
};
/**
* Polyfills
*/
// This method iterates all the keys in the source exports object and copies them to the destination exports one.
// Note: the method will not check for naming collisions and will override any already existing entries in the destination exports.
global.moduleMerge = function (sourceExports: any, destExports: any) {
for (const key in sourceExports) {
destExports[key] = sourceExports[key];
}
};
global.zonedCallback = function (callback: Function): Function {
if (global.zone) {
// Zone v0.5.* style callback wrapping
return global.zone.bind(callback);
}
if (global.Zone) {
// Zone v0.6.* style callback wrapping
return global.Zone.current.wrap(callback);
} else {
return callback;
}
};
global.System = {
import(path) {
return new Promise((resolve, reject) => {
try {
resolve(global.require(path));
} catch (e) {
reject(e);
}
});
},
};
// Custom decorators
global.Deprecated = function (target: Object, key?: string | symbol, descriptor?: any) {
if (descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${key.toString()} is deprecated`);
return originalMethod.apply(this, args);
}; };
global.loadModule = function loadModule(name: string, isUIModule = false): any { return descriptor;
} else {
console.log(`${(target && (<any>target).name) || target} is deprecated`);
return target;
}
};
global.Experimental = function (target: Object, key?: string | symbol, descriptor?: any) {
if (descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${key.toString()} is experimental`);
return originalMethod.apply(this, args);
};
return descriptor;
} else {
console.log(`${(target && (<any>target).name) || target} is experimental`);
return target;
}
};
const modules: Map<string, { moduleId: string; loader: ModuleLoader }> = new Map<string, { moduleId: string; loader: ModuleLoader }>();
const modulesLoadedForUI = new Set<string>();
global.loadModule = function loadModule(name: string, isUIModule = false): any {
const moduleInfo = modules.get(name); const moduleInfo = modules.get(name);
if (moduleInfo) { if (moduleInfo) {
if (isUIModule) { if (isUIModule) {
@ -294,48 +271,39 @@ export function initGlobal() {
return result; return result;
} }
} }
}; };
function registerOnGlobalContext(moduleName: string, exportName: string): void {
Object.defineProperty(global, exportName, {
get: function () {
// We do not need to cache require() call since it is already cached in the runtime.
const m = global.loadModule(moduleName);
global.getRegisteredModules = function getRegisteredModules(): string[] { // Redefine the property to make sure the above code is executed only once.
return Array.from(modules.keys()); const resolvedValue = m[exportName];
}; Object.defineProperty(global, exportName, {
value: resolvedValue,
/** configurable: true,
* Polyfills writable: true,
*/
// This method iterates all the keys in the source exports object and copies them to the destination exports one.
// Note: the method will not check for naming collisions and will override any already existing entries in the destination exports.
global.moduleMerge = function (sourceExports: any, destExports: any) {
for (const key in sourceExports) {
destExports[key] = sourceExports[key];
}
};
global.zonedCallback = function (callback: Function): Function {
if (global.zone) {
// Zone v0.5.* style callback wrapping
return global.zone.bind(callback);
}
if (global.Zone) {
// Zone v0.6.* style callback wrapping
return global.Zone.current.wrap(callback);
} else {
return callback;
}
};
global.System = {
import(path) {
return new Promise((resolve, reject) => {
try {
resolve(global.require(path));
} catch (e) {
reject(e);
}
}); });
},
};
return resolvedValue;
},
configurable: true,
});
}
export function installPolyfills(moduleName: string, exportNames: string[]) {
if (global.__snapshot) {
const loadedModule = global.loadModule(moduleName);
exportNames.forEach((exportName) => (global[exportName] = loadedModule[exportName]));
} else {
exportNames.forEach((exportName) => registerOnGlobalContext(moduleName, exportName));
}
}
if (!global.NativeScriptHasPolyfilled) {
global.NativeScriptHasPolyfilled = true;
console.log('Installing polyfills...');
// DOM api polyfills // DOM api polyfills
global.registerModule('timer', () => timer); global.registerModule('timer', () => timer);
installPolyfills('timer', ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval']); installPolyfills('timer', ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval']);
@ -368,45 +336,6 @@ export function initGlobal() {
// global.registerModule('abortcontroller', () => require('../abortcontroller')); // global.registerModule('abortcontroller', () => require('../abortcontroller'));
// installPolyfills('abortcontroller', ['AbortController', 'AbortSignal']); // installPolyfills('abortcontroller', ['AbortController', 'AbortSignal']);
// Custom decorators
global.Deprecated = function (target: Object, key?: string | symbol, descriptor?: any) {
if (descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${key.toString()} is deprecated`);
return originalMethod.apply(this, args);
};
return descriptor;
} else {
console.log(`${(target && (<any>target).name) || target} is deprecated`);
return target;
}
};
global.Experimental = function (target: Object, key?: string | symbol, descriptor?: any) {
if (descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${key.toString()} is experimental`);
return originalMethod.apply(this, args);
};
return descriptor;
} else {
console.log(`${(target && (<any>target).name) || target} is experimental`);
return target;
}
};
}
} }
declare const jest: any; declare const jest: any;
@ -414,11 +343,7 @@ function isTestingEnv() {
return typeof jest !== 'undefined' || global.__UNIT_TEST__; return typeof jest !== 'undefined' || global.__UNIT_TEST__;
} }
console.log('global.NativeScriptHasInitGlobal:', global.NativeScriptHasInitGlobal);
console.log('isTestingEnv():', isTestingEnv()); console.log('isTestingEnv():', isTestingEnv());
if (!global.NativeScriptHasInitGlobal && !isTestingEnv()) {
initGlobal();
}
// ensure the Application instance is initialized before any other module imports it. // ensure the Application instance is initialized before any other module imports it.
import '../application'; import '../application';

View File

@ -160,10 +160,6 @@ export function enable(mode: InstrumentationMode = 'counters') {
} }
try { try {
// const appConfig = require('~/package.json');
// @ts-ignore
// const appConfig = await import('~/package.json');
console.log('profiling appConfig:', appConfig);
if (appConfig && appConfig.profiling) { if (appConfig && appConfig.profiling) {
enable(appConfig.profiling); enable(appConfig.profiling);
} }

View File

@ -1,6 +1,6 @@
import type { Point, Position } from './view-interfaces'; import type { Point, Position } from './view-interfaces';
import type { GestureTypes, GestureEventData } from '../../gestures'; import type { GestureTypes, GestureEventData } from '../../gestures';
import { getNativeScriptGlobals } from '../../../globals/global-utils';
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper } from './view-common'; import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper } from './view-common';
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties'; import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
import { Length } from '../../styling/length-shared'; import { Length } from '../../styling/length-shared';
@ -143,7 +143,7 @@ function initializeDialogFragment() {
}; };
// Fist fire application.android global event // Fist fire application.android global event
global.NativeScriptGlobals.events.notify(args); getNativeScriptGlobals().events.notify(args);
if (args.cancel) { if (args.cancel) {
return; return;
} }

View File

@ -1,3 +1,4 @@
import { getNativeScriptGlobals } from '../../globals/global-utils';
import { ViewBase } from '../core/view-base'; import { ViewBase } from '../core/view-base';
import { View } from '../core/view'; import { View } from '../core/view';
import { _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties'; import { _evaluateCssVariableExpression, _evaluateCssCalcExpression, isCssVariable, isCssVariableExpression, isCssCalcExpression } from '../core/properties';
@ -23,18 +24,8 @@ import { parse as parseCss } from '../../css/lib/parse';
// @ts-ignore apps resolve this at runtime with path alias in project bundlers // @ts-ignore apps resolve this at runtime with path alias in project bundlers
import appConfig from '~/package.json'; import appConfig from '~/package.json';
// if (!global.__dirname) {
// global.__dirname = typeof __dirname !== 'undefined' ? __dirname : import.meta.dirname;
// }
// const appPackagePath = path.join(global.__dirname, 'package.json');
console.log('style-scope appConfig:', appConfig);
let parser: 'rework' | 'nativescript' | 'css-tree' = 'css-tree'; let parser: 'rework' | 'nativescript' | 'css-tree' = 'css-tree';
try { try {
console.log('style-scope here??');
// @ts-ignore
// const appConfig = require('~/package.json');
// console.log('style-scope appConfig:', appConfig);
if (appConfig) { if (appConfig) {
if (appConfig.cssParser === 'rework') { if (appConfig.cssParser === 'rework') {
parser = 'rework'; parser = 'rework';
@ -497,8 +488,8 @@ const loadCss = profile(`"style-scope".loadCss`, (cssModule: string): void => {
} }
}); });
global.NativeScriptGlobals.events.on('cssChanged', <any>onCssChanged); getNativeScriptGlobals().events.on('cssChanged', <any>onCssChanged);
global.NativeScriptGlobals.events.on('livesync', onLiveSync); getNativeScriptGlobals().events.on('livesync', onLiveSync);
// Call to this method is injected in the application in: // Call to this method is injected in the application in:
// - no-snapshot - code injected in app.ts by [bundle-config-loader](https://github.com/NativeScript/nativescript-dev-webpack/blob/9b1e34d8ef838006c9b575285c42d2304f5f02b5/bundle-config-loader.ts#L85-L92) // - no-snapshot - code injected in app.ts by [bundle-config-loader](https://github.com/NativeScript/nativescript-dev-webpack/blob/9b1e34d8ef838006c9b575285c42d2304f5f02b5/bundle-config-loader.ts#L85-L92)
@ -507,7 +498,7 @@ global.NativeScriptGlobals.events.on('livesync', onLiveSync);
// when the snapshot is created - there is no way to use file qualifiers or change the name of on app.css // when the snapshot is created - there is no way to use file qualifiers or change the name of on app.css
export const loadAppCSS = profile('"style-scope".loadAppCSS', (args: LoadAppCSSEventData) => { export const loadAppCSS = profile('"style-scope".loadAppCSS', (args: LoadAppCSSEventData) => {
loadCss(args.cssFile, null, null); loadCss(args.cssFile, null, null);
global.NativeScriptGlobals.events.off('loadAppCss', loadAppCSS); getNativeScriptGlobals().events.off('loadAppCss', loadAppCSS);
}); });
if (Application.hasLaunched()) { if (Application.hasLaunched()) {
@ -521,7 +512,7 @@ if (Application.hasLaunched()) {
null, null,
); );
} else { } else {
global.NativeScriptGlobals.events.on('loadAppCss', loadAppCSS); getNativeScriptGlobals().events.on('loadAppCss', loadAppCSS);
} }
export class CssState { export class CssState {

View File

@ -95,10 +95,7 @@ function getCurrentAppPath(): string {
if (!global.__dirname) { if (!global.__dirname) {
global.__dirname = typeof __dirname !== 'undefined' ? __dirname : import.meta.dirname; global.__dirname = typeof __dirname !== 'undefined' ? __dirname : import.meta.dirname;
} }
console.log('getCurrentAppPath __dirname:', __dirname);
const currentDir = global.__dirname; const currentDir = global.__dirname;
console.log('getCurrentAppPath global.__dirname:', global.__dirname);
console.log('getCurrentAppPath currentDir:', currentDir);
const tnsModulesIndex = currentDir.indexOf('/tns_modules'); const tnsModulesIndex = currentDir.indexOf('/tns_modules');
// Module not hosted in ~/tns_modules when bundled. Use current dir. // Module not hosted in ~/tns_modules when bundled. Use current dir.

View File

@ -1,6 +1,11 @@
// @ts-nocheck // @ts-nocheck
import { beforeAll, afterAll, vi } from 'vitest'; import { beforeAll, afterAll, vi } from 'vitest';
// mock to allow tests to pass while globals attempt to polyfill crypto
vi.stubGlobal('crypto', {
randomUUID: vi.fn(() => 'mock-uuid'),
// Add other necessary crypto methods as mocks
});
// Mock out global variables and platform APIs touched while unit testing // Mock out global variables and platform APIs touched while unit testing
global.__UNIT_TEST__ = true; global.__UNIT_TEST__ = true;
global.__DEV__ = true; global.__DEV__ = true;

View File

@ -127,26 +127,39 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
.add('@nativescript/core/inspector_modules'); .add('@nativescript/core/inspector_modules');
}); });
// config.merge({ if (env.commonjs) {
// experiments: { // CommonJS output
// // enable ES module syntax (import/exports)
// outputModule: true,
// },
// });
config.output config.output
.path(outputPath) .path(outputPath)
.pathinfo(false) .pathinfo(false)
.publicPath('') .publicPath('')
// .set('module', true)
// .libraryTarget('module')
.libraryTarget('commonjs') .libraryTarget('commonjs')
.globalObject('global') .globalObject('global')
.set('clean', true); .set('clean', true);
if (env === null || env === void 0 ? void 0 : env.uniqueBundle) {
if (env?.uniqueBundle) {
config.output.filename(`[name].${env.uniqueBundle}.js`); config.output.filename(`[name].${env.uniqueBundle}.js`);
} }
} else {
// ESM output
config.merge({
experiments: {
// enable ES module syntax (import/exports)
outputModule: true,
},
});
config.output
.path(outputPath)
.pathinfo(false)
.publicPath('file:///app/')
.set('module', true)
.libraryTarget('module')
.globalObject('global')
.set('clean', true);
if (env === null || env === void 0 ? void 0 : env.uniqueBundle) {
config.output.filename(`[name].${env.uniqueBundle}.mjs`);
}
}
config.watchOptions({ config.watchOptions({
ignored: [ ignored: [
@ -187,29 +200,47 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
config.optimization.runtimeChunk('single'); config.optimization.runtimeChunk('single');
if (env.commonjs) {
// Set up CommonJS output
config.optimization.splitChunks({ config.optimization.splitChunks({
// chunks: 'all',
cacheGroups: { cacheGroups: {
// globals: {
// test: (module) =>
// module.resource &&
// /[\\/]@nativescript[\\/]core[\\/]globals[\\/]index\.(mjs|js|ts)$/.test(
// module.resource,
// ),
// name: 'globals',
// enforce: true, // ignore size/min-chunk thresholds
// chunks: 'all',
// priority: 30,
// },
defaultVendor: { defaultVendor: {
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
priority: -10, priority: -10,
name: 'vendor', name: 'vendor',
// enforce: true,
chunks: 'all', chunks: 'all',
}, },
}, },
}); });
} else {
// Set up ESM output
// NOTE: this fixes all worker bundling issues
// however it causes issues with angular lazy loading.
// TODO: still need to investigate the right combination of webpack settings there
// TODO: test if standalone lazy loaded routes work, maybe it's just with loadChildren modules?
config.output.chunkFilename('[name].mjs');
// now readd exactly what you want:
config.optimization.splitChunks({
// only split out vendor from the main bundle…
chunks: 'initial',
cacheGroups: {
// no “default” group
default: false,
// only pull node_modules into vendor.js from the *initial* chunk
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial',
priority: -10,
reuseExistingChunk: true,
},
},
});
config.optimization.set('moduleIds', 'named').set('chunkIds', 'named');
}
// look for loaders in // look for loaders in
// - node_modules/@nativescript/webpack/dist/loaders // - node_modules/@nativescript/webpack/dist/loaders
@ -444,17 +475,6 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
// } // }
// ]) // ])
// config.plugin('globals-shim').use(BannerPlugin, [
// {
// // commonjs style
// banner: `require("./globals");`,
// // ESM style
// // banner: `import "./globals";`,
// raw: true,
// entryOnly: true,
// },
// ]);
config.plugin('PlatformSuffixPlugin').use(PlatformSuffixPlugin, [ config.plugin('PlatformSuffixPlugin').use(PlatformSuffixPlugin, [
{ {
extensions: platform === 'visionos' ? [platform, 'ios'] : [platform], extensions: platform === 'visionos' ? [platform, 'ios'] : [platform],