@qwickapps/react-framework 1.3.5 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1691 -2
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts +66 -0
- package/dist/__tests__/schemas/transformers/MockSerializableComponent.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +7 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/Html.d.ts +28 -18
- package/dist/components/Html.d.ts.map +1 -1
- package/dist/components/Logo.d.ts +12 -35
- package/dist/components/Logo.d.ts.map +1 -1
- package/dist/components/Markdown.d.ts +18 -13
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/QwickApp.d.ts +16 -3
- package/dist/components/QwickApp.d.ts.map +1 -1
- package/dist/components/QwickIcon.d.ts +23 -0
- package/dist/components/QwickIcon.d.ts.map +1 -0
- package/dist/components/SafeSpan.d.ts +12 -5
- package/dist/components/SafeSpan.d.ts.map +1 -1
- package/dist/components/Scaffold.d.ts.map +1 -1
- package/dist/components/base/ModelView.d.ts +101 -0
- package/dist/components/base/ModelView.d.ts.map +1 -0
- package/dist/components/base/index.d.ts +11 -0
- package/dist/components/base/index.d.ts.map +1 -0
- package/dist/components/blocks/Article.d.ts +12 -2
- package/dist/components/blocks/Article.d.ts.map +1 -1
- package/dist/components/blocks/Code.d.ts +13 -2
- package/dist/components/blocks/Code.d.ts.map +1 -1
- package/dist/components/blocks/CoverImageHeader.d.ts.map +1 -1
- package/dist/components/blocks/FeatureCard.d.ts.map +1 -1
- package/dist/components/blocks/FeatureGrid.d.ts.map +1 -1
- package/dist/components/blocks/Footer.d.ts.map +1 -1
- package/dist/components/blocks/HeroBlock.d.ts +27 -13
- package/dist/components/blocks/HeroBlock.d.ts.map +1 -1
- package/dist/components/blocks/Image.d.ts +41 -0
- package/dist/components/blocks/Image.d.ts.map +1 -0
- package/dist/components/blocks/PageBannerHeader.d.ts.map +1 -1
- package/dist/components/blocks/Section.d.ts +16 -2
- package/dist/components/blocks/Section.d.ts.map +1 -1
- package/dist/components/blocks/Text.d.ts +41 -0
- package/dist/components/blocks/Text.d.ts.map +1 -0
- package/dist/components/blocks/index.d.ts +4 -0
- package/dist/components/blocks/index.d.ts.map +1 -1
- package/dist/components/buttons/Button.d.ts +23 -7
- package/dist/components/buttons/Button.d.ts.map +1 -1
- package/dist/components/forms/FormBlock.d.ts +19 -13
- package/dist/components/forms/FormBlock.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input/ChoiceInputField.d.ts +17 -11
- package/dist/components/input/ChoiceInputField.d.ts.map +1 -1
- package/dist/components/input/HtmlInputField.d.ts +17 -11
- package/dist/components/input/HtmlInputField.d.ts.map +1 -1
- package/dist/components/input/SelectInputField.d.ts +16 -10
- package/dist/components/input/SelectInputField.d.ts.map +1 -1
- package/dist/components/input/SwitchInputField.d.ts +16 -10
- package/dist/components/input/SwitchInputField.d.ts.map +1 -1
- package/dist/components/input/TextField.d.ts.map +1 -1
- package/dist/components/input/TextInputField.d.ts +16 -11
- package/dist/components/input/TextInputField.d.ts.map +1 -1
- package/dist/components/layout/GridCell.d.ts +23 -6
- package/dist/components/layout/GridCell.d.ts.map +1 -1
- package/dist/components/layout/GridLayout.d.ts +24 -23
- package/dist/components/layout/GridLayout.d.ts.map +1 -1
- package/dist/components/pages/FormPage.d.ts.map +1 -1
- package/dist/components/pages/Page.d.ts +49 -87
- package/dist/components/pages/Page.d.ts.map +1 -1
- package/dist/components/pages/index.d.ts +2 -2
- package/dist/components/pages/index.d.ts.map +1 -1
- package/dist/config/AppConfig.d.ts +49 -0
- package/dist/config/AppConfig.d.ts.map +1 -0
- package/dist/config/AppConfigBuilder.d.ts +75 -0
- package/dist/config/AppConfigBuilder.d.ts.map +1 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/types.d.ts +130 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config.d.ts +15 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.esm.js +451 -0
- package/dist/config.js +455 -0
- package/dist/contexts/PrintModeContext.d.ts +27 -0
- package/dist/contexts/PrintModeContext.d.ts.map +1 -0
- package/dist/contexts/QwickAppContext.d.ts +2 -2
- package/dist/contexts/QwickAppContext.d.ts.map +1 -1
- package/dist/contexts/index.d.ts +2 -0
- package/dist/contexts/index.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/usePrintMode.d.ts +39 -0
- package/dist/hooks/usePrintMode.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +10951 -6238
- package/dist/index.js +11014 -6287
- package/dist/schemas/CodeSchema.d.ts +2 -1
- package/dist/schemas/CodeSchema.d.ts.map +1 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts +2 -1
- package/dist/schemas/CollapsibleLayoutSchema.d.ts.map +1 -1
- package/dist/schemas/ContentSchema.d.ts +2 -1
- package/dist/schemas/ContentSchema.d.ts.map +1 -1
- package/dist/schemas/GridCellSchema.d.ts +25 -0
- package/dist/schemas/GridCellSchema.d.ts.map +1 -0
- package/dist/schemas/GridLayoutSchema.d.ts +23 -0
- package/dist/schemas/GridLayoutSchema.d.ts.map +1 -0
- package/dist/schemas/HtmlSchema.d.ts +14 -0
- package/dist/schemas/HtmlSchema.d.ts.map +1 -0
- package/dist/schemas/ImageSchema.d.ts +32 -0
- package/dist/schemas/ImageSchema.d.ts.map +1 -0
- package/dist/schemas/LogoSchema.d.ts +35 -0
- package/dist/schemas/LogoSchema.d.ts.map +1 -0
- package/dist/schemas/MarkdownSchema.d.ts +14 -0
- package/dist/schemas/MarkdownSchema.d.ts.map +1 -0
- package/dist/schemas/PageTemplateSchema.d.ts +31 -0
- package/dist/schemas/PageTemplateSchema.d.ts.map +1 -0
- package/dist/schemas/PrintConfigSchema.d.ts +31 -0
- package/dist/schemas/PrintConfigSchema.d.ts.map +1 -0
- package/dist/schemas/SectionSchema.d.ts +2 -1
- package/dist/schemas/SectionSchema.d.ts.map +1 -1
- package/dist/schemas/TextSchema.d.ts +37 -0
- package/dist/schemas/TextSchema.d.ts.map +1 -0
- package/dist/schemas/ViewModelSchema.d.ts +23 -0
- package/dist/schemas/ViewModelSchema.d.ts.map +1 -0
- package/dist/schemas/index.d.ts +15 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/transformers/ComponentTransformer.d.ts +116 -0
- package/dist/schemas/transformers/ComponentTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts +53 -0
- package/dist/schemas/transformers/ReactNodeTransformer.d.ts.map +1 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts +66 -0
- package/dist/schemas/transformers/__tests__/MockSerializableComponent.d.ts.map +1 -0
- package/dist/schemas/transformers/registry.d.ts +15 -0
- package/dist/schemas/transformers/registry.d.ts.map +1 -0
- package/dist/schemas/types/Serializable.d.ts +46 -0
- package/dist/schemas/types/Serializable.d.ts.map +1 -0
- package/dist/utils/htmlTransform.d.ts.map +1 -1
- package/dist/utils/reactUtils.d.ts +12 -3
- package/dist/utils/reactUtils.d.ts.map +1 -1
- package/package.json +17 -3
- package/src/{components/__tests__ → __tests__/components}/AccessibilityProvider.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Article.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Breadcrumbs.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Button.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CardListGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ChoiceInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Code.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Content.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/CoverImageHeader.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/ErrorBoundary.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/FeatureCard.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/FeatureGrid.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/Footer.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/FormBlock.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/HeroBlock.test.tsx +233 -7
- package/src/{components/__tests__ → __tests__/components}/Html.test.tsx +11 -2
- package/src/{components/__tests__ → __tests__/components}/HtmlInputField.test.tsx +3 -3
- package/src/__tests__/components/Logo.test.js +3 -3
- package/src/{components/__tests__ → __tests__/components}/Markdown.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/PageBannerHeader.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/PaletteSwitcher.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ProductCard.test.tsx +4 -4
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.integration.test.tsx +2 -2
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.simple.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SafeSpan.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.integration.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/Section.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/SelectInputField.test.tsx +1 -1
- package/src/{components/__tests__ → __tests__/components}/TextInputField.test.tsx +3 -3
- package/src/{components/__tests__ → __tests__/components}/ThemeSwitcher.test.tsx +3 -3
- package/src/__tests__/components/base/ModelView.test.tsx +220 -0
- package/src/__tests__/components/blocks/Code.performance.test.tsx +625 -0
- package/src/__tests__/components/blocks/Code.serialization.test.tsx +507 -0
- package/src/__tests__/components/blocks/HeroBlock.serialization.test.tsx +414 -0
- package/src/__tests__/components/blocks/Image.serialization.test.tsx +257 -0
- package/src/__tests__/components/blocks/Section.serialization.test.tsx +553 -0
- package/src/__tests__/components/blocks/Text.performance.test.tsx +442 -0
- package/src/__tests__/components/blocks/Text.serialization.test.tsx +491 -0
- package/src/__tests__/components/buttons/Button.serialization.test.tsx +443 -0
- package/src/__tests__/components/input/FormComponents.serialization.test.tsx +482 -0
- package/src/__tests__/components/input/SelectInputField.serialization.test.tsx +439 -0
- package/src/__tests__/components/input/TextInputField.serialization.test.tsx +359 -0
- package/src/{components/layout/CollapsibleLayout/__tests__ → __tests__/components/layout}/CollapsibleLayout.test.tsx +4 -4
- package/src/__tests__/components/layout/GridCell.serialization.test.tsx +403 -0
- package/src/__tests__/components/layout/GridLayout.serialization.test.tsx +311 -0
- package/src/__tests__/hooks/usePrintMode.test.ts +89 -0
- package/src/__tests__/schemas/PageTemplateSchema.test.ts +161 -0
- package/src/__tests__/schemas/PrintConfigSchema.test.ts +127 -0
- package/src/__tests__/schemas/ViewModelSchema.test.ts +80 -0
- package/src/__tests__/schemas/transformers/ComponentSerializationPatterns.test.tsx +602 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.htmlPatterns.test.ts +301 -0
- package/src/__tests__/schemas/transformers/ComponentTransformer.test.ts +521 -0
- package/src/__tests__/schemas/transformers/CrossBrowserCompatibility.test.ts +586 -0
- package/src/__tests__/schemas/transformers/MockSerializableComponent.ts +103 -0
- package/src/__tests__/schemas/transformers/RealWorldScenarios.test.tsx +1165 -0
- package/src/__tests__/schemas/transformers/SerializationErrorHandling.test.ts +602 -0
- package/src/__tests__/schemas/transformers/SerializationIntegration.test.tsx +691 -0
- package/src/__tests__/schemas/transformers/SerializationPerformance.test.ts +460 -0
- package/src/__tests__/schemas/transformers/TestAutomation.test.ts +597 -0
- package/src/{utils/__tests__ → __tests__/utils}/nested-dom-fix.test.tsx +1 -1
- package/src/components/ErrorBoundary.tsx +8 -8
- package/src/components/Html.tsx +147 -44
- package/src/components/Logo.tsx +198 -100
- package/src/components/Markdown.tsx +125 -16
- package/src/components/QwickApp.tsx +64 -31
- package/src/components/QwickIcon.tsx +59 -0
- package/src/components/SafeSpan.tsx +65 -10
- package/src/components/Scaffold.tsx +2 -8
- package/src/components/base/ModelView.tsx +199 -0
- package/src/components/base/index.ts +11 -0
- package/src/components/blocks/Article.tsx +57 -18
- package/src/components/blocks/Code.md +529 -0
- package/src/components/blocks/Code.tsx +102 -15
- package/src/components/blocks/CoverImageHeader.tsx +9 -4
- package/src/components/blocks/FeatureCard.tsx +1 -2
- package/src/components/blocks/FeatureGrid.tsx +19 -1
- package/src/components/blocks/Footer.tsx +13 -1
- package/src/components/blocks/HeroBlock.tsx +87 -20
- package/src/components/blocks/Image.tsx +395 -0
- package/src/components/blocks/PageBannerHeader.tsx +14 -12
- package/src/components/blocks/ProductCard.tsx +1 -1
- package/src/components/blocks/Section.tsx +113 -8
- package/src/components/blocks/Text.tsx +285 -0
- package/src/components/blocks/index.ts +4 -0
- package/src/components/buttons/Button.tsx +184 -15
- package/src/components/forms/FormBlock.tsx +70 -17
- package/src/components/index.ts +5 -0
- package/src/components/input/ChoiceInputField.tsx +48 -18
- package/src/components/input/HtmlInputField.tsx +48 -18
- package/src/components/input/SelectInputField.tsx +48 -16
- package/src/components/input/SwitchInputField.tsx +48 -17
- package/src/components/input/TextField.tsx +41 -1
- package/src/components/input/TextInputField.tsx +52 -18
- package/src/components/layout/GridCell.tsx +118 -9
- package/src/components/layout/GridLayout.tsx +125 -24
- package/src/components/pages/FormPage.tsx +0 -1
- package/src/components/pages/Page.css +304 -332
- package/src/components/pages/Page.tsx +307 -255
- package/src/components/pages/index.ts +2 -2
- package/src/config/AppConfig.ts +133 -0
- package/src/config/AppConfigBuilder.ts +421 -0
- package/src/config/__tests__/AppConfig.test.ts +385 -0
- package/src/config/__tests__/AppConfigBuilder.test.ts +432 -0
- package/src/config/index.ts +24 -0
- package/src/config/types.ts +170 -0
- package/src/config.ts +25 -0
- package/src/contexts/PrintModeContext.tsx +332 -0
- package/src/contexts/QwickAppContext.tsx +2 -2
- package/src/contexts/index.ts +2 -0
- package/src/hooks/index.ts +5 -1
- package/src/hooks/usePrintMode.ts +73 -0
- package/src/index.ts +3 -0
- package/src/schemas/CodeSchema.ts +3 -3
- package/src/schemas/CollapsibleLayoutSchema.ts +2 -1
- package/src/schemas/ContentSchema.ts +2 -1
- package/src/schemas/GridCellSchema.ts +164 -0
- package/src/schemas/GridLayoutSchema.ts +133 -0
- package/src/schemas/HtmlSchema.ts +47 -0
- package/src/schemas/ImageSchema.ts +235 -0
- package/src/schemas/LogoSchema.ts +241 -0
- package/src/schemas/MarkdownSchema.ts +47 -0
- package/src/schemas/PageTemplateSchema.ts +186 -0
- package/src/schemas/PrintConfigSchema.ts +207 -0
- package/src/schemas/README.md +661 -0
- package/src/schemas/SectionSchema.ts +2 -1
- package/src/schemas/TextSchema.ts +329 -0
- package/src/schemas/ViewModelSchema.ts +115 -0
- package/src/schemas/index.ts +21 -2
- package/src/schemas/transformers/ComponentTransformer.ts +403 -0
- package/src/schemas/transformers/ReactNodeTransformer.ts +236 -0
- package/src/schemas/transformers/registry.ts +72 -0
- package/src/schemas/types/Serializable.ts +51 -0
- package/src/stories/AccessibilityProvider.stories.tsx +253 -253
- package/src/stories/Article.stories.tsx +433 -433
- package/src/stories/Button.stories.tsx +1 -1
- package/src/stories/CardListGrid.stories.tsx +451 -451
- package/src/stories/ChoiceInputField.stories.tsx +503 -503
- package/src/stories/Code.stories.tsx +1 -1
- package/src/stories/CollapsibleLayout.stories.tsx +1414 -1414
- package/src/stories/Content.stories.tsx +393 -393
- package/src/stories/CoverImageHeader.stories.tsx +701 -701
- package/src/stories/DataBinding.advanced.stories.tsx +432 -432
- package/src/stories/DataProvider.stories.tsx +1192 -1192
- package/src/stories/FeatureCard.stories.tsx +557 -557
- package/src/stories/FeatureGrid.stories.tsx +594 -594
- package/src/stories/Footer.stories.tsx +640 -640
- package/src/stories/FormBlock.stories.tsx +760 -760
- package/src/stories/FormComponents.stories.tsx +349 -541
- package/src/stories/GridCell.stories.tsx +417 -0
- package/src/stories/GridLayout.stories.tsx +353 -0
- package/src/stories/HeroBlock.stories.tsx +862 -373
- package/src/stories/HtmlInputField.stories.tsx +474 -474
- package/src/stories/Image.stories.tsx +819 -0
- package/src/stories/Introduction.stories.tsx +667 -667
- package/src/stories/LayoutBlocks.stories.tsx +324 -324
- package/src/stories/Logo.stories.tsx +165 -6
- package/src/stories/Markdown.stories.tsx +137 -137
- package/src/stories/ModelView.stories.tsx +477 -0
- package/src/stories/Page.stories.tsx +688 -688
- package/src/stories/PageBannerHeader.stories.tsx +864 -864
- package/src/stories/PaletteSwitcher.stories.tsx +119 -119
- package/src/stories/ProductCard.stories.tsx +424 -424
- package/src/stories/QwickApp.stories.tsx +368 -368
- package/src/stories/ResponsiveMenu.stories.tsx +249 -249
- package/src/stories/SafeSpan.stories.tsx +531 -531
- package/src/stories/Section.stories.tsx +90 -2
- package/src/stories/SelectInputField.stories.tsx +524 -524
- package/src/stories/Text.stories.tsx +560 -0
- package/src/stories/TextInputField.stories.tsx +443 -443
- package/src/stories/ThemeSwitcher.stories.tsx +123 -123
- package/src/utils/htmlTransform.tsx +74 -53
- package/src/utils/reactUtils.tsx +57 -6
- package/dist/index.bundled.css +0 -12
- /package/src/{hooks/__tests__ → __tests__/hooks}/useDataBinding.test.tsx.disabled +0 -0
- /package/src/{schemas/__tests__ → __tests__/schemas}/builders.test.ts +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/createDataDrivenComponent.test.tsx.disabled +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/htmlTransform.test.tsx +0 -0
- /package/src/{utils/__tests__ → __tests__/utils}/optional-logging.test.ts +0 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Component Performance Tests
|
|
3
|
+
*
|
|
4
|
+
* Validates performance requirements for serialization operations
|
|
5
|
+
* and ensures the implementation meets quality gates for production use.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { Code } from '../../../components/blocks/Code';
|
|
12
|
+
import { ComponentTransformer } from '../../../schemas/transformers/ComponentTransformer';
|
|
13
|
+
|
|
14
|
+
// Large sample code for performance testing - using regular strings to avoid template literal issues
|
|
15
|
+
const largeJavaScriptCode = `
|
|
16
|
+
// Large JavaScript code sample for performance testing
|
|
17
|
+
class AdvancedDataProcessor {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.batchSize = options.batchSize || 1000;
|
|
20
|
+
this.maxRetries = options.maxRetries || 3;
|
|
21
|
+
this.timeout = options.timeout || 30000;
|
|
22
|
+
this.cache = new Map();
|
|
23
|
+
this.workers = [];
|
|
24
|
+
this.eventListeners = new Map();
|
|
25
|
+
|
|
26
|
+
this.initializeWorkerPool();
|
|
27
|
+
this.setupErrorHandling();
|
|
28
|
+
this.configurePerformanceMonitoring();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async processLargeBatch(data) {
|
|
32
|
+
const startTime = performance.now();
|
|
33
|
+
const results = [];
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Validate input data
|
|
37
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
38
|
+
throw new Error('Invalid data: Expected non-empty array');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Split data into manageable chunks
|
|
42
|
+
const chunks = this.chunkArray(data, this.batchSize);
|
|
43
|
+
console.log('Processing ' + chunks.length + ' chunks of data');
|
|
44
|
+
|
|
45
|
+
// Process chunks concurrently with worker pool
|
|
46
|
+
const promises = chunks.map(async (chunk, index) => {
|
|
47
|
+
const worker = this.getAvailableWorker();
|
|
48
|
+
const chunkId = 'chunk_' + index + '_' + Date.now();
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const result = await this.processChunkWithWorker(worker, chunk, chunkId);
|
|
52
|
+
this.updateProgressMetrics(index, chunks.length);
|
|
53
|
+
return result;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Error processing chunk ' + chunkId + ':', error);
|
|
56
|
+
return await this.handleChunkError(chunk, chunkId, error);
|
|
57
|
+
} finally {
|
|
58
|
+
this.releaseWorker(worker);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const chunkResults = await Promise.allSettled(promises);
|
|
63
|
+
|
|
64
|
+
// Aggregate results and handle any failures
|
|
65
|
+
for (const result of chunkResults) {
|
|
66
|
+
if (result.status === 'fulfilled') {
|
|
67
|
+
results.push(...result.value);
|
|
68
|
+
} else {
|
|
69
|
+
console.error('Chunk processing failed:', result.reason);
|
|
70
|
+
this.emit('chunkError', result.reason);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const processingTime = performance.now() - startTime;
|
|
75
|
+
this.logPerformanceMetrics(processingTime, data.length, results.length);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
processedCount: results.length,
|
|
80
|
+
totalCount: data.length,
|
|
81
|
+
processingTime,
|
|
82
|
+
results
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const processingTime = performance.now() - startTime;
|
|
87
|
+
console.error('Batch processing failed:', error);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: error.message,
|
|
92
|
+
processedCount: results.length,
|
|
93
|
+
totalCount: data.length,
|
|
94
|
+
processingTime,
|
|
95
|
+
results
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
chunkArray(array, size) {
|
|
101
|
+
const chunks = [];
|
|
102
|
+
for (let i = 0; i < array.length; i += size) {
|
|
103
|
+
chunks.push(array.slice(i, i + size));
|
|
104
|
+
}
|
|
105
|
+
return chunks;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async processChunkWithWorker(worker, chunk, chunkId) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const timeout = setTimeout(() => {
|
|
111
|
+
reject(new Error('Chunk processing timeout: ' + chunkId));
|
|
112
|
+
}, this.timeout);
|
|
113
|
+
|
|
114
|
+
worker.postMessage({
|
|
115
|
+
type: 'PROCESS_CHUNK',
|
|
116
|
+
payload: { chunk, chunkId }
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
worker.onmessage = (event) => {
|
|
120
|
+
clearTimeout(timeout);
|
|
121
|
+
if (event.data.type === 'CHUNK_COMPLETE') {
|
|
122
|
+
resolve(event.data.payload.results);
|
|
123
|
+
} else if (event.data.type === 'CHUNK_ERROR') {
|
|
124
|
+
reject(new Error(event.data.payload.error));
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
initializeWorkerPool() {
|
|
131
|
+
const workerCount = navigator.hardwareConcurrency || 4;
|
|
132
|
+
console.log('Initializing worker pool with ' + workerCount + ' workers');
|
|
133
|
+
|
|
134
|
+
for (let i = 0; i < workerCount; i++) {
|
|
135
|
+
const worker = new Worker(new URL('./data-processor.worker.js', import.meta.url));
|
|
136
|
+
worker.available = true;
|
|
137
|
+
this.workers.push(worker);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getAvailableWorker() {
|
|
142
|
+
const worker = this.workers.find(w => w.available);
|
|
143
|
+
if (worker) {
|
|
144
|
+
worker.available = false;
|
|
145
|
+
return worker;
|
|
146
|
+
}
|
|
147
|
+
// If no workers available, wait and retry
|
|
148
|
+
return new Promise(resolve => {
|
|
149
|
+
const checkWorkers = () => {
|
|
150
|
+
const availableWorker = this.workers.find(w => w.available);
|
|
151
|
+
if (availableWorker) {
|
|
152
|
+
availableWorker.available = false;
|
|
153
|
+
resolve(availableWorker);
|
|
154
|
+
} else {
|
|
155
|
+
setTimeout(checkWorkers, 10);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
checkWorkers();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
releaseWorker(worker) {
|
|
163
|
+
worker.available = true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Export for use in other modules
|
|
168
|
+
export default AdvancedDataProcessor;
|
|
169
|
+
`;
|
|
170
|
+
|
|
171
|
+
const largeTypeScriptCode = `
|
|
172
|
+
// Large TypeScript code sample for performance testing
|
|
173
|
+
interface DatabaseConnection {
|
|
174
|
+
readonly id: string;
|
|
175
|
+
readonly host: string;
|
|
176
|
+
readonly port: number;
|
|
177
|
+
readonly database: string;
|
|
178
|
+
readonly ssl: boolean;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface QueryOptions {
|
|
182
|
+
timeout?: number;
|
|
183
|
+
retries?: number;
|
|
184
|
+
cache?: boolean;
|
|
185
|
+
cacheTTL?: number;
|
|
186
|
+
transaction?: boolean;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface QueryResult<T = any> {
|
|
190
|
+
data: T[];
|
|
191
|
+
count: number;
|
|
192
|
+
executionTime: number;
|
|
193
|
+
fromCache: boolean;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
type EventHandler<T = any> = (event: T) => void | Promise<void>;
|
|
197
|
+
type QueryBuilder = (query: string, params?: any[]) => Promise<QueryResult>;
|
|
198
|
+
|
|
199
|
+
class EnterpriseDatabase {
|
|
200
|
+
private connections: Map<string, DatabaseConnection> = new Map();
|
|
201
|
+
private queryCache: Map<string, { result: QueryResult; timestamp: number }> = new Map();
|
|
202
|
+
private eventHandlers: Map<string, EventHandler[]> = new Map();
|
|
203
|
+
private transactionStack: string[] = [];
|
|
204
|
+
private connectionPool: DatabaseConnection[] = [];
|
|
205
|
+
private readonly maxConnections: number = 50;
|
|
206
|
+
private readonly defaultTimeout: number = 30000;
|
|
207
|
+
|
|
208
|
+
constructor(private config: {
|
|
209
|
+
defaultConnection: DatabaseConnection;
|
|
210
|
+
maxConnections?: number;
|
|
211
|
+
cacheEnabled?: boolean;
|
|
212
|
+
cacheTTL?: number;
|
|
213
|
+
}) {
|
|
214
|
+
this.initializeConnectionPool();
|
|
215
|
+
this.setupHealthChecking();
|
|
216
|
+
this.configureQueryOptimization();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async query<T = any>(
|
|
220
|
+
sql: string,
|
|
221
|
+
params: any[] = [],
|
|
222
|
+
options: QueryOptions = {}
|
|
223
|
+
): Promise<QueryResult<T>> {
|
|
224
|
+
const startTime = performance.now();
|
|
225
|
+
const queryId = this.generateQueryId(sql, params);
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
// Check cache first
|
|
229
|
+
if (options.cache !== false && this.config.cacheEnabled) {
|
|
230
|
+
const cached = this.getCachedResult(queryId, options.cacheTTL);
|
|
231
|
+
if (cached) {
|
|
232
|
+
this.emit('cacheHit', { queryId, sql });
|
|
233
|
+
return cached;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Get connection from pool
|
|
238
|
+
const connection = await this.getConnection();
|
|
239
|
+
|
|
240
|
+
// Execute query with retry logic
|
|
241
|
+
const result = await this.executeWithRetry(
|
|
242
|
+
connection,
|
|
243
|
+
sql,
|
|
244
|
+
params,
|
|
245
|
+
options.retries || 3,
|
|
246
|
+
options.timeout || this.defaultTimeout
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
const executionTime = performance.now() - startTime;
|
|
250
|
+
const queryResult: QueryResult<T> = {
|
|
251
|
+
data: result.rows,
|
|
252
|
+
count: result.rowCount || result.rows.length,
|
|
253
|
+
executionTime,
|
|
254
|
+
fromCache: false
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Cache successful results
|
|
258
|
+
if (options.cache !== false && this.config.cacheEnabled) {
|
|
259
|
+
this.cacheResult(queryId, queryResult, options.cacheTTL);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Log performance metrics
|
|
263
|
+
this.logQueryPerformance(sql, executionTime, queryResult.count);
|
|
264
|
+
this.emit('queryComplete', { sql, executionTime, resultCount: queryResult.count });
|
|
265
|
+
|
|
266
|
+
// Release connection back to pool
|
|
267
|
+
this.releaseConnection(connection);
|
|
268
|
+
|
|
269
|
+
return queryResult;
|
|
270
|
+
|
|
271
|
+
} catch (error) {
|
|
272
|
+
const executionTime = performance.now() - startTime;
|
|
273
|
+
this.emit('queryError', { sql, error: error.message, executionTime });
|
|
274
|
+
|
|
275
|
+
console.error('Database query failed:', {
|
|
276
|
+
sql: sql.substring(0, 200) + (sql.length > 200 ? '...' : ''),
|
|
277
|
+
params,
|
|
278
|
+
error: error.message,
|
|
279
|
+
executionTime
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
throw new Error('Query execution failed: ' + error.message);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private generateQueryId(sql: string, params: any[]): string {
|
|
287
|
+
return btoa(sql + JSON.stringify(params)).replace(/[^a-zA-Z0-9]/g, '').substring(0, 32);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
on<T>(event: string, handler: EventHandler<T>): void {
|
|
291
|
+
if (!this.eventHandlers.has(event)) {
|
|
292
|
+
this.eventHandlers.set(event, []);
|
|
293
|
+
}
|
|
294
|
+
this.eventHandlers.get(event)!.push(handler);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private emit<T>(event: string, data: T): void {
|
|
298
|
+
const handlers = this.eventHandlers.get(event) || [];
|
|
299
|
+
handlers.forEach(handler => {
|
|
300
|
+
try {
|
|
301
|
+
handler(data);
|
|
302
|
+
} catch (error) {
|
|
303
|
+
console.error('Event handler error for ' + event + ':', error);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export { EnterpriseDatabase, type DatabaseConnection, type QueryOptions, type QueryResult };
|
|
310
|
+
`;
|
|
311
|
+
|
|
312
|
+
// Test performance benchmarks
|
|
313
|
+
describe('Code Component Performance Tests', () => {
|
|
314
|
+
beforeEach(() => {
|
|
315
|
+
ComponentTransformer.clearRegistry();
|
|
316
|
+
ComponentTransformer.registerComponent(Code as any);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
afterEach(() => {
|
|
320
|
+
ComponentTransformer.clearRegistry();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
describe('Serialization Performance', () => {
|
|
324
|
+
it('should serialize typical Code component in <10ms', () => {
|
|
325
|
+
const codeInstance = new Code({
|
|
326
|
+
children: 'console.log("Hello World");',
|
|
327
|
+
language: 'javascript',
|
|
328
|
+
showCopy: true,
|
|
329
|
+
title: 'example.js'
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const iterations = 100;
|
|
333
|
+
const startTime = performance.now();
|
|
334
|
+
|
|
335
|
+
for (let i = 0; i < iterations; i++) {
|
|
336
|
+
codeInstance.toJson();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const totalTime = performance.now() - startTime;
|
|
340
|
+
const averageTime = totalTime / iterations;
|
|
341
|
+
|
|
342
|
+
console.log(`Serialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
343
|
+
expect(averageTime).toBeLessThan(10); // Should be under 10ms per operation
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('should serialize large code content in <15ms', () => {
|
|
347
|
+
const codeInstance = new Code({
|
|
348
|
+
children: largeJavaScriptCode,
|
|
349
|
+
language: 'javascript',
|
|
350
|
+
showCopy: true,
|
|
351
|
+
showLineNumbers: true,
|
|
352
|
+
title: 'large-file.js'
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const iterations = 50;
|
|
356
|
+
const startTime = performance.now();
|
|
357
|
+
|
|
358
|
+
for (let i = 0; i < iterations; i++) {
|
|
359
|
+
codeInstance.toJson();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const totalTime = performance.now() - startTime;
|
|
363
|
+
const averageTime = totalTime / iterations;
|
|
364
|
+
|
|
365
|
+
console.log(`Large code serialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
366
|
+
expect(averageTime).toBeLessThan(15); // Should be under 15ms for large content
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should serialize complex ReactNode children in <20ms', () => {
|
|
370
|
+
const complexChildren = (
|
|
371
|
+
<div>
|
|
372
|
+
<span>Line 1: {largeJavaScriptCode.substring(0, 100)}</span>
|
|
373
|
+
<br />
|
|
374
|
+
<span>Line 2: {largeTypeScriptCode.substring(0, 100)}</span>
|
|
375
|
+
<div>
|
|
376
|
+
<code>{largeJavaScriptCode.substring(100, 200)}</code>
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const codeInstance = new Code({
|
|
382
|
+
children: complexChildren,
|
|
383
|
+
language: 'javascript',
|
|
384
|
+
showCopy: true,
|
|
385
|
+
title: 'complex.js'
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const iterations = 25;
|
|
389
|
+
const startTime = performance.now();
|
|
390
|
+
|
|
391
|
+
for (let i = 0; i < iterations; i++) {
|
|
392
|
+
codeInstance.toJson();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const totalTime = performance.now() - startTime;
|
|
396
|
+
const averageTime = totalTime / iterations;
|
|
397
|
+
|
|
398
|
+
console.log(`Complex ReactNode serialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
399
|
+
expect(averageTime).toBeLessThan(20); // Should be under 20ms for complex ReactNodes
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
describe('Deserialization Performance', () => {
|
|
404
|
+
it('should deserialize typical JSON data in <5ms', () => {
|
|
405
|
+
const jsonData = {
|
|
406
|
+
children: 'console.log("Hello World");',
|
|
407
|
+
language: 'javascript',
|
|
408
|
+
showCopy: true,
|
|
409
|
+
title: 'example.js'
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const iterations = 200;
|
|
413
|
+
const startTime = performance.now();
|
|
414
|
+
|
|
415
|
+
for (let i = 0; i < iterations; i++) {
|
|
416
|
+
Code.fromJson(jsonData);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const totalTime = performance.now() - startTime;
|
|
420
|
+
const averageTime = totalTime / iterations;
|
|
421
|
+
|
|
422
|
+
console.log(`Deserialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
423
|
+
expect(averageTime).toBeLessThan(5); // Should be under 5ms per operation
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should deserialize large code content in <8ms', () => {
|
|
427
|
+
const jsonData = {
|
|
428
|
+
children: largeTypeScriptCode,
|
|
429
|
+
language: 'typescript',
|
|
430
|
+
showCopy: true,
|
|
431
|
+
showLineNumbers: true,
|
|
432
|
+
title: 'large-file.ts'
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const iterations = 100;
|
|
436
|
+
const startTime = performance.now();
|
|
437
|
+
|
|
438
|
+
for (let i = 0; i < iterations; i++) {
|
|
439
|
+
Code.fromJson(jsonData);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const totalTime = performance.now() - startTime;
|
|
443
|
+
const averageTime = totalTime / iterations;
|
|
444
|
+
|
|
445
|
+
console.log(`Large code deserialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
446
|
+
expect(averageTime).toBeLessThan(8); // Should be under 8ms for large content
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
describe('ComponentTransformer Performance', () => {
|
|
451
|
+
it('should serialize through ComponentTransformer in <15ms', () => {
|
|
452
|
+
const codeElement = (
|
|
453
|
+
<Code
|
|
454
|
+
language="javascript"
|
|
455
|
+
showCopy={true}
|
|
456
|
+
showLineNumbers={true}
|
|
457
|
+
title="performance-test.js"
|
|
458
|
+
>
|
|
459
|
+
{largeJavaScriptCode}
|
|
460
|
+
</Code>
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
const iterations = 50;
|
|
464
|
+
const startTime = performance.now();
|
|
465
|
+
|
|
466
|
+
for (let i = 0; i < iterations; i++) {
|
|
467
|
+
ComponentTransformer.serialize(codeElement);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const totalTime = performance.now() - startTime;
|
|
471
|
+
const averageTime = totalTime / iterations;
|
|
472
|
+
|
|
473
|
+
console.log(`ComponentTransformer serialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
474
|
+
expect(averageTime).toBeLessThan(15); // Should be under 15ms via ComponentTransformer
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('should deserialize through ComponentTransformer in <10ms', () => {
|
|
478
|
+
const codeElement = (
|
|
479
|
+
<Code
|
|
480
|
+
language="javascript"
|
|
481
|
+
title="performance-test.js"
|
|
482
|
+
>
|
|
483
|
+
{largeJavaScriptCode}
|
|
484
|
+
</Code>
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
const serializedData = ComponentTransformer.serialize(codeElement);
|
|
488
|
+
|
|
489
|
+
const iterations = 75;
|
|
490
|
+
const startTime = performance.now();
|
|
491
|
+
|
|
492
|
+
for (let i = 0; i < iterations; i++) {
|
|
493
|
+
ComponentTransformer.deserialize(serializedData);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const totalTime = performance.now() - startTime;
|
|
497
|
+
const averageTime = totalTime / iterations;
|
|
498
|
+
|
|
499
|
+
console.log(`ComponentTransformer deserialization: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
500
|
+
expect(averageTime).toBeLessThan(10); // Should be under 10ms via ComponentTransformer
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
describe('Round-trip Performance', () => {
|
|
505
|
+
it('should complete round-trip in <25ms for typical content', () => {
|
|
506
|
+
const originalProps = {
|
|
507
|
+
children: 'function hello() { return "world"; }',
|
|
508
|
+
language: 'javascript',
|
|
509
|
+
showCopy: true,
|
|
510
|
+
showLineNumbers: false,
|
|
511
|
+
title: 'hello.js'
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const iterations = 50;
|
|
515
|
+
const startTime = performance.now();
|
|
516
|
+
|
|
517
|
+
for (let i = 0; i < iterations; i++) {
|
|
518
|
+
// Create instance → serialize → deserialize
|
|
519
|
+
const codeInstance = new Code(originalProps);
|
|
520
|
+
const serializedData = codeInstance.toJson();
|
|
521
|
+
Code.fromJson(serializedData);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const totalTime = performance.now() - startTime;
|
|
525
|
+
const averageTime = totalTime / iterations;
|
|
526
|
+
|
|
527
|
+
console.log(`Round-trip performance: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
528
|
+
expect(averageTime).toBeLessThan(25); // Should complete round-trip in under 25ms
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('should complete ComponentTransformer round-trip in <30ms', () => {
|
|
532
|
+
const codeElement = (
|
|
533
|
+
<Code
|
|
534
|
+
language="typescript"
|
|
535
|
+
showCopy={true}
|
|
536
|
+
title="round-trip.ts"
|
|
537
|
+
>
|
|
538
|
+
{largeTypeScriptCode}
|
|
539
|
+
</Code>
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
const iterations = 25;
|
|
543
|
+
const startTime = performance.now();
|
|
544
|
+
|
|
545
|
+
for (let i = 0; i < iterations; i++) {
|
|
546
|
+
// Serialize → Deserialize via ComponentTransformer
|
|
547
|
+
const serialized = ComponentTransformer.serialize(codeElement);
|
|
548
|
+
ComponentTransformer.deserialize(serialized);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const totalTime = performance.now() - startTime;
|
|
552
|
+
const averageTime = totalTime / iterations;
|
|
553
|
+
|
|
554
|
+
console.log(`ComponentTransformer round-trip: ${averageTime.toFixed(2)}ms average over ${iterations} iterations`);
|
|
555
|
+
expect(averageTime).toBeLessThan(30); // Should complete ComponentTransformer round-trip in under 30ms
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
describe('Memory Usage Validation', () => {
|
|
560
|
+
it('should not cause memory leaks during repeated operations', () => {
|
|
561
|
+
const initialMemory = (performance as any).memory?.usedJSHeapSize || 0;
|
|
562
|
+
|
|
563
|
+
const codeElement = (
|
|
564
|
+
<Code language="javascript" title="memory-test.js">
|
|
565
|
+
{largeJavaScriptCode}
|
|
566
|
+
</Code>
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
// Perform many operations
|
|
570
|
+
for (let i = 0; i < 1000; i++) {
|
|
571
|
+
const serialized = ComponentTransformer.serialize(codeElement);
|
|
572
|
+
const deserialized = ComponentTransformer.deserialize(serialized);
|
|
573
|
+
|
|
574
|
+
// Force garbage collection hint (if available)
|
|
575
|
+
if (typeof global !== 'undefined' && (global as any).gc) {
|
|
576
|
+
if (i % 100 === 0) (global as any).gc();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const finalMemory = (performance as any).memory?.usedJSHeapSize || 0;
|
|
581
|
+
|
|
582
|
+
if (initialMemory > 0 && finalMemory > 0) {
|
|
583
|
+
const memoryIncrease = finalMemory - initialMemory;
|
|
584
|
+
const memoryIncreaseKB = memoryIncrease / 1024;
|
|
585
|
+
|
|
586
|
+
console.log(`Memory increase: ${memoryIncreaseKB.toFixed(2)}KB after 1000 operations`);
|
|
587
|
+
|
|
588
|
+
// Should not increase memory by more than 1MB (significant leak indicator)
|
|
589
|
+
expect(memoryIncrease).toBeLessThan(1024 * 1024); // 1MB
|
|
590
|
+
} else {
|
|
591
|
+
console.log('Memory measurement not available - skipping memory leak test');
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
describe('Concurrent Operations Performance', () => {
|
|
597
|
+
it('should handle concurrent serialization efficiently', async () => {
|
|
598
|
+
const codeInstances = Array.from({ length: 100 }, (_, i) =>
|
|
599
|
+
new Code({
|
|
600
|
+
children: `console.log("Instance ${i}");`,
|
|
601
|
+
language: 'javascript',
|
|
602
|
+
title: `instance-${i}.js`
|
|
603
|
+
})
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
const startTime = performance.now();
|
|
607
|
+
|
|
608
|
+
// Serialize all instances concurrently
|
|
609
|
+
const promises = codeInstances.map(instance =>
|
|
610
|
+
Promise.resolve(instance.toJson())
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
const results = await Promise.all(promises);
|
|
614
|
+
|
|
615
|
+
const totalTime = performance.now() - startTime;
|
|
616
|
+
const averageTime = totalTime / results.length;
|
|
617
|
+
|
|
618
|
+
console.log(`Concurrent serialization: ${totalTime.toFixed(2)}ms total, ${averageTime.toFixed(2)}ms average for 100 instances`);
|
|
619
|
+
|
|
620
|
+
expect(results).toHaveLength(100);
|
|
621
|
+
expect(totalTime).toBeLessThan(1000); // Should complete 100 concurrent operations in under 1 second
|
|
622
|
+
expect(averageTime).toBeLessThan(10); // Each operation should still be under 10ms on average
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
});
|