mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 03:31:45 +08:00
chore: cleanup
This commit is contained in:
@ -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 { readyInitAccessibilityCssHelper, readyInitFontScale } from '../accessibility/accessibility-common';
|
||||
import { getAppMainEntry, isAppInBackground, setAppInBackground, setAppMainEntry } from './helpers-common';
|
||||
import { getNativeScriptGlobals } from '../globals/global-utils';
|
||||
|
||||
// prettier-ignore
|
||||
const ORIENTATION_CSS_CLASSES = [
|
||||
@ -28,7 +29,7 @@ const SYSTEM_APPEARANCE_CSS_CLASSES = [
|
||||
`${CSSUtils.CLASS_PREFIX}${CoreTypes.SystemAppearance.dark}`,
|
||||
];
|
||||
|
||||
const globalEvents = global.NativeScriptGlobals.events;
|
||||
const globalEvents = getNativeScriptGlobals().events;
|
||||
|
||||
// helper interface to correctly type Application event handlers
|
||||
interface ApplicationEvents {
|
||||
@ -161,7 +162,7 @@ export class ApplicationCommon {
|
||||
* @internal - should not be constructed by the user.
|
||||
*/
|
||||
constructor() {
|
||||
global.NativeScriptGlobals.appInstanceReady = true;
|
||||
getNativeScriptGlobals().appInstanceReady = true;
|
||||
|
||||
global.__onUncaughtError = (error: NativeScriptError) => {
|
||||
this.notify({
|
||||
@ -507,7 +508,7 @@ export class ApplicationCommon {
|
||||
}
|
||||
|
||||
hasLaunched(): boolean {
|
||||
return global.NativeScriptGlobals && global.NativeScriptGlobals.launched;
|
||||
return getNativeScriptGlobals().launched;
|
||||
}
|
||||
|
||||
private _systemAppearance: 'dark' | 'light' | null;
|
||||
|
@ -42,6 +42,7 @@ import {
|
||||
} from '../accessibility/accessibility-common';
|
||||
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 { getNativeScriptGlobals } from '../globals/global-utils';
|
||||
|
||||
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) => {
|
||||
if (!getImageFetcher()) {
|
||||
initImageCache(args.activity);
|
||||
@ -1376,7 +1377,7 @@ global.NativeScriptGlobals.addEventWiring(() => {
|
||||
});
|
||||
});
|
||||
|
||||
global.NativeScriptGlobals.addEventWiring(() => {
|
||||
getNativeScriptGlobals().addEventWiring(() => {
|
||||
Application.android.on('activityStopped', (args) => {
|
||||
if (getImageFetcher()) {
|
||||
getImageFetcher().closeCache();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { parse } from 'css-tree';
|
||||
import * as cssTree from 'css-tree';
|
||||
|
||||
function mapSelectors(selector: string): string[] {
|
||||
if (!selector) {
|
||||
@ -129,7 +129,7 @@ function transformAst(node, css, type = null) {
|
||||
|
||||
export function cssTreeParse(css, source): any {
|
||||
const errors = [];
|
||||
const ast = parse(css, {
|
||||
const ast = cssTree.parse(css, {
|
||||
parseValue: false,
|
||||
parseAtrulePrelude: false,
|
||||
parseRulePrelude: false,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { encoding as textEncoding } from '../text';
|
||||
import { ios as iosUtils } from '../utils';
|
||||
import { getFileExtension } from '../utils/utils-shared';
|
||||
import { iOSNativeHelper } from '../utils';
|
||||
|
||||
// TODO: Implement all the APIs receiving callback using async blocks
|
||||
// TODO: Check whether we need try/catch blocks for the iOS implementation
|
||||
@ -258,7 +257,7 @@ export class FileSystemAccess {
|
||||
}
|
||||
|
||||
public getCurrentAppPath(): string {
|
||||
return iosUtils.getCurrentAppPath();
|
||||
return iOSNativeHelper.getCurrentAppPath();
|
||||
}
|
||||
|
||||
public copy = this.copySync.bind(this);
|
||||
@ -612,8 +611,24 @@ export class FileSystemAccess {
|
||||
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 {
|
||||
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) {
|
||||
@ -685,7 +700,7 @@ export class FileSystemAccess {
|
||||
}
|
||||
|
||||
public joinPaths(paths: string[]): string {
|
||||
return iosUtils.joinPaths(...paths);
|
||||
return iOSNativeHelper.joinPaths(...paths);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import * as definition from './fps-native';
|
||||
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 onFrame: (currentTimeMillis: number) => void;
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
import * as definition from './fps-native';
|
||||
|
||||
@NativeClass
|
||||
class FrameHandlerImpl extends NSObject {
|
||||
private _owner: WeakRef<FPSCallback>;
|
||||
@ -23,7 +21,7 @@ class FrameHandlerImpl extends NSObject {
|
||||
};
|
||||
}
|
||||
|
||||
export class FPSCallback implements definition.FPSCallback {
|
||||
export class FPSCallback {
|
||||
public running: boolean;
|
||||
private onFrame: Function;
|
||||
private displayLink: CADisplayLink;
|
||||
|
2
packages/core/global-types.d.ts
vendored
2
packages/core/global-types.d.ts
vendored
@ -26,7 +26,7 @@ declare interface NativeScriptError extends Error {
|
||||
|
||||
//Augment the NodeJS global type with our own extensions
|
||||
declare module globalThis {
|
||||
var NativeScriptHasInitGlobal: boolean;
|
||||
var NativeScriptHasPolyfilled: boolean;
|
||||
var NativeScriptGlobals: {
|
||||
/**
|
||||
* Global framework event handling
|
||||
|
74
packages/core/globals/global-utils.ts
Normal file
74
packages/core/globals/global-utils.ts
Normal 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;
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
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 animationFrame from '../animation-frame';
|
||||
import * as mediaQueryList from '../media-query-list';
|
||||
@ -50,6 +48,230 @@ interface ExtensionMap {
|
||||
[originalFileExtension: string]: string;
|
||||
}
|
||||
|
||||
// ts-helpers
|
||||
// Required by V8 snapshot generator
|
||||
if (!global.__extends) {
|
||||
global.__extends = function (d, b) {
|
||||
for (const p in b) {
|
||||
if (b.hasOwnProperty(p)) {
|
||||
d[p] = b[p];
|
||||
}
|
||||
}
|
||||
function __() {
|
||||
this.constructor = d;
|
||||
}
|
||||
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
|
||||
};
|
||||
}
|
||||
|
||||
// Bind the tslib helpers to global scope.
|
||||
// This is needed when we don't use importHelpers, which
|
||||
// breaks extending native-classes
|
||||
for (const fnName of Object.getOwnPropertyNames(tslib)) {
|
||||
if (typeof tslib[fnName] !== 'function') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fnName in global) {
|
||||
// Don't override globals that are already defined (ex. __extends)
|
||||
continue;
|
||||
}
|
||||
|
||||
global[fnName] = tslib[fnName];
|
||||
}
|
||||
|
||||
// module helpers
|
||||
const defaultExtensionMap: ExtensionMap = {
|
||||
'.js': '.js',
|
||||
'.ts': '.js',
|
||||
'.kt': '.js',
|
||||
'.css': '.css',
|
||||
'.scss': '.css',
|
||||
'.less': '.css',
|
||||
'.sass': '.css',
|
||||
'.xml': '.xml',
|
||||
};
|
||||
|
||||
// Cast to <any> because moduleResolvers is read-only in definitions
|
||||
global.moduleResolvers = [global.require];
|
||||
|
||||
global.registerModule = function (name: string, loader: ModuleLoader): void {
|
||||
modules.set(name, { loader, moduleId: name });
|
||||
};
|
||||
|
||||
global._unregisterModule = function _unregisterModule(name: string): void {
|
||||
modules.delete(name);
|
||||
};
|
||||
|
||||
global._isModuleLoadedForUI = function _isModuleLoadedForUI(moduleName: string): boolean {
|
||||
return modulesLoadedForUI.has(moduleName);
|
||||
};
|
||||
|
||||
global.registerWebpackModules = function registerWebpackModules(context: Context, extensionMap: ExtensionMap = {}) {
|
||||
context.keys().forEach((moduleId) => {
|
||||
const extDotIndex = moduleId.lastIndexOf('.');
|
||||
const base = moduleId.substring(0, extDotIndex);
|
||||
const originalExt = moduleId.substring(extDotIndex);
|
||||
const registerExt = extensionMap[originalExt] || defaultExtensionMap[originalExt] || originalExt;
|
||||
|
||||
// We prefer source files for webpack scenarios before compilation leftovers,
|
||||
// e. g. if we get a .js and .ts for the same module, the .js is probably the compiled version of the .ts file,
|
||||
// so we register the .ts with higher priority, similar is the case with us preferring the .scss to .css
|
||||
const isSourceFile = originalExt !== registerExt;
|
||||
const registerName = base + registerExt;
|
||||
|
||||
const registerWithName = (nickName: string) => {
|
||||
modules.set(nickName, {
|
||||
moduleId,
|
||||
loader: () => {
|
||||
return context(moduleId);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (registerName.startsWith('./') && registerName.endsWith('.js')) {
|
||||
const jsNickNames = [
|
||||
// This is extremely short version like "main-page" that was promoted to be used with global.registerModule("module-name", loaderFunc);
|
||||
registerName.substring(2, registerName.length - 5),
|
||||
// This is for supporting module names like "./main/main-page"
|
||||
registerName.substring(0, registerName.length - 3),
|
||||
// This is for supporting module names like "main/main-page.js"
|
||||
registerName.substring(2),
|
||||
];
|
||||
|
||||
jsNickNames.forEach((jsNickName) => {
|
||||
if (isSourceFile || !global.moduleExists(jsNickName)) {
|
||||
registerWithName(jsNickName);
|
||||
}
|
||||
});
|
||||
} else if (registerName.startsWith('./')) {
|
||||
const moduleNickNames = [
|
||||
// This is for supporting module names like "main/main-page.xml"
|
||||
registerName.substring(2),
|
||||
];
|
||||
|
||||
moduleNickNames.forEach((moduleNickName) => {
|
||||
if (!global.moduleExists(moduleNickName)) {
|
||||
registerWithName(moduleNickName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isSourceFile || !global.moduleExists(registerName)) {
|
||||
registerWithName(registerName);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
global.moduleExists = function moduleExists(name: string): boolean {
|
||||
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);
|
||||
};
|
||||
|
||||
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);
|
||||
if (moduleInfo) {
|
||||
if (isUIModule) {
|
||||
modulesLoadedForUI.add(moduleInfo.moduleId);
|
||||
}
|
||||
|
||||
const result = moduleInfo.loader(name);
|
||||
|
||||
if (result.enableAutoAccept) {
|
||||
result.enableAutoAccept();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const resolver of global.moduleResolvers) {
|
||||
const result = resolver(name);
|
||||
if (result) {
|
||||
modules.set(name, { moduleId: name, loader: () => result });
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
function registerOnGlobalContext(moduleName: string, exportName: string): void {
|
||||
Object.defineProperty(global, exportName, {
|
||||
get: function () {
|
||||
@ -70,70 +292,6 @@ function registerOnGlobalContext(moduleName: string, exportName: string): void {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
@ -143,270 +301,41 @@ export function installPolyfills(moduleName: string, exportNames: string[]) {
|
||||
}
|
||||
}
|
||||
|
||||
export function initGlobal() {
|
||||
if (!global.NativeScriptHasInitGlobal) {
|
||||
global.NativeScriptHasInitGlobal = true;
|
||||
// init global state handler
|
||||
global.NativeScriptGlobals = new NativeScriptGlobalState();
|
||||
if (!global.NativeScriptHasPolyfilled) {
|
||||
global.NativeScriptHasPolyfilled = true;
|
||||
console.log('Installing polyfills...');
|
||||
// DOM api polyfills
|
||||
global.registerModule('timer', () => timer);
|
||||
installPolyfills('timer', ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval']);
|
||||
|
||||
// ts-helpers
|
||||
// Required by V8 snapshot generator
|
||||
if (!global.__extends) {
|
||||
global.__extends = function (d, b) {
|
||||
for (const p in b) {
|
||||
if (b.hasOwnProperty(p)) {
|
||||
d[p] = b[p];
|
||||
}
|
||||
}
|
||||
function __() {
|
||||
this.constructor = d;
|
||||
}
|
||||
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
|
||||
};
|
||||
}
|
||||
global.registerModule('animation', () => animationFrame);
|
||||
installPolyfills('animation', ['requestAnimationFrame', 'cancelAnimationFrame']);
|
||||
|
||||
// Bind the tslib helpers to global scope.
|
||||
// This is needed when we don't use importHelpers, which
|
||||
// breaks extending native-classes
|
||||
for (const fnName of Object.getOwnPropertyNames(tslib)) {
|
||||
if (typeof tslib[fnName] !== 'function') {
|
||||
continue;
|
||||
}
|
||||
global.registerModule('media-query-list', () => mediaQueryList);
|
||||
installPolyfills('media-query-list', ['matchMedia', 'MediaQueryList']);
|
||||
|
||||
if (fnName in global) {
|
||||
// Don't override globals that are already defined (ex. __extends)
|
||||
continue;
|
||||
}
|
||||
global.registerModule('text', () => text);
|
||||
installPolyfills('text', ['TextDecoder', 'TextEncoder']);
|
||||
|
||||
global[fnName] = tslib[fnName];
|
||||
}
|
||||
global.registerModule('xhr', () => xhrImpl);
|
||||
installPolyfills('xhr', ['XMLHttpRequest', 'FormData', 'Blob', 'File', 'FileReader']);
|
||||
|
||||
// module helpers
|
||||
const modules: Map<string, { moduleId: string; loader: ModuleLoader }> = new Map<string, { moduleId: string; loader: ModuleLoader }>();
|
||||
const modulesLoadedForUI = new Set<string>();
|
||||
const defaultExtensionMap: ExtensionMap = {
|
||||
'.js': '.js',
|
||||
'.ts': '.js',
|
||||
'.kt': '.js',
|
||||
'.css': '.css',
|
||||
'.scss': '.css',
|
||||
'.less': '.css',
|
||||
'.sass': '.css',
|
||||
'.xml': '.xml',
|
||||
};
|
||||
global.registerModule('fetch', () => fetchPolyfill);
|
||||
installPolyfills('fetch', ['fetch', 'Headers', 'Request', 'Response']);
|
||||
|
||||
// Cast to <any> because moduleResolvers is read-only in definitions
|
||||
global.moduleResolvers = [global.require];
|
||||
global.registerModule('wgc', () => wgc);
|
||||
installPolyfills('wgc', ['atob', 'btoa']);
|
||||
|
||||
global.registerModule = function (name: string, loader: ModuleLoader): void {
|
||||
modules.set(name, { loader, moduleId: name });
|
||||
};
|
||||
global.registerModule('crypto', () => cryptoImpl);
|
||||
installPolyfills('crypto', ['Crypto']);
|
||||
|
||||
global._unregisterModule = function _unregisterModule(name: string): void {
|
||||
modules.delete(name);
|
||||
};
|
||||
global.registerModule('subtle', () => subtleCryptoImpl);
|
||||
installPolyfills('subtle-crypto', ['Subtle']);
|
||||
|
||||
global._isModuleLoadedForUI = function _isModuleLoadedForUI(moduleName: string): boolean {
|
||||
return modulesLoadedForUI.has(moduleName);
|
||||
};
|
||||
global.crypto = new global.Crypto();
|
||||
|
||||
global.registerWebpackModules = function registerWebpackModules(context: Context, extensionMap: ExtensionMap = {}) {
|
||||
context.keys().forEach((moduleId) => {
|
||||
const extDotIndex = moduleId.lastIndexOf('.');
|
||||
const base = moduleId.substr(0, extDotIndex);
|
||||
const originalExt = moduleId.substr(extDotIndex);
|
||||
const registerExt = extensionMap[originalExt] || defaultExtensionMap[originalExt] || originalExt;
|
||||
|
||||
// We prefer source files for webpack scenarios before compilation leftovers,
|
||||
// e. g. if we get a .js and .ts for the same module, the .js is probably the compiled version of the .ts file,
|
||||
// so we register the .ts with higher priority, similar is the case with us preferring the .scss to .css
|
||||
const isSourceFile = originalExt !== registerExt;
|
||||
const registerName = base + registerExt;
|
||||
|
||||
const registerWithName = (nickName: string) => {
|
||||
modules.set(nickName, {
|
||||
moduleId,
|
||||
loader: () => {
|
||||
return context(moduleId);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (registerName.startsWith('./') && registerName.endsWith('.js')) {
|
||||
const jsNickNames = [
|
||||
// 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),
|
||||
// This is for supporting module names like "./main/main-page"
|
||||
registerName.substr(0, registerName.length - 3),
|
||||
// This is for supporting module names like "main/main-page.js"
|
||||
registerName.substr(2),
|
||||
];
|
||||
|
||||
jsNickNames.forEach((jsNickName) => {
|
||||
if (isSourceFile || !global.moduleExists(jsNickName)) {
|
||||
registerWithName(jsNickName);
|
||||
}
|
||||
});
|
||||
} else if (registerName.startsWith('./')) {
|
||||
const moduleNickNames = [
|
||||
// This is for supporting module names like "main/main-page.xml"
|
||||
registerName.substr(2),
|
||||
];
|
||||
|
||||
moduleNickNames.forEach((moduleNickName) => {
|
||||
if (!global.moduleExists(moduleNickName)) {
|
||||
registerWithName(moduleNickName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isSourceFile || !global.moduleExists(registerName)) {
|
||||
registerWithName(registerName);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
global.moduleExists = function moduleExists(name: string): boolean {
|
||||
return modules.has(name);
|
||||
};
|
||||
|
||||
global.loadModule = function loadModule(name: string, isUIModule = false): any {
|
||||
const moduleInfo = modules.get(name);
|
||||
if (moduleInfo) {
|
||||
if (isUIModule) {
|
||||
modulesLoadedForUI.add(moduleInfo.moduleId);
|
||||
}
|
||||
|
||||
const result = moduleInfo.loader(name);
|
||||
|
||||
if (result.enableAutoAccept) {
|
||||
result.enableAutoAccept();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const resolver of global.moduleResolvers) {
|
||||
const result = resolver(name);
|
||||
if (result) {
|
||||
modules.set(name, { moduleId: name, loader: () => result });
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// DOM api polyfills
|
||||
global.registerModule('timer', () => timer);
|
||||
installPolyfills('timer', ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval']);
|
||||
|
||||
global.registerModule('animation', () => animationFrame);
|
||||
installPolyfills('animation', ['requestAnimationFrame', 'cancelAnimationFrame']);
|
||||
|
||||
global.registerModule('media-query-list', () => mediaQueryList);
|
||||
installPolyfills('media-query-list', ['matchMedia', 'MediaQueryList']);
|
||||
|
||||
global.registerModule('text', () => text);
|
||||
installPolyfills('text', ['TextDecoder', 'TextEncoder']);
|
||||
|
||||
global.registerModule('xhr', () => xhrImpl);
|
||||
installPolyfills('xhr', ['XMLHttpRequest', 'FormData', 'Blob', 'File', 'FileReader']);
|
||||
|
||||
global.registerModule('fetch', () => fetchPolyfill);
|
||||
installPolyfills('fetch', ['fetch', 'Headers', 'Request', 'Response']);
|
||||
|
||||
global.registerModule('wgc', () => wgc);
|
||||
installPolyfills('wgc', ['atob', 'btoa']);
|
||||
|
||||
global.registerModule('crypto', () => cryptoImpl);
|
||||
installPolyfills('crypto', ['Crypto']);
|
||||
|
||||
global.registerModule('subtle', () => subtleCryptoImpl);
|
||||
installPolyfills('subtle-crypto', ['Subtle']);
|
||||
|
||||
global.crypto = new global.Crypto();
|
||||
|
||||
// global.registerModule('abortcontroller', () => require('../abortcontroller'));
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
// global.registerModule('abortcontroller', () => require('../abortcontroller'));
|
||||
// installPolyfills('abortcontroller', ['AbortController', 'AbortSignal']);
|
||||
}
|
||||
|
||||
declare const jest: any;
|
||||
@ -414,11 +343,7 @@ function isTestingEnv() {
|
||||
return typeof jest !== 'undefined' || global.__UNIT_TEST__;
|
||||
}
|
||||
|
||||
console.log('global.NativeScriptHasInitGlobal:', global.NativeScriptHasInitGlobal);
|
||||
console.log('isTestingEnv():', isTestingEnv());
|
||||
if (!global.NativeScriptHasInitGlobal && !isTestingEnv()) {
|
||||
initGlobal();
|
||||
}
|
||||
|
||||
// ensure the Application instance is initialized before any other module imports it.
|
||||
import '../application';
|
||||
|
@ -160,10 +160,6 @@ export function enable(mode: InstrumentationMode = 'counters') {
|
||||
}
|
||||
|
||||
try {
|
||||
// const appConfig = require('~/package.json');
|
||||
// @ts-ignore
|
||||
// const appConfig = await import('~/package.json');
|
||||
console.log('profiling appConfig:', appConfig);
|
||||
if (appConfig && appConfig.profiling) {
|
||||
enable(appConfig.profiling);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Point, Position } from './view-interfaces';
|
||||
import type { GestureTypes, GestureEventData } from '../../gestures';
|
||||
|
||||
import { getNativeScriptGlobals } from '../../../globals/global-utils';
|
||||
import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUserInteractionEnabledProperty, testIDProperty, AndroidHelper } from './view-common';
|
||||
import { paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../../styling/style-properties';
|
||||
import { Length } from '../../styling/length-shared';
|
||||
@ -143,7 +143,7 @@ function initializeDialogFragment() {
|
||||
};
|
||||
|
||||
// Fist fire application.android global event
|
||||
global.NativeScriptGlobals.events.notify(args);
|
||||
getNativeScriptGlobals().events.notify(args);
|
||||
if (args.cancel) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { getNativeScriptGlobals } from '../../globals/global-utils';
|
||||
import { ViewBase } from '../core/view-base';
|
||||
import { View } from '../core/view';
|
||||
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
|
||||
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';
|
||||
try {
|
||||
console.log('style-scope here??');
|
||||
// @ts-ignore
|
||||
// const appConfig = require('~/package.json');
|
||||
// console.log('style-scope appConfig:', appConfig);
|
||||
if (appConfig) {
|
||||
if (appConfig.cssParser === 'rework') {
|
||||
parser = 'rework';
|
||||
@ -497,8 +488,8 @@ const loadCss = profile(`"style-scope".loadCss`, (cssModule: string): void => {
|
||||
}
|
||||
});
|
||||
|
||||
global.NativeScriptGlobals.events.on('cssChanged', <any>onCssChanged);
|
||||
global.NativeScriptGlobals.events.on('livesync', onLiveSync);
|
||||
getNativeScriptGlobals().events.on('cssChanged', <any>onCssChanged);
|
||||
getNativeScriptGlobals().events.on('livesync', onLiveSync);
|
||||
|
||||
// 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)
|
||||
@ -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
|
||||
export const loadAppCSS = profile('"style-scope".loadAppCSS', (args: LoadAppCSSEventData) => {
|
||||
loadCss(args.cssFile, null, null);
|
||||
global.NativeScriptGlobals.events.off('loadAppCss', loadAppCSS);
|
||||
getNativeScriptGlobals().events.off('loadAppCss', loadAppCSS);
|
||||
});
|
||||
|
||||
if (Application.hasLaunched()) {
|
||||
@ -521,7 +512,7 @@ if (Application.hasLaunched()) {
|
||||
null,
|
||||
);
|
||||
} else {
|
||||
global.NativeScriptGlobals.events.on('loadAppCss', loadAppCSS);
|
||||
getNativeScriptGlobals().events.on('loadAppCss', loadAppCSS);
|
||||
}
|
||||
|
||||
export class CssState {
|
||||
|
@ -95,10 +95,7 @@ function getCurrentAppPath(): string {
|
||||
if (!global.__dirname) {
|
||||
global.__dirname = typeof __dirname !== 'undefined' ? __dirname : import.meta.dirname;
|
||||
}
|
||||
console.log('getCurrentAppPath __dirname:', __dirname);
|
||||
const currentDir = global.__dirname;
|
||||
console.log('getCurrentAppPath global.__dirname:', global.__dirname);
|
||||
console.log('getCurrentAppPath currentDir:', currentDir);
|
||||
const tnsModulesIndex = currentDir.indexOf('/tns_modules');
|
||||
|
||||
// Module not hosted in ~/tns_modules when bundled. Use current dir.
|
||||
|
@ -1,6 +1,11 @@
|
||||
// @ts-nocheck
|
||||
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
|
||||
global.__UNIT_TEST__ = true;
|
||||
global.__DEV__ = true;
|
||||
|
@ -127,25 +127,38 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
|
||||
.add('@nativescript/core/inspector_modules');
|
||||
});
|
||||
|
||||
// config.merge({
|
||||
// experiments: {
|
||||
// // enable ES module syntax (import/exports)
|
||||
// outputModule: true,
|
||||
// },
|
||||
// });
|
||||
if (env.commonjs) {
|
||||
// CommonJS output
|
||||
config.output
|
||||
.path(outputPath)
|
||||
.pathinfo(false)
|
||||
.publicPath('')
|
||||
.libraryTarget('commonjs')
|
||||
.globalObject('global')
|
||||
.set('clean', true);
|
||||
if (env === null || env === void 0 ? void 0 : env.uniqueBundle) {
|
||||
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('')
|
||||
// .set('module', true)
|
||||
// .libraryTarget('module')
|
||||
.libraryTarget('commonjs')
|
||||
.globalObject('global')
|
||||
.set('clean', true);
|
||||
|
||||
if (env?.uniqueBundle) {
|
||||
config.output.filename(`[name].${env.uniqueBundle}.js`);
|
||||
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({
|
||||
@ -187,29 +200,47 @@ export default function (config: Config, env: IWebpackEnv = _env): Config {
|
||||
|
||||
config.optimization.runtimeChunk('single');
|
||||
|
||||
config.optimization.splitChunks({
|
||||
// chunks: 'all',
|
||||
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: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: -10,
|
||||
name: 'vendor',
|
||||
// enforce: true,
|
||||
chunks: 'all',
|
||||
if (env.commonjs) {
|
||||
// Set up CommonJS output
|
||||
config.optimization.splitChunks({
|
||||
cacheGroups: {
|
||||
defaultVendor: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: -10,
|
||||
name: 'vendor',
|
||||
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 re‑add 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
|
||||
// - 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, [
|
||||
{
|
||||
extensions: platform === 'visionos' ? [platform, 'ios'] : [platform],
|
||||
|
Reference in New Issue
Block a user