From 09092a2b8c0ccc76c2be66bab25498ff25a87c35 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Fri, 11 Oct 2024 18:16:13 +0800 Subject: [PATCH 1/6] feat(ios): add HippyFontChangeTriggerNotification for font update 2 --- .../component/textinput/HippyShadowTextView.mm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/renderer/native/ios/renderer/component/textinput/HippyShadowTextView.mm b/renderer/native/ios/renderer/component/textinput/HippyShadowTextView.mm index 83b518f50e1..0d38fba2fc0 100644 --- a/renderer/native/ios/renderer/component/textinput/HippyShadowTextView.mm +++ b/renderer/native/ios/renderer/component/textinput/HippyShadowTextView.mm @@ -192,17 +192,15 @@ - (void)dirtyText:(BOOL)needToDoLayout { } - (void)amendLayoutBeforeMount:(NSMutableSet *)blocks { - [super amendLayoutBeforeMount:blocks]; - - if (NativeRenderUpdateLifecycleComputed == _propagationLifecycle) { - return; + if (NativeRenderUpdateLifecycleComputed != _propagationLifecycle) { + //Set needs layout for font change event, etc. + NSNumber *currentTag = self.hippyTag; + [blocks addObject:^(NSDictionary *viewRegistry, UIView * _Nullable lazyCreatedView) { + UIView *view = lazyCreatedView ?: viewRegistry[currentTag]; + [view setNeedsLayout]; + }]; } - //Set needs layout for font change event, etc. - NSNumber *currentTag = self.hippyTag; - [blocks addObject:^(NSDictionary *viewRegistry, UIView * _Nullable lazyCreatedView) { - UIView *view = lazyCreatedView ?: viewRegistry[currentTag]; - [view setNeedsLayout]; - }]; + [super amendLayoutBeforeMount:blocks]; } From 26a9d93d56767777a39d3d593177ba97093f7308 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Sat, 12 Oct 2024 15:51:37 +0800 Subject: [PATCH 2/6] refactor(ios): minor update of UIManager and ShadowView --- .../native/ios/renderer/HippyUIManager.mm | 35 ++++++++++--------- .../component/view/HippyShadowView.mm | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/renderer/native/ios/renderer/HippyUIManager.mm b/renderer/native/ios/renderer/HippyUIManager.mm index c24a2d3df9d..140acda23c9 100644 --- a/renderer/native/ios/renderer/HippyUIManager.mm +++ b/renderer/native/ios/renderer/HippyUIManager.mm @@ -201,16 +201,16 @@ @interface HippyUIManager() { NSHashTable> *_componentTransactionListeners; std::mutex _renderQueueLock; - NSMutableDictionary *_viewManagers; - NSArray *_extraComponents; - - NSMutableArray> *_imageProviders; } - +/// All managed ViewManagers +@property (atomic, strong) NSMutableDictionary *viewManagers; +/// All extra components +@property (atomic, strong) NSArray *extraComponents; @end + @implementation HippyUIManager @synthesize domManager = _domManager; @@ -675,36 +675,37 @@ - (void)updateView:(nonnull NSNumber *)componentTag - (__kindof HippyViewManager *)viewManagerForViewName:(NSString *)viewName { HippyBridge *strongBridge = self.bridge; - if (!_viewManagers) { - _viewManagers = [NSMutableDictionary dictionary]; - if (_extraComponents) { - for (Class cls in _extraComponents) { + if (!self.viewManagers) { + NSMutableDictionary *viewManagers = [NSMutableDictionary dictionary]; + if (self.extraComponents) { + for (Class cls in self.extraComponents) { NSString *viewName = viewNameFromViewManagerClass(cls); - HippyAssert(![_viewManagers objectForKey:viewName], + HippyAssert(![viewManagers objectForKey:viewName], @"duplicated component %@ for class %@ and %@", viewName, NSStringFromClass(cls), - NSStringFromClass([_viewManagers objectForKey:viewName])); - [_viewManagers setObject:cls forKey:viewName]; + NSStringFromClass([viewManagers objectForKey:viewName])); + [viewManagers setObject:cls forKey:viewName]; } } NSArray *classes = HippyGetViewManagerClasses(strongBridge); NSMutableDictionary *defaultViewManagerClasses = [NSMutableDictionary dictionaryWithCapacity:[classes count]]; for (Class cls in classes) { NSString *viewName = viewNameFromViewManagerClass(cls); - if ([_viewManagers objectForKey:viewName]) { + if ([viewManagers objectForKey:viewName]) { continue; } [defaultViewManagerClasses setObject:cls forKey:viewName]; } - [_viewManagers addEntriesFromDictionary:defaultViewManagerClasses]; + [viewManagers addEntriesFromDictionary:defaultViewManagerClasses]; + self.viewManagers = viewManagers; } // Get and instantiate the class - id object = [_viewManagers objectForKey:viewName]; + id object = [self.viewManagers objectForKey:viewName]; if (object_isClass(object)) { HippyViewManager *viewManager = [object new]; viewManager.bridge = strongBridge; NSAssert([viewManager isKindOfClass:[HippyViewManager class]], @"Must be a HippyViewManager instance"); - [_viewManagers setObject:viewManager forKey:viewName]; + [self.viewManagers setObject:viewManager forKey:viewName]; object = viewManager; } return object; @@ -1125,7 +1126,7 @@ - (void)dispatchFunction:(const std::string &)functionName } - (void)registerExtraComponent:(NSArray *)extraComponents { - _extraComponents = extraComponents; + self.extraComponents = extraComponents; } diff --git a/renderer/native/ios/renderer/component/view/HippyShadowView.mm b/renderer/native/ios/renderer/component/view/HippyShadowView.mm index 17875abdf35..8f59aacd67b 100644 --- a/renderer/native/ios/renderer/component/view/HippyShadowView.mm +++ b/renderer/native/ios/renderer/component/view/HippyShadowView.mm @@ -97,7 +97,7 @@ - (instancetype)init { if ((self = [super init])) { _propagationLifecycle = NativeRenderUpdateLifecycleUninitialized; _frame = CGRectMake(0, 0, NAN, NAN); - _objectSubviews = [NSMutableArray arrayWithCapacity:8]; + _objectSubviews = [NSMutableArray array]; _confirmedLayoutDirection = hippy::Direction::Inherit; _layoutDirection = hippy::Direction::Inherit; } From 9a62008c145acc702897472553b911687229587b Mon Sep 17 00:00:00 2001 From: zealotchen Date: Mon, 14 Oct 2024 20:51:51 +0800 Subject: [PATCH 3/6] fix vue2 css match error --- .../hippy-vue-css-loader/src/css-loader.ts | 33 +++++++++++-------- .../src/style-match/css-map.ts | 22 ++----------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/driver/js/packages/hippy-vue-css-loader/src/css-loader.ts b/driver/js/packages/hippy-vue-css-loader/src/css-loader.ts index 7bb3b17ee38..9544b8bd140 100644 --- a/driver/js/packages/hippy-vue-css-loader/src/css-loader.ts +++ b/driver/js/packages/hippy-vue-css-loader/src/css-loader.ts @@ -32,14 +32,17 @@ let sourceId = 0; function hippyVueCSSLoader(this: any, source: any) { const options = getOptions(this); const parsed = parseCSS(source, { source: sourceId }); - const hash = crypto.createHash('shake256', { outputLength: 3 }); + + const majorNodeVersion = parseInt(process.versions.node.split('.')[0], 10); + const hashType = majorNodeVersion >= 17 ? 'md5' : 'md4'; + const hash = crypto.createHash(hashType); const contentHash = hash.update(source).digest('hex'); sourceId += 1; - const rulesAst = parsed.stylesheet.rules.filter((n: any) => n.type === 'rule').map((n: any) => ([ - contentHash, - n.selectors, - // filter comment declaration and empty declaration - n.declarations.filter(dec => dec.type !== 'comment').map((dec: any) => { + const rulesAst = parsed.stylesheet.rules.filter((n: any) => n.type === 'rule').map((n: any) => ({ + hash: contentHash, + selectors: n.selectors, + + declarations: n.declarations.map((dec: any) => { let { value } = dec; const isVariableColor = dec.property?.startsWith('-') && typeof value === 'string' && ( @@ -52,14 +55,18 @@ function hippyVueCSSLoader(this: any, source: any) { if (dec.property && (dec.property.toLowerCase().indexOf('color') > -1 || isVariableColor)) { value = translateColor(value); } - return [dec.property, value]; + return { + type: dec.type, + property: dec.property, + value, + }; }), - ])).filter(rule => rule[2].length > 0); - const code = `(function(n) { - if (!global[n]) { - global[n] = []; + })); + const code = `(function() { + if (!global['${GLOBAL_STYLE_NAME}']) { + global['${GLOBAL_STYLE_NAME}'] = []; } - global[n] = global[n].concat(${JSON.stringify(rulesAst)}); + global['${GLOBAL_STYLE_NAME}'] = global['${GLOBAL_STYLE_NAME}'].concat(${JSON.stringify(rulesAst)}); if(module.hot) { module.hot.dispose(() => { @@ -70,7 +77,7 @@ function hippyVueCSSLoader(this: any, source: any) { global['${GLOBAL_DISPOSE_STYLE_NAME}'] = global['${GLOBAL_DISPOSE_STYLE_NAME}'].concat('${contentHash}'); }) } - })('${GLOBAL_STYLE_NAME}')`; + })()`; return `module.exports=${code}`; } diff --git a/driver/js/packages/hippy-vue-next-style-parser/src/style-match/css-map.ts b/driver/js/packages/hippy-vue-next-style-parser/src/style-match/css-map.ts index 2eb77cef3ac..29e021fa60a 100644 --- a/driver/js/packages/hippy-vue-next-style-parser/src/style-match/css-map.ts +++ b/driver/js/packages/hippy-vue-next-style-parser/src/style-match/css-map.ts @@ -34,9 +34,6 @@ import { SelectorsMap } from './css-selectors-match'; import { parseSelector } from './parser'; import { HIPPY_GLOBAL_STYLE_NAME, HIPPY_GLOBAL_DISPOSE_STYLE_NAME } from './'; -type Declaration = [property: string, value: string | number]; -export type ASTRule = [hash: string, selectors: string[], declarations: Declaration[]]; - // style load hook const beforeLoadStyleHook: Function = (declaration: Function): Function => declaration; @@ -73,7 +70,7 @@ function createSimpleSelectorFromAst(ast) { ? new AttributeSelector(ast.property, ast.test, ast.value) : new AttributeSelector(ast.property); default: - return new InvalidSelector(new Error('Unknown selector.'));; + return null; } } @@ -128,23 +125,10 @@ function createSelector(sel) { * @param beforeLoadStyle */ export function fromAstNodes( - astRules: Array = [], + astRules: CssAttribute[] = [], beforeLoadStyle?: Function, ): RuleSet[] { - const rules = astRules.map(rule => { - if (!Array.isArray(rule)) return rule; - const [hash, selectors, declarations] = rule as ASTRule; - return { - hash, - selectors, - declarations: declarations.map(([property, value]) => ({ - type: 'declaration', - property, - value, - })), - }; - }); - return rules.map((rule) => { + return astRules.map((rule) => { const declarations = rule.declarations .filter(isDeclaration) // use default hook when there is no hook passed in From 9f34b100ac29afc61058032e665546d116636439 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Sat, 12 Oct 2024 17:58:25 +0800 Subject: [PATCH 4/6] fix(ios): thread race of bundle load op in very small scenarios --- framework/ios/base/bridge/HippyBridge.mm | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index 1de3a8eecb1..4f644c7c684 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -183,7 +183,7 @@ @interface HippyBridge() { /// Bundle fetch operation queue (concurrent) @property (nonatomic, strong) NSOperationQueue *bundleQueue; /// Record the last execute operation for adding execution dependency. -@property (atomic, strong, nullable) NSOperation *lastExecuteOperation; +@property (nonatomic, strong, nullable) NSOperation *lastExecuteOperation; /// Cached Dimensions info,will be passed to JS Side. @property (atomic, strong) NSDictionary *cachedDimensionsInfo; @@ -591,13 +591,17 @@ - (void)beginLoadingBundle:(NSURL *)bundleURL strongSelf.valid, script]; HippyLogError(@"%@", errMsg); completion(bundleURL, HippyErrorWithMessage(errMsg)); - strongSelf.lastExecuteOperation = nil; + @synchronized (self) { + strongSelf.lastExecuteOperation = nil; + } return; } [strongSelf executeJSCode:script sourceURL:bundleURL onCompletion:^(id result, NSError *error) { HippyLogInfo(@"End executing bundle(%s)", HP_CSTR_NOT_NULL(bundleURL.absoluteString.lastPathComponent.UTF8String)); - strongSelf.lastExecuteOperation = nil; + @synchronized (self) { + strongSelf.lastExecuteOperation = nil; + } if (completion) { completion(bundleURL, error); } @@ -624,13 +628,18 @@ - (void)beginLoadingBundle:(NSURL *)bundleURL // Add dependency, make sure that doing fetch before execute, // and all execution operations must be queued. [executeOperation addDependency:fetchOperation]; - if (self.lastExecuteOperation) { - [executeOperation addDependency:self.lastExecuteOperation]; + @synchronized (self) { + NSOperation *lastOp = self.lastExecuteOperation; + if (lastOp) { + [executeOperation addDependency:lastOp]; + } } // Enqueue operation [_bundleQueue addOperations:@[fetchOperation, executeOperation] waitUntilFinished:NO]; - self.lastExecuteOperation = executeOperation; + @synchronized (self) { + self.lastExecuteOperation = executeOperation; + } } - (void)unloadInstanceForRootView:(NSNumber *)rootTag { From 0409983175ef0bfebf06a03a89db882a8516db95 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Mon, 14 Oct 2024 20:46:18 +0800 Subject: [PATCH 5/6] chore(core): make perf debugging logs disabled by default --- modules/footstone/include/footstone/logging.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/footstone/include/footstone/logging.h b/modules/footstone/include/footstone/logging.h index 71f5dbd2ee9..3cfa7329c76 100644 --- a/modules/footstone/include/footstone/logging.h +++ b/modules/footstone/include/footstone/logging.h @@ -225,9 +225,9 @@ bool ShouldCreateLogMessage(LogSeverity severity); #define HP_CSTR_NOT_NULL( p ) (p ? p : "") -#ifdef DEBUG +#ifdef ENABLE_HIPPY_PERFLOG +// enable perf log output when `ENABLE_HIPPY_PERFLOG` is set -// enable perf log output in debug mode only #define TDF_PERF_LOG(format, ...) \ footstone::LogMessage::LogWithFormat(__FILE_NAME__, __LINE__, "[HP PERF] " format, \ ##__VA_ARGS__) @@ -241,4 +241,4 @@ footstone::LogMessage::LogWithFormat(__FILE_NAME__, __LINE__, "[HP PERF] " forma #define TDF_PERF_LOG(format, ...) #define TDF_PERF_DO_STMT_AND_LOG(STMT , format, ...) -#endif +#endif /* ENABLE_HIPPY_PERFLOG */ From a803246cda2212f4500fedaa882456db26f49620 Mon Sep 17 00:00:00 2001 From: wwwcg Date: Mon, 14 Oct 2024 20:25:18 +0800 Subject: [PATCH 6/6] chore(demo): update list demo in both react and vue --- .../src/components/ListView/index.jsx | 53 +++++++++---------- .../src/components/demos/demo-list.vue | 1 - .../src/components/demo/demo-list.vue | 4 +- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/driver/js/examples/hippy-react-demo/src/components/ListView/index.jsx b/driver/js/examples/hippy-react-demo/src/components/ListView/index.jsx index eb57411f47b..6c50de00f2e 100644 --- a/driver/js/examples/hippy-react-demo/src/components/ListView/index.jsx +++ b/driver/js/examples/hippy-react-demo/src/components/ListView/index.jsx @@ -4,7 +4,6 @@ import { View, StyleSheet, Text, - Platform, } from '@hippy/react'; const STYLE_LOADING = 100; @@ -271,8 +270,7 @@ export default class ListExample extends React.Component { return true; }} bounces={true} - // horizontal ListView flag(only Android support) - horizontal={horizontal} + horizontal={horizontal} // horizontal ListView flag style={[{ backgroundColor: '#ffffff' }, horizontal ? { height: 50 } : { flex: 1 }]} numberOfRows={dataSource.length} renderRow={this.getRenderRow} @@ -297,33 +295,32 @@ export default class ListExample extends React.Component { onScroll={this.onScroll} scrollEventThrottle={1000} // 1s /> - {Platform.OS === 'android' - ? this.changeDirection()} - style={{ - position: 'absolute', - right: 20, - bottom: 20, - width: 67, - height: 67, - borderRadius: 30, - boxShadowOpacity: 0.6, - boxShadowRadius: 5, - boxShadowOffsetX: 3, - boxShadowOffsetY: 3, - boxShadowColor: '#4c9afa' }}> - + this.changeDirection()} + style={{ + position: 'absolute', + right: 20, + bottom: 20, + width: 67, + height: 67, + borderRadius: 30, + boxShadowOpacity: 0.6, + boxShadowRadius: 5, + boxShadowOffsetX: 3, + boxShadowOffsetY: 3, + boxShadowColor: '#4c9afa' }}> + 切换方向 - : null} + ); } diff --git a/driver/js/examples/hippy-vue-demo/src/components/demos/demo-list.vue b/driver/js/examples/hippy-vue-demo/src/components/demos/demo-list.vue index 853bda36ee8..24d2a913cb2 100644 --- a/driver/js/examples/hippy-vue-demo/src/components/demos/demo-list.vue +++ b/driver/js/examples/hippy-vue-demo/src/components/demos/demo-list.vue @@ -78,7 +78,6 @@
-import { type ListViewEvent, Native } from '@hippy/vue-next'; +import { type ListViewEvent } from '@hippy/vue-next'; import { defineComponent, ref, onMounted, type Ref } from '@vue/runtime-core'; const STYLE_LOADING = 100; @@ -269,7 +268,6 @@ export default defineComponent({ list, STYLE_LOADING, horizontal, - Platform: Native.Platform, onAppear, onDelete, onDisappear,