Files
Sean Perkins 4a41983098 fix(core): malformed URIs will not throw exception (#29486)
Issue number: resolves #29479

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

If an application includes a malformed URI, an Ionic Framework can
"crash" due to an uncaught exception in parsing the URI for the Ionic
config.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Handle the malformed URI fallback if the config cannot be determined
- Added unit tests for this case

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2024-05-15 19:30:21 +00:00

85 lines
2.1 KiB
TypeScript

import type { IonicConfig } from '../interface';
// TODO(FW-2832): types
export class Config {
private m = new Map<keyof IonicConfig, any>();
reset(configObj: IonicConfig) {
this.m = new Map<keyof IonicConfig, any>(Object.entries(configObj) as any);
}
get(key: keyof IonicConfig, fallback?: any): any {
const value = this.m.get(key);
return value !== undefined ? value : fallback;
}
getBoolean(key: keyof IonicConfig, fallback = false): boolean {
const val = this.m.get(key);
if (val === undefined) {
return fallback;
}
if (typeof val === 'string') {
return val === 'true';
}
return !!val;
}
getNumber(key: keyof IonicConfig, fallback?: number): number {
const val = parseFloat(this.m.get(key));
return isNaN(val) ? (fallback !== undefined ? fallback : NaN) : val;
}
set(key: keyof IonicConfig, value: any) {
this.m.set(key, value);
}
}
export const config = /*@__PURE__*/ new Config();
export const configFromSession = (win: Window): any => {
try {
const configStr = win.sessionStorage.getItem(IONIC_SESSION_KEY);
return configStr !== null ? JSON.parse(configStr) : {};
} catch (e) {
return {};
}
};
export const saveConfig = (win: Window, c: any) => {
try {
win.sessionStorage.setItem(IONIC_SESSION_KEY, JSON.stringify(c));
} catch (e) {
return;
}
};
export const configFromURL = (win: Window) => {
const configObj: any = {};
win.location.search
.slice(1)
.split('&')
.map((entry) => entry.split('='))
.map(([key, value]) => {
try {
return [decodeURIComponent(key), decodeURIComponent(value)];
} catch (e) {
return ['', ''];
}
})
.filter(([key]) => startsWith(key, IONIC_PREFIX))
.map(([key, value]) => [key.slice(IONIC_PREFIX.length), value])
.forEach(([key, value]) => {
configObj[key] = value;
});
return configObj;
};
const startsWith = (input: string, search: string): boolean => {
return input.substr(0, search.length) === search;
};
const IONIC_PREFIX = 'ionic:';
const IONIC_SESSION_KEY = 'ionic-persist-config';