🐛 isPropertyReadonly support accessor assert (#2284)

This commit is contained in:
Kuitos 2022-09-26 20:57:39 +08:00 committed by GitHub
parent 0aaf55a77f
commit 9a343b4074
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 16 deletions

View File

@ -5,24 +5,25 @@ import {
getDefaultTplWrapper,
getWrapperId,
getXPathForElement,
isPropertyReadonly,
nextTask,
sleep,
validateExportLifecycle,
} from '../utils';
test('should wrap the id [1]', () => {
it('should wrap the id [1]', () => {
const id = 'REACT16';
expect(getWrapperId(id)).toBe(`__qiankun_microapp_wrapper_for_${'react_16'}__`);
});
test('should wrap the id [2]', () => {
it('should wrap the id [2]', () => {
const id = 'react16';
expect(getWrapperId(id)).toBe('__qiankun_microapp_wrapper_for_react_16__');
});
test('should wrap string with div', () => {
it('should wrap string with div', () => {
const tpl = '<span>qiankun</span>';
const factory = getDefaultTplWrapper('react16');
@ -34,7 +35,7 @@ test('should wrap string with div', () => {
);
});
test('should be able to validate lifecycle', () => {
it('should be able to validate lifecycle', () => {
const noop = () => undefined;
const export1 = {
@ -71,7 +72,7 @@ test.skip('should be able to suspend', async () => {
expect(diff >= 10).toBeTruthy();
});
test('Deferred should worked [1]', async () => {
it('Deferred should worked [1]', async () => {
const inst = new Deferred();
setTimeout(() => {
@ -82,7 +83,7 @@ test('Deferred should worked [1]', async () => {
expect(ret).toBe(1);
});
test('Deferred should worked [2]', async () => {
it('Deferred should worked [2]', async () => {
const inst = new Deferred();
setTimeout(() => {
@ -100,7 +101,7 @@ test('Deferred should worked [2]', async () => {
expect(err).toBeInstanceOf(Error);
});
test('should getXPathForElement work well', () => {
it('should getXPathForElement work well', () => {
const article = document.createElement('article');
article.innerHTML = `
<div>
@ -140,7 +141,7 @@ it('should nextTick just executed once in one task context', async () => {
expect(counter).toBe(3);
});
it('should genAppInstanceIdByName works well', () => {
it('should genAppInstanceIdByName work well', () => {
const instanceId1 = genAppInstanceIdByName('hello');
expect(instanceId1).toBe('hello');
@ -150,3 +151,34 @@ it('should genAppInstanceIdByName works well', () => {
const instanceId3 = genAppInstanceIdByName('hello');
expect(instanceId3).toBe('hello_2');
});
it('should isPropertyReadonly work well', () => {
const a = {
get name() {
return 'read only';
},
};
expect(isPropertyReadonly(a, 'name')).toBeTruthy();
const b = {
get name() {
return 'read only';
},
set name(_) {},
};
expect(isPropertyReadonly(b, 'name')).toBeFalsy();
const c = {};
Object.defineProperty(c, 'name', { writable: false });
expect(isPropertyReadonly(c, 'name')).toBeTruthy();
const d = {};
Object.defineProperty(d, 'name', { configurable: true });
expect(isPropertyReadonly(d, 'name')).toBeTruthy();
const e = {};
Object.defineProperty(e, 'name', { writable: true });
expect(isPropertyReadonly(e, 'name')).toBeFalsy();
expect(isPropertyReadonly(undefined, 'name')).toBeFalsy();
});

View File

@ -96,27 +96,26 @@ export const isCallable = (fn: any) => {
*/
const propertyReadonlyCacheMap = new WeakMap<any, Record<PropertyKey, boolean>>();
export function isPropertyReadonly(target: any, p?: PropertyKey): boolean {
// 异常返回
if (!target || !p) {
return false;
}
// 取缓存
const targetPropertiesFromCache = propertyReadonlyCacheMap.get(target) || {};
if (typeof targetPropertiesFromCache[p] === 'boolean') {
if (targetPropertiesFromCache[p]) {
return targetPropertiesFromCache[p];
}
// 计算
const propertyDescriptor = Object.getOwnPropertyDescriptor(target, p);
const result = propertyDescriptor?.configurable === false && propertyDescriptor?.writable === false;
const readonly = Boolean(
propertyDescriptor &&
(propertyDescriptor.writable === false || (propertyDescriptor.get && !propertyDescriptor.set)),
);
// 写缓存
targetPropertiesFromCache[p] = result;
targetPropertiesFromCache[p] = readonly;
propertyReadonlyCacheMap.set(target, targetPropertiesFromCache);
return result;
return readonly;
}
const boundedMap = new WeakMap<CallableFunction, boolean>();