This is page 166 of 190. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/assets/img/%7BimageSrc%7D?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .changeset
│ └── config.json
├── .eslintrc.cjs
├── .github
│ ├── build-checklist.png
│ ├── ISSUE_TEMPLATE
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows
│ ├── deploy-blog-optimized.yml
│ ├── deploy-blog-swa.yml
│ ├── deploy-blog.yml
│ ├── deploy-docs-optimized.yml
│ ├── deploy-docs-swa.yml
│ ├── deploy-docs.yml
│ ├── prepare-versions.yml
│ ├── release-packages.yml
│ ├── run-all-tests.yml
│ └── run-smoke-tests.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
│ ├── launch.json
│ └── settings.json
├── blog
│ ├── .gitignore
│ ├── .gitkeep
│ ├── CHANGELOG.md
│ ├── extensions.ts
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── public
│ │ ├── blog
│ │ │ ├── images
│ │ │ │ ├── an-advanced-codefence.gif
│ │ │ │ ├── an-advanced-codefence.mp4
│ │ │ │ ├── blog-page-component.png
│ │ │ │ ├── blog-scrabble.png
│ │ │ │ ├── codefence-runner.png
│ │ │ │ ├── integrated-blog-search.png
│ │ │ │ ├── lorem-ipsum.png
│ │ │ │ ├── playground-checkbox-source.png
│ │ │ │ ├── playground.png
│ │ │ │ ├── use-xmlui-mcp-to-find-a-howto.png
│ │ │ │ └── xmlui-demo-gallery.png
│ │ │ ├── introducing-xmlui.md
│ │ │ ├── lorem-ipsum.md
│ │ │ ├── newest-post.md
│ │ │ ├── older-post.md
│ │ │ ├── xmlui-playground.md
│ │ │ └── xmlui-powered-blog.md
│ │ ├── mockServiceWorker.js
│ │ ├── resources
│ │ │ ├── favicon.ico
│ │ │ ├── files
│ │ │ │ └── for-download
│ │ │ │ └── xmlui
│ │ │ │ └── xmlui-standalone.umd.js
│ │ │ ├── github.svg
│ │ │ ├── icons
│ │ │ │ ├── github.svg
│ │ │ │ └── rss.svg
│ │ │ ├── llms.txt
│ │ │ ├── logo-dark.svg
│ │ │ ├── logo.svg
│ │ │ ├── pg-popout.svg
│ │ │ ├── rss.svg
│ │ │ └── xmlui-logo.svg
│ │ ├── serve.json
│ │ ├── staticwebapp.config.json
│ │ └── web.config
│ ├── scripts
│ │ ├── download-latest-xmlui.js
│ │ ├── generate-rss.js
│ │ ├── get-releases.js
│ │ └── utils.js
│ ├── src
│ │ ├── components
│ │ │ ├── BlogOverview.xmlui
│ │ │ ├── BlogPage.xmlui
│ │ │ ├── LinkButton.xmlui
│ │ │ ├── PageNotFound.xmlui
│ │ │ └── Separator.xmlui
│ │ ├── config.ts
│ │ ├── Main.xmlui
│ │ └── themes
│ │ └── blog-theme.ts
│ └── tsconfig.json
├── CONTRIBUTING.md
├── docs
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── ComponentRefLinks.txt
│ ├── content
│ │ ├── _meta.json
│ │ ├── components
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── APICall.md
│ │ │ ├── App.md
│ │ │ ├── AppHeader.md
│ │ │ ├── AppState.md
│ │ │ ├── AutoComplete.md
│ │ │ ├── Avatar.md
│ │ │ ├── Backdrop.md
│ │ │ ├── Badge.md
│ │ │ ├── BarChart.md
│ │ │ ├── Bookmark.md
│ │ │ ├── Breakout.md
│ │ │ ├── Button.md
│ │ │ ├── Card.md
│ │ │ ├── Carousel.md
│ │ │ ├── ChangeListener.md
│ │ │ ├── Checkbox.md
│ │ │ ├── CHStack.md
│ │ │ ├── ColorPicker.md
│ │ │ ├── Column.md
│ │ │ ├── ContentSeparator.md
│ │ │ ├── CVStack.md
│ │ │ ├── DataSource.md
│ │ │ ├── DateInput.md
│ │ │ ├── DatePicker.md
│ │ │ ├── DonutChart.md
│ │ │ ├── DropdownMenu.md
│ │ │ ├── EmojiSelector.md
│ │ │ ├── ExpandableItem.md
│ │ │ ├── FileInput.md
│ │ │ ├── FileUploadDropZone.md
│ │ │ ├── FlowLayout.md
│ │ │ ├── Footer.md
│ │ │ ├── Form.md
│ │ │ ├── FormItem.md
│ │ │ ├── FormSection.md
│ │ │ ├── Fragment.md
│ │ │ ├── H1.md
│ │ │ ├── H2.md
│ │ │ ├── H3.md
│ │ │ ├── H4.md
│ │ │ ├── H5.md
│ │ │ ├── H6.md
│ │ │ ├── Heading.md
│ │ │ ├── HSplitter.md
│ │ │ ├── HStack.md
│ │ │ ├── Icon.md
│ │ │ ├── IFrame.md
│ │ │ ├── Image.md
│ │ │ ├── Items.md
│ │ │ ├── LabelList.md
│ │ │ ├── Legend.md
│ │ │ ├── LineChart.md
│ │ │ ├── Link.md
│ │ │ ├── List.md
│ │ │ ├── Logo.md
│ │ │ ├── Markdown.md
│ │ │ ├── MenuItem.md
│ │ │ ├── MenuSeparator.md
│ │ │ ├── ModalDialog.md
│ │ │ ├── NavGroup.md
│ │ │ ├── NavLink.md
│ │ │ ├── NavPanel.md
│ │ │ ├── NoResult.md
│ │ │ ├── NumberBox.md
│ │ │ ├── Option.md
│ │ │ ├── Page.md
│ │ │ ├── PageMetaTitle.md
│ │ │ ├── Pages.md
│ │ │ ├── Pagination.md
│ │ │ ├── PasswordInput.md
│ │ │ ├── PieChart.md
│ │ │ ├── ProgressBar.md
│ │ │ ├── Queue.md
│ │ │ ├── RadioGroup.md
│ │ │ ├── RealTimeAdapter.md
│ │ │ ├── Redirect.md
│ │ │ ├── Select.md
│ │ │ ├── Slider.md
│ │ │ ├── Slot.md
│ │ │ ├── SpaceFiller.md
│ │ │ ├── Spinner.md
│ │ │ ├── Splitter.md
│ │ │ ├── Stack.md
│ │ │ ├── StickyBox.md
│ │ │ ├── SubMenuItem.md
│ │ │ ├── Switch.md
│ │ │ ├── TabItem.md
│ │ │ ├── Table.md
│ │ │ ├── TableOfContents.md
│ │ │ ├── Tabs.md
│ │ │ ├── Text.md
│ │ │ ├── TextArea.md
│ │ │ ├── TextBox.md
│ │ │ ├── Theme.md
│ │ │ ├── TimeInput.md
│ │ │ ├── Timer.md
│ │ │ ├── ToneChangerButton.md
│ │ │ ├── ToneSwitch.md
│ │ │ ├── Tooltip.md
│ │ │ ├── Tree.md
│ │ │ ├── VSplitter.md
│ │ │ ├── VStack.md
│ │ │ ├── xmlui-animations
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── Animation.md
│ │ │ │ ├── FadeAnimation.md
│ │ │ │ ├── FadeInAnimation.md
│ │ │ │ ├── FadeOutAnimation.md
│ │ │ │ ├── ScaleAnimation.md
│ │ │ │ └── SlideInAnimation.md
│ │ │ ├── xmlui-pdf
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Pdf.md
│ │ │ ├── xmlui-spreadsheet
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Spreadsheet.md
│ │ │ └── xmlui-website-blocks
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── Carousel.md
│ │ │ ├── HelloMd.md
│ │ │ ├── HeroSection.md
│ │ │ └── ScrollToTop.md
│ │ └── extensions
│ │ ├── _meta.json
│ │ ├── xmlui-animations
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── Animation.md
│ │ │ ├── FadeAnimation.md
│ │ │ ├── FadeInAnimation.md
│ │ │ ├── FadeOutAnimation.md
│ │ │ ├── ScaleAnimation.md
│ │ │ └── SlideInAnimation.md
│ │ └── xmlui-website-blocks
│ │ ├── _meta.json
│ │ ├── _overview.md
│ │ ├── Carousel.md
│ │ ├── FancyButton.md
│ │ ├── HeroSection.md
│ │ └── ScrollToTop.md
│ ├── extensions.ts
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── public
│ │ ├── feed.rss
│ │ ├── mockServiceWorker.js
│ │ ├── pages
│ │ │ ├── _meta.json
│ │ │ ├── app-structure.md
│ │ │ ├── build-editor-component.md
│ │ │ ├── build-hello-world-component.md
│ │ │ ├── components-intro.md
│ │ │ ├── context-variables.md
│ │ │ ├── forms.md
│ │ │ ├── globals.md
│ │ │ ├── glossary.md
│ │ │ ├── helper-tags.md
│ │ │ ├── hosted-deployment.md
│ │ │ ├── howto
│ │ │ │ ├── assign-a-complex-json-literal-to-a-component-variable.md
│ │ │ │ ├── chain-a-refetch.md
│ │ │ │ ├── control-cache-invalidation.md
│ │ │ │ ├── debounce-user-input-for-api-calls.md
│ │ │ │ ├── debounce-with-changelistener.md
│ │ │ │ ├── debug-a-component.md
│ │ │ │ ├── delay-a-datasource-until-another-datasource-is-ready.md
│ │ │ │ ├── delegate-a-method.md
│ │ │ │ ├── do-custom-form-validation.md
│ │ │ │ ├── expose-a-method-from-a-component.md
│ │ │ │ ├── filter-and-transform-data-from-an-api.md
│ │ │ │ ├── group-items-in-list-by-a-property.md
│ │ │ │ ├── handle-background-operations.md
│ │ │ │ ├── hide-an-element-until-its-datasource-is-ready.md
│ │ │ │ ├── make-a-set-of-equal-width-cards.md
│ │ │ │ ├── make-a-table-responsive.md
│ │ │ │ ├── make-navpanel-width-responsive.md
│ │ │ │ ├── modify-a-value-reported-in-a-column.md
│ │ │ │ ├── paginate-a-list.md
│ │ │ │ ├── pass-data-to-a-modal-dialog.md
│ │ │ │ ├── react-to-button-click-not-keystrokes.md
│ │ │ │ ├── set-the-initial-value-of-a-select-from-fetched-data.md
│ │ │ │ ├── share-a-modaldialog-across-components.md
│ │ │ │ ├── sync-selections-between-table-and-list-views.md
│ │ │ │ ├── update-ui-optimistically.md
│ │ │ │ ├── use-built-in-form-validation.md
│ │ │ │ └── use-the-same-modaldialog-to-add-or-edit.md
│ │ │ ├── howto.md
│ │ │ ├── intro.md
│ │ │ ├── layout.md
│ │ │ ├── markup.md
│ │ │ ├── mcp.md
│ │ │ ├── modal-dialogs.md
│ │ │ ├── news-and-reviews.md
│ │ │ ├── reactive-intro.md
│ │ │ ├── refactoring.md
│ │ │ ├── routing-and-links.md
│ │ │ ├── samples
│ │ │ │ ├── color-palette.xmlui
│ │ │ │ ├── color-values.xmlui
│ │ │ │ ├── shadow-sizes.xmlui
│ │ │ │ ├── spacing-sizes.xmlui
│ │ │ │ ├── swatch.xmlui
│ │ │ │ ├── theme-gallery-brief.xmlui
│ │ │ │ └── theme-gallery.xmlui
│ │ │ ├── scoping.md
│ │ │ ├── scripting.md
│ │ │ ├── styles-and-themes
│ │ │ │ ├── common-units.md
│ │ │ │ ├── layout-props.md
│ │ │ │ ├── theme-variable-defaults.md
│ │ │ │ ├── theme-variables.md
│ │ │ │ └── themes.md
│ │ │ ├── template-properties.md
│ │ │ ├── test.md
│ │ │ ├── tutorial-01.md
│ │ │ ├── tutorial-02.md
│ │ │ ├── tutorial-03.md
│ │ │ ├── tutorial-04.md
│ │ │ ├── tutorial-05.md
│ │ │ ├── tutorial-06.md
│ │ │ ├── tutorial-07.md
│ │ │ ├── tutorial-08.md
│ │ │ ├── tutorial-09.md
│ │ │ ├── tutorial-10.md
│ │ │ ├── tutorial-11.md
│ │ │ ├── tutorial-12.md
│ │ │ ├── universal-properties.md
│ │ │ ├── user-defined-components.md
│ │ │ ├── vscode.md
│ │ │ ├── working-with-markdown.md
│ │ │ ├── working-with-text.md
│ │ │ ├── xmlui-animations
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── Animation.md
│ │ │ │ ├── FadeAnimation.md
│ │ │ │ ├── FadeInAnimation.md
│ │ │ │ ├── FadeOutAnimation.md
│ │ │ │ ├── ScaleAnimation.md
│ │ │ │ └── SlideInAnimation.md
│ │ │ ├── xmlui-charts
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── BarChart.md
│ │ │ │ ├── DonutChart.md
│ │ │ │ ├── LabelList.md
│ │ │ │ ├── Legend.md
│ │ │ │ ├── LineChart.md
│ │ │ │ └── PieChart.md
│ │ │ ├── xmlui-pdf
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Pdf.md
│ │ │ └── xmlui-spreadsheet
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ └── Spreadsheet.md
│ │ ├── resources
│ │ │ ├── devdocs
│ │ │ │ ├── debug-proxy-object-2.png
│ │ │ │ ├── debug-proxy-object.png
│ │ │ │ ├── table_editor_01.png
│ │ │ │ ├── table_editor_02.png
│ │ │ │ ├── table_editor_03.png
│ │ │ │ ├── table_editor_04.png
│ │ │ │ ├── table_editor_05.png
│ │ │ │ ├── table_editor_06.png
│ │ │ │ ├── table_editor_07.png
│ │ │ │ ├── table_editor_08.png
│ │ │ │ ├── table_editor_09.png
│ │ │ │ ├── table_editor_10.png
│ │ │ │ ├── table_editor_11.png
│ │ │ │ ├── table-editor-01.png
│ │ │ │ ├── table-editor-02.png
│ │ │ │ ├── table-editor-03.png
│ │ │ │ ├── table-editor-04.png
│ │ │ │ ├── table-editor-06.png
│ │ │ │ ├── table-editor-07.png
│ │ │ │ ├── table-editor-08.png
│ │ │ │ ├── table-editor-09.png
│ │ │ │ └── xmlui-rendering-of-tiptap-markdown.png
│ │ │ ├── favicon.ico
│ │ │ ├── files
│ │ │ │ ├── clients.json
│ │ │ │ ├── daily-revenue.json
│ │ │ │ ├── dashboard-stats.json
│ │ │ │ ├── demo.xmlui
│ │ │ │ ├── demo.xmlui.xs
│ │ │ │ ├── downloads
│ │ │ │ │ └── downloads.json
│ │ │ │ ├── for-download
│ │ │ │ │ ├── index-with-api.html
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── mockApi.js
│ │ │ │ │ ├── start-darwin.sh
│ │ │ │ │ ├── start-linux.sh
│ │ │ │ │ ├── start.bat
│ │ │ │ │ └── xmlui
│ │ │ │ │ └── xmlui-standalone.umd.js
│ │ │ │ ├── getting-started
│ │ │ │ │ ├── cl-tutorial-final.zip
│ │ │ │ │ ├── cl-tutorial.zip
│ │ │ │ │ ├── cl-tutorial2.zip
│ │ │ │ │ ├── cl-tutorial3.zip
│ │ │ │ │ ├── cl-tutorial4.zip
│ │ │ │ │ ├── cl-tutorial5.zip
│ │ │ │ │ ├── cl-tutorial6.zip
│ │ │ │ │ ├── getting-started.zip
│ │ │ │ │ ├── hello-xmlui.zip
│ │ │ │ │ ├── xmlui-empty.zip
│ │ │ │ │ └── xmlui-starter.zip
│ │ │ │ ├── howto
│ │ │ │ │ └── component-icons
│ │ │ │ │ └── up-arrow.svg
│ │ │ │ ├── invoices.json
│ │ │ │ ├── monthly-status.json
│ │ │ │ ├── news-and-reviews.json
│ │ │ │ ├── products.json
│ │ │ │ ├── releases.json
│ │ │ │ ├── tutorials
│ │ │ │ │ ├── datasource
│ │ │ │ │ │ └── api.ts
│ │ │ │ │ └── p2do
│ │ │ │ │ ├── api.ts
│ │ │ │ │ └── todo-logo.svg
│ │ │ │ └── xmlui.json
│ │ │ ├── icons
│ │ │ │ ├── github.svg
│ │ │ │ └── rss.svg
│ │ │ ├── images
│ │ │ │ ├── apiaction-tutorial
│ │ │ │ │ ├── add-success.png
│ │ │ │ │ ├── apiaction-param.png
│ │ │ │ │ ├── change-completed.png
│ │ │ │ │ ├── change-in-progress.png
│ │ │ │ │ ├── confirm-delete.png
│ │ │ │ │ ├── data-error.png
│ │ │ │ │ ├── data-progress.png
│ │ │ │ │ ├── data-success.png
│ │ │ │ │ ├── display-1.png
│ │ │ │ │ ├── item-deleted.png
│ │ │ │ │ ├── item-updated.png
│ │ │ │ │ ├── missing-api-key.png
│ │ │ │ │ ├── new-item-added.png
│ │ │ │ │ └── test-message.png
│ │ │ │ ├── chat-api
│ │ │ │ │ └── domain-model.svg
│ │ │ │ ├── components
│ │ │ │ │ ├── image
│ │ │ │ │ │ └── breakfast.jpg
│ │ │ │ │ ├── markdown
│ │ │ │ │ │ └── colors.png
│ │ │ │ │ └── modal
│ │ │ │ │ ├── deep_link_dialog_1.jpg
│ │ │ │ │ └── deep_link_dialog_2.jpg
│ │ │ │ ├── create-apps
│ │ │ │ │ ├── collapsed-vertical.png
│ │ │ │ │ ├── using-forms-warning-dialog.png
│ │ │ │ │ └── using-forms.png
│ │ │ │ ├── datasource-tutorial
│ │ │ │ │ ├── data-with-header.png
│ │ │ │ │ ├── filtered-data.png
│ │ │ │ │ ├── filtered-items.png
│ │ │ │ │ ├── initial-page-items.png
│ │ │ │ │ ├── list-items.png
│ │ │ │ │ ├── next-page-items.png
│ │ │ │ │ ├── no-data.png
│ │ │ │ │ ├── pagination-1.jpg
│ │ │ │ │ ├── pagination-1.png
│ │ │ │ │ ├── polling-1.png
│ │ │ │ │ ├── refetch-data.png
│ │ │ │ │ ├── slow-loading.png
│ │ │ │ │ ├── test-message.png
│ │ │ │ │ ├── Thumbs.db
│ │ │ │ │ ├── unconventional-data.png
│ │ │ │ │ └── unfiltered-items.png
│ │ │ │ ├── flower.jpg
│ │ │ │ ├── get-started
│ │ │ │ │ ├── add-new-contact.png
│ │ │ │ │ ├── app-modified.png
│ │ │ │ │ ├── app-start.png
│ │ │ │ │ ├── app-with-boxes.png
│ │ │ │ │ ├── app-with-toast.png
│ │ │ │ │ ├── boilerplate-structure.png
│ │ │ │ │ ├── cl-initial.png
│ │ │ │ │ ├── cl-start.png
│ │ │ │ │ ├── contact-counts.png
│ │ │ │ │ ├── contact-dialog-title.png
│ │ │ │ │ ├── contact-dialog.png
│ │ │ │ │ ├── contact-menus.png
│ │ │ │ │ ├── contact-predicates.png
│ │ │ │ │ ├── context-menu.png
│ │ │ │ │ ├── dashboard-numbers.png
│ │ │ │ │ ├── default-contact-list.png
│ │ │ │ │ ├── delete-contact.png
│ │ │ │ │ ├── delete-task.png
│ │ │ │ │ ├── detailed-template.png
│ │ │ │ │ ├── edit-contact-details.png
│ │ │ │ │ ├── edited-contact-saved.png
│ │ │ │ │ ├── empty-sections.png
│ │ │ │ │ ├── filter-completed.png
│ │ │ │ │ ├── fullwidth-desktop.png
│ │ │ │ │ ├── fullwidth-mobile.png
│ │ │ │ │ ├── initial-table.png
│ │ │ │ │ ├── items-and-badges.png
│ │ │ │ │ ├── loading-message.png
│ │ │ │ │ ├── new-contact-button.png
│ │ │ │ │ ├── new-contact-saved.png
│ │ │ │ │ ├── no-empty-sections.png
│ │ │ │ │ ├── personal-todo-initial.png
│ │ │ │ │ ├── piechart.png
│ │ │ │ │ ├── review-today.png
│ │ │ │ │ ├── rudimentary-dashboard.png
│ │ │ │ │ ├── section-collapsed.png
│ │ │ │ │ ├── sectioned-items.png
│ │ │ │ │ ├── sections-ordered.png
│ │ │ │ │ ├── spacex-list-with-links.png
│ │ │ │ │ ├── spacex-list.png
│ │ │ │ │ ├── start-personal-todo-1.png
│ │ │ │ │ ├── submit-new-contact.png
│ │ │ │ │ ├── submit-new-task.png
│ │ │ │ │ ├── syntax-highlighting.png
│ │ │ │ │ ├── table-with-badge.png
│ │ │ │ │ ├── template-with-card.png
│ │ │ │ │ ├── test-emulated-api.png
│ │ │ │ │ ├── Thumbs.db
│ │ │ │ │ ├── todo-logo.png
│ │ │ │ │ └── xmlui-tools.png
│ │ │ │ ├── HelloApp.png
│ │ │ │ ├── HelloApp2.png
│ │ │ │ ├── logos
│ │ │ │ │ ├── xmlui1.svg
│ │ │ │ │ ├── xmlui2.svg
│ │ │ │ │ ├── xmlui3.svg
│ │ │ │ │ ├── xmlui4.svg
│ │ │ │ │ ├── xmlui5.svg
│ │ │ │ │ ├── xmlui6.svg
│ │ │ │ │ └── xmlui7.svg
│ │ │ │ ├── pdf
│ │ │ │ │ └── dummy-pdf.jpg
│ │ │ │ ├── rendering-engine
│ │ │ │ │ ├── AppEngine-flow.svg
│ │ │ │ │ ├── Component.svg
│ │ │ │ │ ├── CompoundComponent.svg
│ │ │ │ │ ├── RootComponent.svg
│ │ │ │ │ └── tree-with-containers.svg
│ │ │ │ ├── reviewers-guide
│ │ │ │ │ ├── AppEngine-flow.svg
│ │ │ │ │ └── incbutton-in-action.png
│ │ │ │ ├── tools
│ │ │ │ │ └── boilerplate-structure.png
│ │ │ │ ├── try.svg
│ │ │ │ ├── tutorial
│ │ │ │ │ ├── app-chat-history.png
│ │ │ │ │ ├── app-content-placeholder.png
│ │ │ │ │ ├── app-header-and-content.png
│ │ │ │ │ ├── app-links-channel-selected.png
│ │ │ │ │ ├── app-links-click.png
│ │ │ │ │ ├── app-navigation.png
│ │ │ │ │ ├── finished-ex01.png
│ │ │ │ │ ├── finished-ex02.png
│ │ │ │ │ ├── hello.png
│ │ │ │ │ ├── splash-screen-advanced.png
│ │ │ │ │ ├── splash-screen-after-click.png
│ │ │ │ │ ├── splash-screen-centered.png
│ │ │ │ │ ├── splash-screen-events.png
│ │ │ │ │ ├── splash-screen-expression.png
│ │ │ │ │ ├── splash-screen-reuse-after.png
│ │ │ │ │ ├── splash-screen-reuse-before.png
│ │ │ │ │ └── splash-screen.png
│ │ │ │ └── tutorial-01.png
│ │ │ ├── llms.txt
│ │ │ ├── logo-dark.svg
│ │ │ ├── logo.svg
│ │ │ ├── pg-popout.svg
│ │ │ └── xmlui-logo.svg
│ │ ├── serve.json
│ │ ├── staticwebapp.config.json
│ │ └── web.config
│ ├── scripts
│ │ ├── download-latest-xmlui.js
│ │ ├── generate-rss.js
│ │ ├── get-releases.js
│ │ └── utils.js
│ ├── src
│ │ ├── components
│ │ │ ├── BlogOverview.xmlui
│ │ │ ├── BlogPage.xmlui
│ │ │ ├── Boxes.xmlui
│ │ │ ├── Breadcrumb.xmlui
│ │ │ ├── ChangeLog.xmlui
│ │ │ ├── ColorPalette.xmlui
│ │ │ ├── DocumentLinks.xmlui
│ │ │ ├── DocumentPage.xmlui
│ │ │ ├── DocumentPageNoTOC.xmlui
│ │ │ ├── Icons.xmlui
│ │ │ ├── IncButton.xmlui
│ │ │ ├── IncButton2.xmlui
│ │ │ ├── LinkButton.xmlui
│ │ │ ├── NameValue.xmlui
│ │ │ ├── PageNotFound.xmlui
│ │ │ ├── PaletteItem.xmlui
│ │ │ ├── Palettes.xmlui
│ │ │ ├── SectionHeader.xmlui
│ │ │ ├── Separator.xmlui
│ │ │ ├── TBD.xmlui
│ │ │ ├── Test.xmlui
│ │ │ ├── ThemesIntro.xmlui
│ │ │ ├── ThousandThemes.xmlui
│ │ │ ├── TubeStops.xmlui
│ │ │ ├── TubeStops.xmlui.xs
│ │ │ └── TwoColumnCode.xmlui
│ │ ├── config.ts
│ │ ├── Main.xmlui
│ │ └── themes
│ │ ├── docs-theme.ts
│ │ ├── earthtone.ts
│ │ ├── xmlui-gray-on-default.ts
│ │ ├── xmlui-green-on-default.ts
│ │ └── xmlui-orange-on-default.ts
│ └── tsconfig.json
├── LICENSE
├── package-lock.json
├── package.json
├── packages
│ ├── tsconfig.json
│ ├── xmlui-animations
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── Animation.tsx
│ │ ├── AnimationNative.tsx
│ │ ├── FadeAnimation.tsx
│ │ ├── FadeInAnimation.tsx
│ │ ├── FadeOutAnimation.tsx
│ │ ├── index.tsx
│ │ ├── ScaleAnimation.tsx
│ │ └── SlideInAnimation.tsx
│ ├── xmlui-devtools
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── devtools
│ │ │ │ ├── DevTools.tsx
│ │ │ │ ├── DevToolsNative.module.scss
│ │ │ │ ├── DevToolsNative.tsx
│ │ │ │ ├── ModalDialog.module.scss
│ │ │ │ ├── ModalDialog.tsx
│ │ │ │ ├── ModalVisibilityContext.tsx
│ │ │ │ ├── Tooltip.module.scss
│ │ │ │ ├── Tooltip.tsx
│ │ │ │ └── utils.ts
│ │ │ ├── editor
│ │ │ │ └── Editor.tsx
│ │ │ └── index.tsx
│ │ └── vite.config-overrides.ts
│ ├── xmlui-hello-world
│ │ ├── .gitignore
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── HelloWorld.module.scss
│ │ ├── HelloWorld.tsx
│ │ ├── HelloWorldNative.tsx
│ │ └── index.tsx
│ ├── xmlui-os-frames
│ │ ├── .gitignore
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── IPhoneFrame.module.scss
│ │ ├── IPhoneFrame.tsx
│ │ ├── MacOSAppFrame.module.scss
│ │ ├── MacOSAppFrame.tsx
│ │ ├── WindowsAppFrame.module.scss
│ │ └── WindowsAppFrame.tsx
│ ├── xmlui-pdf
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ ├── components
│ │ │ │ └── Pdf.xmlui
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── LazyPdfNative.tsx
│ │ ├── Pdf.module.scss
│ │ └── Pdf.tsx
│ ├── xmlui-playground
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── hooks
│ │ │ ├── usePlayground.ts
│ │ │ └── useToast.ts
│ │ ├── index.tsx
│ │ ├── playground
│ │ │ ├── Box.module.scss
│ │ │ ├── Box.tsx
│ │ │ ├── CodeSelector.module.scss
│ │ │ ├── CodeSelector.tsx
│ │ │ ├── ConfirmationDialog.module.scss
│ │ │ ├── ConfirmationDialog.tsx
│ │ │ ├── Editor.tsx
│ │ │ ├── Header.module.scss
│ │ │ ├── Header.tsx
│ │ │ ├── Playground.tsx
│ │ │ ├── PlaygroundContent.module.scss
│ │ │ ├── PlaygroundContent.tsx
│ │ │ ├── PlaygroundNative.module.scss
│ │ │ ├── PlaygroundNative.tsx
│ │ │ ├── Preview.tsx
│ │ │ ├── StandalonePlayground.tsx
│ │ │ ├── StandalonePlaygroundNative.module.scss
│ │ │ ├── StandalonePlaygroundNative.tsx
│ │ │ ├── ThemeSwitcher.module.scss
│ │ │ ├── ThemeSwitcher.tsx
│ │ │ └── utils.ts
│ │ ├── providers
│ │ │ ├── Toast.module.scss
│ │ │ └── ToastProvider.tsx
│ │ ├── state
│ │ │ └── store.ts
│ │ ├── themes
│ │ │ └── theme.ts
│ │ └── utils
│ │ └── helpers.ts
│ ├── xmlui-search
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── Search.module.scss
│ │ └── Search.tsx
│ ├── xmlui-spreadsheet
│ │ ├── .gitignore
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── Spreadsheet.tsx
│ │ └── SpreadsheetNative.tsx
│ └── xmlui-website-blocks
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── demo
│ │ ├── components
│ │ │ ├── HeroBackgroundBreakoutPage.xmlui
│ │ │ ├── HeroBackgroundsPage.xmlui
│ │ │ ├── HeroContentsPage.xmlui
│ │ │ ├── HeroTextAlignPage.xmlui
│ │ │ ├── HeroTextPage.xmlui
│ │ │ └── HeroTonesPage.xmlui
│ │ ├── Main.xmlui
│ │ └── themes
│ │ └── default.ts
│ ├── index.html
│ ├── index.ts
│ ├── meta
│ │ └── componentsMetadata.ts
│ ├── package.json
│ ├── public
│ │ └── resources
│ │ ├── building.jpg
│ │ └── xmlui-logo.svg
│ └── src
│ ├── Carousel
│ │ ├── Carousel.module.scss
│ │ ├── Carousel.tsx
│ │ ├── CarouselContext.tsx
│ │ └── CarouselNative.tsx
│ ├── FancyButton
│ │ ├── FancyButton.module.scss
│ │ ├── FancyButton.tsx
│ │ └── FancyButton.xmlui
│ ├── Hello
│ │ ├── Hello.tsx
│ │ ├── Hello.xmlui
│ │ └── Hello.xmlui.xs
│ ├── HeroSection
│ │ ├── HeroSection.module.scss
│ │ ├── HeroSection.spec.ts
│ │ ├── HeroSection.tsx
│ │ └── HeroSectionNative.tsx
│ ├── index.tsx
│ ├── ScrollToTop
│ │ ├── ScrollToTop.module.scss
│ │ ├── ScrollToTop.tsx
│ │ └── ScrollToTopNative.tsx
│ └── vite-env.d.ts
├── playwright.config.ts
├── README.md
├── tools
│ ├── codefence
│ │ └── xmlui-code-fence-docs.md
│ ├── create-app
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── create-app.ts
│ │ ├── helpers
│ │ │ ├── copy.ts
│ │ │ ├── get-pkg-manager.ts
│ │ │ ├── git.ts
│ │ │ ├── install.ts
│ │ │ ├── is-folder-empty.ts
│ │ │ ├── is-writeable.ts
│ │ │ ├── make-dir.ts
│ │ │ └── validate-pkg.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── templates
│ │ │ ├── default
│ │ │ │ └── ts
│ │ │ │ ├── gitignore
│ │ │ │ ├── index.html
│ │ │ │ ├── index.ts
│ │ │ │ ├── public
│ │ │ │ │ ├── mockServiceWorker.js
│ │ │ │ │ ├── resources
│ │ │ │ │ │ ├── favicon.ico
│ │ │ │ │ │ └── xmlui-logo.svg
│ │ │ │ │ └── serve.json
│ │ │ │ └── src
│ │ │ │ ├── components
│ │ │ │ │ ├── ApiAware.xmlui
│ │ │ │ │ ├── Home.xmlui
│ │ │ │ │ ├── IncButton.xmlui
│ │ │ │ │ └── PagePanel.xmlui
│ │ │ │ ├── config.ts
│ │ │ │ └── Main.xmlui
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── create-xmlui-hello-world
│ │ ├── index.js
│ │ └── package.json
│ └── vscode
│ ├── .gitignore
│ ├── .vscode
│ │ ├── launch.json
│ │ └── tasks.json
│ ├── .vscodeignore
│ ├── build.sh
│ ├── CHANGELOG.md
│ ├── esbuild.js
│ ├── eslint.config.mjs
│ ├── formatter-docs.md
│ ├── generate-test-sample.sh
│ ├── LICENSE.md
│ ├── package-lock.json
│ ├── package.json
│ ├── README.md
│ ├── resources
│ │ ├── xmlui-logo.png
│ │ └── xmlui-markup-syntax-highlighting.png
│ ├── src
│ │ ├── extension.ts
│ │ └── server.ts
│ ├── syntaxes
│ │ └── xmlui.tmLanguage.json
│ ├── test-samples
│ │ └── sample.xmlui
│ ├── tsconfig.json
│ └── tsconfig.tsbuildinfo
├── turbo.json
└── xmlui
├── .gitignore
├── bin
│ ├── bootstrap.cjs
│ ├── bootstrap.js
│ ├── build-lib.ts
│ ├── build.ts
│ ├── index.ts
│ ├── preview.ts
│ ├── start.ts
│ ├── vite-xmlui-plugin.ts
│ └── viteConfig.ts
├── CHANGELOG.md
├── conventions
│ ├── component-qa-checklist.md
│ ├── copilot-conventions.md
│ ├── create-xmlui-components.md
│ ├── mermaid.md
│ ├── testing-conventions.md
│ └── xmlui-in-a-nutshell.md
├── dev-docs
│ ├── accessibility.md
│ ├── build-system.md
│ ├── build-xmlui.md
│ ├── component-behaviors.md
│ ├── component-metadata.md
│ ├── components-with-options.md
│ ├── containers.md
│ ├── data-operations.md
│ ├── glossary.md
│ ├── index.md
│ ├── next
│ │ ├── component-dev-guide.md
│ │ ├── configuration-management-enhancement-summary.md
│ │ ├── documentation-scripts-refactoring-complete-summary.md
│ │ ├── documentation-scripts-refactoring-plan.md
│ │ ├── duplicate-pattern-extraction-summary.md
│ │ ├── error-handling-standardization-summary.md
│ │ ├── generating-component-reference.md
│ │ ├── index.md
│ │ ├── logging-consistency-implementation-summary.md
│ │ ├── project-build.md
│ │ ├── project-structure.md
│ │ ├── theme-context.md
│ │ ├── tiptap-design-considerations.md
│ │ ├── working-with-code.md
│ │ ├── xmlui-runtime-architecture
│ │ └── xmlui-wcag-accessibility-report.md
│ ├── react-fundamentals.md
│ ├── release-method.md
│ ├── standalone-app.md
│ ├── theme-variables-refactoring.md
│ ├── ud-components.md
│ └── xmlui-repo.md
├── package.json
├── scripts
│ ├── coverage-only.js
│ ├── e2e-test-summary.js
│ ├── extract-component-metadata.js
│ ├── generate-docs
│ │ ├── build-downloads-map.mjs
│ │ ├── build-pages-map.mjs
│ │ ├── components-config.json
│ │ ├── configuration-management.mjs
│ │ ├── constants.mjs
│ │ ├── create-theme-files.mjs
│ │ ├── DocsGenerator.mjs
│ │ ├── error-handling.mjs
│ │ ├── extensions-config.json
│ │ ├── folders.mjs
│ │ ├── generate-summary-files.mjs
│ │ ├── get-docs.mjs
│ │ ├── input-handler.mjs
│ │ ├── logger.mjs
│ │ ├── logging-standards.mjs
│ │ ├── MetadataProcessor.mjs
│ │ ├── pattern-utilities.mjs
│ │ └── utils.mjs
│ ├── generate-metadata-markdown.js
│ ├── get-langserver-metadata.js
│ ├── inline-links.mjs
│ └── README-e2e-summary.md
├── src
│ ├── abstractions
│ │ ├── _conventions.md
│ │ ├── ActionDefs.ts
│ │ ├── AppContextDefs.ts
│ │ ├── ComponentDefs.ts
│ │ ├── ContainerDefs.ts
│ │ ├── ExtensionDefs.ts
│ │ ├── FunctionDefs.ts
│ │ ├── RendererDefs.ts
│ │ ├── scripting
│ │ │ ├── BlockScope.ts
│ │ │ ├── Compilation.ts
│ │ │ ├── LogicalThread.ts
│ │ │ ├── LoopScope.ts
│ │ │ ├── modules.ts
│ │ │ ├── ScriptParserError.ts
│ │ │ ├── Token.ts
│ │ │ ├── TryScope.ts
│ │ │ └── TryScopeExp.ts
│ │ └── ThemingDefs.ts
│ ├── components
│ │ ├── _conventions.md
│ │ ├── abstractions.ts
│ │ ├── Accordion
│ │ │ ├── Accordion.md
│ │ │ ├── Accordion.module.scss
│ │ │ ├── Accordion.spec.ts
│ │ │ ├── Accordion.tsx
│ │ │ ├── AccordionContext.tsx
│ │ │ ├── AccordionItem.tsx
│ │ │ ├── AccordionItemNative.tsx
│ │ │ └── AccordionNative.tsx
│ │ ├── Animation
│ │ │ └── AnimationNative.tsx
│ │ ├── APICall
│ │ │ ├── APICall.md
│ │ │ ├── APICall.spec.ts
│ │ │ ├── APICall.tsx
│ │ │ └── APICallNative.tsx
│ │ ├── App
│ │ │ ├── App.md
│ │ │ ├── App.module.scss
│ │ │ ├── App.spec.ts
│ │ │ ├── App.tsx
│ │ │ ├── AppLayoutContext.ts
│ │ │ ├── AppNative.tsx
│ │ │ ├── AppStateContext.ts
│ │ │ ├── doc-resources
│ │ │ │ ├── condensed-sticky.xmlui
│ │ │ │ ├── condensed.xmlui
│ │ │ │ ├── horizontal-sticky.xmlui
│ │ │ │ ├── horizontal.xmlui
│ │ │ │ ├── vertical-full-header.xmlui
│ │ │ │ ├── vertical-sticky.xmlui
│ │ │ │ └── vertical.xmlui
│ │ │ ├── IndexerContext.ts
│ │ │ ├── LinkInfoContext.ts
│ │ │ ├── SearchContext.tsx
│ │ │ ├── Sheet.module.scss
│ │ │ └── Sheet.tsx
│ │ ├── AppHeader
│ │ │ ├── AppHeader.md
│ │ │ ├── AppHeader.module.scss
│ │ │ ├── AppHeader.spec.ts
│ │ │ ├── AppHeader.tsx
│ │ │ └── AppHeaderNative.tsx
│ │ ├── AppState
│ │ │ ├── AppState.md
│ │ │ ├── AppState.spec.ts
│ │ │ ├── AppState.tsx
│ │ │ └── AppStateNative.tsx
│ │ ├── AutoComplete
│ │ │ ├── AutoComplete.md
│ │ │ ├── AutoComplete.module.scss
│ │ │ ├── AutoComplete.spec.ts
│ │ │ ├── AutoComplete.tsx
│ │ │ ├── AutoCompleteContext.tsx
│ │ │ └── AutoCompleteNative.tsx
│ │ ├── Avatar
│ │ │ ├── Avatar.md
│ │ │ ├── Avatar.module.scss
│ │ │ ├── Avatar.spec.ts
│ │ │ ├── Avatar.tsx
│ │ │ └── AvatarNative.tsx
│ │ ├── Backdrop
│ │ │ ├── Backdrop.md
│ │ │ ├── Backdrop.module.scss
│ │ │ ├── Backdrop.spec.ts
│ │ │ ├── Backdrop.tsx
│ │ │ └── BackdropNative.tsx
│ │ ├── Badge
│ │ │ ├── Badge.md
│ │ │ ├── Badge.module.scss
│ │ │ ├── Badge.spec.ts
│ │ │ ├── Badge.tsx
│ │ │ └── BadgeNative.tsx
│ │ ├── Bookmark
│ │ │ ├── Bookmark.md
│ │ │ ├── Bookmark.module.scss
│ │ │ ├── Bookmark.spec.ts
│ │ │ ├── Bookmark.tsx
│ │ │ └── BookmarkNative.tsx
│ │ ├── Breakout
│ │ │ ├── Breakout.module.scss
│ │ │ ├── Breakout.spec.ts
│ │ │ ├── Breakout.tsx
│ │ │ └── BreakoutNative.tsx
│ │ ├── Button
│ │ │ ├── Button-style.spec.ts
│ │ │ ├── Button.md
│ │ │ ├── Button.module.scss
│ │ │ ├── Button.spec.ts
│ │ │ ├── Button.tsx
│ │ │ └── ButtonNative.tsx
│ │ ├── Card
│ │ │ ├── Card.md
│ │ │ ├── Card.module.scss
│ │ │ ├── Card.spec.ts
│ │ │ ├── Card.tsx
│ │ │ └── CardNative.tsx
│ │ ├── Carousel
│ │ │ ├── Carousel.md
│ │ │ ├── Carousel.module.scss
│ │ │ ├── Carousel.spec.ts
│ │ │ ├── Carousel.tsx
│ │ │ ├── CarouselContext.tsx
│ │ │ ├── CarouselItem.tsx
│ │ │ ├── CarouselItemNative.tsx
│ │ │ └── CarouselNative.tsx
│ │ ├── ChangeListener
│ │ │ ├── ChangeListener.md
│ │ │ ├── ChangeListener.spec.ts
│ │ │ ├── ChangeListener.tsx
│ │ │ └── ChangeListenerNative.tsx
│ │ ├── chart-color-schemes.ts
│ │ ├── Charts
│ │ │ ├── AreaChart
│ │ │ │ ├── AreaChart.md
│ │ │ │ ├── AreaChart.spec.ts
│ │ │ │ ├── AreaChart.tsx
│ │ │ │ └── AreaChartNative.tsx
│ │ │ ├── BarChart
│ │ │ │ ├── BarChart.md
│ │ │ │ ├── BarChart.module.scss
│ │ │ │ ├── BarChart.spec.ts
│ │ │ │ ├── BarChart.tsx
│ │ │ │ └── BarChartNative.tsx
│ │ │ ├── DonutChart
│ │ │ │ ├── DonutChart.spec.ts
│ │ │ │ └── DonutChart.tsx
│ │ │ ├── LabelList
│ │ │ │ ├── LabelList.module.scss
│ │ │ │ ├── LabelList.spec.ts
│ │ │ │ ├── LabelList.tsx
│ │ │ │ └── LabelListNative.tsx
│ │ │ ├── Legend
│ │ │ │ ├── Legend.spec.ts
│ │ │ │ ├── Legend.tsx
│ │ │ │ └── LegendNative.tsx
│ │ │ ├── LineChart
│ │ │ │ ├── LineChart.md
│ │ │ │ ├── LineChart.module.scss
│ │ │ │ ├── LineChart.spec.ts
│ │ │ │ ├── LineChart.tsx
│ │ │ │ └── LineChartNative.tsx
│ │ │ ├── PieChart
│ │ │ │ ├── PieChart.md
│ │ │ │ ├── PieChart.spec.ts
│ │ │ │ ├── PieChart.tsx
│ │ │ │ ├── PieChartNative.module.scss
│ │ │ │ └── PieChartNative.tsx
│ │ │ ├── RadarChart
│ │ │ │ ├── RadarChart.md
│ │ │ │ ├── RadarChart.spec.ts
│ │ │ │ ├── RadarChart.tsx
│ │ │ │ └── RadarChartNative.tsx
│ │ │ ├── Tooltip
│ │ │ │ ├── TooltipContent.module.scss
│ │ │ │ ├── TooltipContent.spec.ts
│ │ │ │ └── TooltipContent.tsx
│ │ │ └── utils
│ │ │ ├── abstractions.ts
│ │ │ └── ChartProvider.tsx
│ │ ├── Checkbox
│ │ │ ├── Checkbox.md
│ │ │ ├── Checkbox.spec.ts
│ │ │ └── Checkbox.tsx
│ │ ├── CodeBlock
│ │ │ ├── CodeBlock.module.scss
│ │ │ ├── CodeBlock.spec.ts
│ │ │ ├── CodeBlock.tsx
│ │ │ ├── CodeBlockNative.tsx
│ │ │ └── highlight-code.ts
│ │ ├── collectedComponentMetadata.ts
│ │ ├── ColorPicker
│ │ │ ├── ColorPicker.md
│ │ │ ├── ColorPicker.module.scss
│ │ │ ├── ColorPicker.spec.ts
│ │ │ ├── ColorPicker.tsx
│ │ │ └── ColorPickerNative.tsx
│ │ ├── Column
│ │ │ ├── Column.md
│ │ │ ├── Column.tsx
│ │ │ ├── ColumnNative.tsx
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ └── TableContext.tsx
│ │ ├── component-utils.ts
│ │ ├── ComponentProvider.tsx
│ │ ├── ComponentRegistryContext.tsx
│ │ ├── container-helpers.tsx
│ │ ├── ContentSeparator
│ │ │ ├── ContentSeparator.md
│ │ │ ├── ContentSeparator.module.scss
│ │ │ ├── ContentSeparator.spec.ts
│ │ │ ├── ContentSeparator.tsx
│ │ │ ├── ContentSeparatorNative.tsx
│ │ │ └── test-padding.xmlui
│ │ ├── DataSource
│ │ │ ├── DataSource.md
│ │ │ └── DataSource.tsx
│ │ ├── DateInput
│ │ │ ├── DateInput.md
│ │ │ ├── DateInput.module.scss
│ │ │ ├── DateInput.spec.ts
│ │ │ ├── DateInput.tsx
│ │ │ └── DateInputNative.tsx
│ │ ├── DatePicker
│ │ │ ├── DatePicker.md
│ │ │ ├── DatePicker.module.scss
│ │ │ ├── DatePicker.spec.ts
│ │ │ ├── DatePicker.tsx
│ │ │ └── DatePickerNative.tsx
│ │ ├── DropdownMenu
│ │ │ ├── DropdownMenu.md
│ │ │ ├── DropdownMenu.module.scss
│ │ │ ├── DropdownMenu.spec.ts
│ │ │ ├── DropdownMenu.tsx
│ │ │ ├── DropdownMenuNative.tsx
│ │ │ ├── MenuItem.md
│ │ │ └── SubMenuItem.md
│ │ ├── EmojiSelector
│ │ │ ├── EmojiSelector.md
│ │ │ ├── EmojiSelector.spec.ts
│ │ │ ├── EmojiSelector.tsx
│ │ │ └── EmojiSelectorNative.tsx
│ │ ├── ExpandableItem
│ │ │ ├── ExpandableItem.module.scss
│ │ │ ├── ExpandableItem.spec.ts
│ │ │ ├── ExpandableItem.tsx
│ │ │ └── ExpandableItemNative.tsx
│ │ ├── FileInput
│ │ │ ├── FileInput.md
│ │ │ ├── FileInput.module.scss
│ │ │ ├── FileInput.spec.ts
│ │ │ ├── FileInput.tsx
│ │ │ └── FileInputNative.tsx
│ │ ├── FileUploadDropZone
│ │ │ ├── FileUploadDropZone.md
│ │ │ ├── FileUploadDropZone.module.scss
│ │ │ ├── FileUploadDropZone.spec.ts
│ │ │ ├── FileUploadDropZone.tsx
│ │ │ └── FileUploadDropZoneNative.tsx
│ │ ├── FlowLayout
│ │ │ ├── FlowLayout.md
│ │ │ ├── FlowLayout.module.scss
│ │ │ ├── FlowLayout.spec.ts
│ │ │ ├── FlowLayout.spec.ts-snapshots
│ │ │ │ └── Edge-cases-boxShadow-is-not-clipped-1-non-smoke-darwin.png
│ │ │ ├── FlowLayout.tsx
│ │ │ └── FlowLayoutNative.tsx
│ │ ├── Footer
│ │ │ ├── Footer.md
│ │ │ ├── Footer.module.scss
│ │ │ ├── Footer.spec.ts
│ │ │ ├── Footer.tsx
│ │ │ └── FooterNative.tsx
│ │ ├── Form
│ │ │ ├── Form.md
│ │ │ ├── Form.module.scss
│ │ │ ├── Form.spec.ts
│ │ │ ├── Form.tsx
│ │ │ ├── formActions.ts
│ │ │ ├── FormContext.ts
│ │ │ └── FormNative.tsx
│ │ ├── FormItem
│ │ │ ├── FormItem.md
│ │ │ ├── FormItem.module.scss
│ │ │ ├── FormItem.spec.ts
│ │ │ ├── FormItem.tsx
│ │ │ ├── FormItemNative.tsx
│ │ │ ├── HelperText.module.scss
│ │ │ ├── HelperText.tsx
│ │ │ ├── ItemWithLabel.tsx
│ │ │ └── Validations.ts
│ │ ├── FormSection
│ │ │ ├── FormSection.md
│ │ │ ├── FormSection.ts
│ │ │ └── FormSection.xmlui
│ │ ├── Fragment
│ │ │ ├── Fragment.spec.ts
│ │ │ └── Fragment.tsx
│ │ ├── Heading
│ │ │ ├── abstractions.ts
│ │ │ ├── H1.md
│ │ │ ├── H1.spec.ts
│ │ │ ├── H2.md
│ │ │ ├── H2.spec.ts
│ │ │ ├── H3.md
│ │ │ ├── H3.spec.ts
│ │ │ ├── H4.md
│ │ │ ├── H4.spec.ts
│ │ │ ├── H5.md
│ │ │ ├── H5.spec.ts
│ │ │ ├── H6.md
│ │ │ ├── H6.spec.ts
│ │ │ ├── Heading.md
│ │ │ ├── Heading.module.scss
│ │ │ ├── Heading.spec.ts
│ │ │ ├── Heading.tsx
│ │ │ └── HeadingNative.tsx
│ │ ├── HoverCard
│ │ │ ├── HoverCard.tsx
│ │ │ └── HovercardNative.tsx
│ │ ├── HtmlTags
│ │ │ ├── HtmlTags.module.scss
│ │ │ ├── HtmlTags.spec.ts
│ │ │ └── HtmlTags.tsx
│ │ ├── Icon
│ │ │ ├── AdmonitionDanger.tsx
│ │ │ ├── AdmonitionInfo.tsx
│ │ │ ├── AdmonitionNote.tsx
│ │ │ ├── AdmonitionTip.tsx
│ │ │ ├── AdmonitionWarning.tsx
│ │ │ ├── ApiIcon.tsx
│ │ │ ├── ArrowDropDown.module.scss
│ │ │ ├── ArrowDropDown.tsx
│ │ │ ├── ArrowDropUp.module.scss
│ │ │ ├── ArrowDropUp.tsx
│ │ │ ├── ArrowLeft.module.scss
│ │ │ ├── ArrowLeft.tsx
│ │ │ ├── ArrowRight.module.scss
│ │ │ ├── ArrowRight.tsx
│ │ │ ├── Attach.tsx
│ │ │ ├── Binding.module.scss
│ │ │ ├── Binding.tsx
│ │ │ ├── BoardIcon.tsx
│ │ │ ├── BoxIcon.tsx
│ │ │ ├── CheckIcon.tsx
│ │ │ ├── ChevronDownIcon.tsx
│ │ │ ├── ChevronLeft.tsx
│ │ │ ├── ChevronRight.tsx
│ │ │ ├── ChevronUpIcon.tsx
│ │ │ ├── CodeFileIcon.tsx
│ │ │ ├── CodeSandbox.tsx
│ │ │ ├── CompactListIcon.tsx
│ │ │ ├── ContentCopyIcon.tsx
│ │ │ ├── DarkToLightIcon.tsx
│ │ │ ├── DatabaseIcon.module.scss
│ │ │ ├── DatabaseIcon.tsx
│ │ │ ├── DocFileIcon.tsx
│ │ │ ├── DocIcon.tsx
│ │ │ ├── DotMenuHorizontalIcon.tsx
│ │ │ ├── DotMenuIcon.tsx
│ │ │ ├── EmailIcon.tsx
│ │ │ ├── EmptyFolderIcon.tsx
│ │ │ ├── ErrorIcon.tsx
│ │ │ ├── ExpressionIcon.tsx
│ │ │ ├── FillPlusCricleIcon.tsx
│ │ │ ├── FilterIcon.tsx
│ │ │ ├── FolderIcon.tsx
│ │ │ ├── GlobeIcon.tsx
│ │ │ ├── HomeIcon.tsx
│ │ │ ├── HyperLinkIcon.tsx
│ │ │ ├── Icon.md
│ │ │ ├── Icon.module.scss
│ │ │ ├── Icon.spec.ts
│ │ │ ├── Icon.tsx
│ │ │ ├── IconNative.tsx
│ │ │ ├── ImageFileIcon.tsx
│ │ │ ├── Inspect.tsx
│ │ │ ├── LightToDark.tsx
│ │ │ ├── LinkIcon.tsx
│ │ │ ├── ListIcon.tsx
│ │ │ ├── LooseListIcon.tsx
│ │ │ ├── MoonIcon.tsx
│ │ │ ├── MoreOptionsIcon.tsx
│ │ │ ├── NoSortIcon.tsx
│ │ │ ├── PDFIcon.tsx
│ │ │ ├── PenIcon.tsx
│ │ │ ├── PhoneIcon.tsx
│ │ │ ├── PhotoIcon.tsx
│ │ │ ├── PlusIcon.tsx
│ │ │ ├── SearchIcon.tsx
│ │ │ ├── ShareIcon.tsx
│ │ │ ├── SortAscendingIcon.tsx
│ │ │ ├── SortDescendingIcon.tsx
│ │ │ ├── StarsIcon.tsx
│ │ │ ├── SunIcon.tsx
│ │ │ ├── svg
│ │ │ │ ├── admonition_danger.svg
│ │ │ │ ├── admonition_info.svg
│ │ │ │ ├── admonition_note.svg
│ │ │ │ ├── admonition_tip.svg
│ │ │ │ ├── admonition_warning.svg
│ │ │ │ ├── api.svg
│ │ │ │ ├── arrow-dropdown.svg
│ │ │ │ ├── arrow-left.svg
│ │ │ │ ├── arrow-right.svg
│ │ │ │ ├── arrow-up.svg
│ │ │ │ ├── attach.svg
│ │ │ │ ├── binding.svg
│ │ │ │ ├── box.svg
│ │ │ │ ├── bulb.svg
│ │ │ │ ├── code-file.svg
│ │ │ │ ├── code-sandbox.svg
│ │ │ │ ├── dark_to_light.svg
│ │ │ │ ├── database.svg
│ │ │ │ ├── doc.svg
│ │ │ │ ├── empty-folder.svg
│ │ │ │ ├── expression.svg
│ │ │ │ ├── eye-closed.svg
│ │ │ │ ├── eye-dark.svg
│ │ │ │ ├── eye.svg
│ │ │ │ ├── file-text.svg
│ │ │ │ ├── filter.svg
│ │ │ │ ├── folder.svg
│ │ │ │ ├── img.svg
│ │ │ │ ├── inspect.svg
│ │ │ │ ├── light_to_dark.svg
│ │ │ │ ├── moon.svg
│ │ │ │ ├── pdf.svg
│ │ │ │ ├── photo.svg
│ │ │ │ ├── share.svg
│ │ │ │ ├── stars.svg
│ │ │ │ ├── sun.svg
│ │ │ │ ├── trending-down.svg
│ │ │ │ ├── trending-level.svg
│ │ │ │ ├── trending-up.svg
│ │ │ │ ├── txt.svg
│ │ │ │ ├── unknown-file.svg
│ │ │ │ ├── unlink.svg
│ │ │ │ └── xls.svg
│ │ │ ├── TableDeleteColumnIcon.tsx
│ │ │ ├── TableDeleteRowIcon.tsx
│ │ │ ├── TableInsertColumnIcon.tsx
│ │ │ ├── TableInsertRowIcon.tsx
│ │ │ ├── TrashIcon.tsx
│ │ │ ├── TrendingDownIcon.tsx
│ │ │ ├── TrendingLevelIcon.tsx
│ │ │ ├── TrendingUpIcon.tsx
│ │ │ ├── TxtIcon.tsx
│ │ │ ├── UnknownFileIcon.tsx
│ │ │ ├── UnlinkIcon.tsx
│ │ │ ├── UserIcon.tsx
│ │ │ ├── WarningIcon.tsx
│ │ │ └── XlsIcon.tsx
│ │ ├── IconProvider.tsx
│ │ ├── IconRegistryContext.tsx
│ │ ├── IFrame
│ │ │ ├── IFrame.md
│ │ │ ├── IFrame.module.scss
│ │ │ ├── IFrame.spec.ts
│ │ │ ├── IFrame.tsx
│ │ │ └── IFrameNative.tsx
│ │ ├── Image
│ │ │ ├── Image.md
│ │ │ ├── Image.module.scss
│ │ │ ├── Image.spec.ts
│ │ │ ├── Image.tsx
│ │ │ └── ImageNative.tsx
│ │ ├── Input
│ │ │ ├── index.ts
│ │ │ ├── InputAdornment.module.scss
│ │ │ ├── InputAdornment.tsx
│ │ │ ├── InputDivider.module.scss
│ │ │ ├── InputDivider.tsx
│ │ │ ├── InputLabel.module.scss
│ │ │ ├── InputLabel.tsx
│ │ │ ├── PartialInput.module.scss
│ │ │ └── PartialInput.tsx
│ │ ├── InspectButton
│ │ │ ├── InspectButton.module.scss
│ │ │ └── InspectButton.tsx
│ │ ├── Items
│ │ │ ├── Items.md
│ │ │ ├── Items.spec.ts
│ │ │ ├── Items.tsx
│ │ │ └── ItemsNative.tsx
│ │ ├── Link
│ │ │ ├── Link.md
│ │ │ ├── Link.module.scss
│ │ │ ├── Link.spec.ts
│ │ │ ├── Link.tsx
│ │ │ └── LinkNative.tsx
│ │ ├── List
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ ├── List.md
│ │ │ ├── List.module.scss
│ │ │ ├── List.spec.ts
│ │ │ ├── List.tsx
│ │ │ └── ListNative.tsx
│ │ ├── Logo
│ │ │ ├── doc-resources
│ │ │ │ └── xmlui-logo.svg
│ │ │ ├── Logo.md
│ │ │ ├── Logo.tsx
│ │ │ └── LogoNative.tsx
│ │ ├── Markdown
│ │ │ ├── CodeText.module.scss
│ │ │ ├── CodeText.tsx
│ │ │ ├── Markdown.md
│ │ │ ├── Markdown.module.scss
│ │ │ ├── Markdown.spec.ts
│ │ │ ├── Markdown.tsx
│ │ │ ├── MarkdownNative.tsx
│ │ │ ├── parse-binding-expr.ts
│ │ │ └── utils.ts
│ │ ├── metadata-helpers.ts
│ │ ├── ModalDialog
│ │ │ ├── ConfirmationModalContextProvider.tsx
│ │ │ ├── Dialog.module.scss
│ │ │ ├── Dialog.tsx
│ │ │ ├── ModalDialog.md
│ │ │ ├── ModalDialog.module.scss
│ │ │ ├── ModalDialog.spec.ts
│ │ │ ├── ModalDialog.tsx
│ │ │ ├── ModalDialogNative.tsx
│ │ │ └── ModalVisibilityContext.tsx
│ │ ├── NavGroup
│ │ │ ├── NavGroup.md
│ │ │ ├── NavGroup.module.scss
│ │ │ ├── NavGroup.spec.ts
│ │ │ ├── NavGroup.tsx
│ │ │ ├── NavGroupContext.ts
│ │ │ └── NavGroupNative.tsx
│ │ ├── NavLink
│ │ │ ├── NavLink.md
│ │ │ ├── NavLink.module.scss
│ │ │ ├── NavLink.spec.ts
│ │ │ ├── NavLink.tsx
│ │ │ └── NavLinkNative.tsx
│ │ ├── NavPanel
│ │ │ ├── NavPanel.md
│ │ │ ├── NavPanel.module.scss
│ │ │ ├── NavPanel.spec.ts
│ │ │ ├── NavPanel.tsx
│ │ │ └── NavPanelNative.tsx
│ │ ├── NestedApp
│ │ │ ├── AppWithCodeView.module.scss
│ │ │ ├── AppWithCodeView.tsx
│ │ │ ├── AppWithCodeViewNative.tsx
│ │ │ ├── defaultProps.tsx
│ │ │ ├── logo.svg
│ │ │ ├── NestedApp.module.scss
│ │ │ ├── NestedApp.tsx
│ │ │ ├── NestedAppNative.tsx
│ │ │ ├── Tooltip.module.scss
│ │ │ ├── Tooltip.tsx
│ │ │ └── utils.ts
│ │ ├── NoResult
│ │ │ ├── NoResult.md
│ │ │ ├── NoResult.module.scss
│ │ │ ├── NoResult.spec.ts
│ │ │ ├── NoResult.tsx
│ │ │ └── NoResultNative.tsx
│ │ ├── NumberBox
│ │ │ ├── numberbox-abstractions.ts
│ │ │ ├── NumberBox.md
│ │ │ ├── NumberBox.module.scss
│ │ │ ├── NumberBox.spec.ts
│ │ │ ├── NumberBox.tsx
│ │ │ └── NumberBoxNative.tsx
│ │ ├── Option
│ │ │ ├── Option.md
│ │ │ ├── Option.spec.ts
│ │ │ ├── Option.tsx
│ │ │ ├── OptionNative.tsx
│ │ │ └── OptionTypeProvider.tsx
│ │ ├── PageMetaTitle
│ │ │ ├── PageMetaTilteNative.tsx
│ │ │ ├── PageMetaTitle.md
│ │ │ ├── PageMetaTitle.spec.ts
│ │ │ └── PageMetaTitle.tsx
│ │ ├── Pages
│ │ │ ├── Page.md
│ │ │ ├── Pages.md
│ │ │ ├── Pages.module.scss
│ │ │ ├── Pages.tsx
│ │ │ └── PagesNative.tsx
│ │ ├── Pagination
│ │ │ ├── Pagination.md
│ │ │ ├── Pagination.module.scss
│ │ │ ├── Pagination.spec.ts
│ │ │ ├── Pagination.tsx
│ │ │ └── PaginationNative.tsx
│ │ ├── PositionedContainer
│ │ │ ├── PositionedContainer.module.scss
│ │ │ ├── PositionedContainer.tsx
│ │ │ └── PositionedContainerNative.tsx
│ │ ├── ProfileMenu
│ │ │ ├── ProfileMenu.module.scss
│ │ │ └── ProfileMenu.tsx
│ │ ├── ProgressBar
│ │ │ ├── ProgressBar.md
│ │ │ ├── ProgressBar.module.scss
│ │ │ ├── ProgressBar.spec.ts
│ │ │ ├── ProgressBar.tsx
│ │ │ └── ProgressBarNative.tsx
│ │ ├── Queue
│ │ │ ├── Queue.md
│ │ │ ├── Queue.spec.ts
│ │ │ ├── Queue.tsx
│ │ │ ├── queueActions.ts
│ │ │ └── QueueNative.tsx
│ │ ├── RadioGroup
│ │ │ ├── RadioGroup.md
│ │ │ ├── RadioGroup.module.scss
│ │ │ ├── RadioGroup.spec.ts
│ │ │ ├── RadioGroup.tsx
│ │ │ ├── RadioGroupNative.tsx
│ │ │ ├── RadioItem.tsx
│ │ │ └── RadioItemNative.tsx
│ │ ├── RealTimeAdapter
│ │ │ ├── RealTimeAdapter.tsx
│ │ │ └── RealTimeAdapterNative.tsx
│ │ ├── Redirect
│ │ │ ├── Redirect.md
│ │ │ ├── Redirect.spec.ts
│ │ │ └── Redirect.tsx
│ │ ├── ResponsiveBar
│ │ │ ├── README.md
│ │ │ ├── ResponsiveBar.md
│ │ │ ├── ResponsiveBar.module.scss
│ │ │ ├── ResponsiveBar.spec.ts
│ │ │ ├── ResponsiveBar.tsx
│ │ │ └── ResponsiveBarNative.tsx
│ │ ├── Select
│ │ │ ├── HiddenOption.tsx
│ │ │ ├── OptionContext.ts
│ │ │ ├── Select.md
│ │ │ ├── Select.module.scss
│ │ │ ├── Select.spec.ts
│ │ │ ├── Select.tsx
│ │ │ ├── SelectContext.tsx
│ │ │ └── SelectNative.tsx
│ │ ├── SelectionStore
│ │ │ ├── SelectionStore.md
│ │ │ ├── SelectionStore.tsx
│ │ │ └── SelectionStoreNative.tsx
│ │ ├── Slider
│ │ │ ├── Slider.md
│ │ │ ├── Slider.module.scss
│ │ │ ├── Slider.spec.ts
│ │ │ ├── Slider.tsx
│ │ │ └── SliderNative.tsx
│ │ ├── Slot
│ │ │ ├── Slot.md
│ │ │ ├── Slot.spec.ts
│ │ │ └── Slot.ts
│ │ ├── SlotItem.tsx
│ │ ├── SpaceFiller
│ │ │ ├── SpaceFiller.md
│ │ │ ├── SpaceFiller.module.scss
│ │ │ ├── SpaceFiller.spec.ts
│ │ │ ├── SpaceFiller.tsx
│ │ │ └── SpaceFillerNative.tsx
│ │ ├── Spinner
│ │ │ ├── Spinner.md
│ │ │ ├── Spinner.module.scss
│ │ │ ├── Spinner.spec.ts
│ │ │ ├── Spinner.tsx
│ │ │ └── SpinnerNative.tsx
│ │ ├── Splitter
│ │ │ ├── HSplitter.md
│ │ │ ├── HSplitter.spec.ts
│ │ │ ├── Splitter.md
│ │ │ ├── Splitter.module.scss
│ │ │ ├── Splitter.spec.ts
│ │ │ ├── Splitter.tsx
│ │ │ ├── SplitterNative.tsx
│ │ │ ├── utils.ts
│ │ │ ├── VSplitter.md
│ │ │ └── VSplitter.spec.ts
│ │ ├── Stack
│ │ │ ├── CHStack.md
│ │ │ ├── CHStack.spec.ts
│ │ │ ├── CVStack.md
│ │ │ ├── CVStack.spec.ts
│ │ │ ├── HStack.md
│ │ │ ├── HStack.spec.ts
│ │ │ ├── Stack.md
│ │ │ ├── Stack.module.scss
│ │ │ ├── Stack.spec.ts
│ │ │ ├── Stack.tsx
│ │ │ ├── StackNative.tsx
│ │ │ ├── VStack.md
│ │ │ └── VStack.spec.ts
│ │ ├── StickyBox
│ │ │ ├── StickyBox.md
│ │ │ ├── StickyBox.module.scss
│ │ │ ├── StickyBox.tsx
│ │ │ └── StickyBoxNative.tsx
│ │ ├── Switch
│ │ │ ├── Switch.md
│ │ │ ├── Switch.spec.ts
│ │ │ └── Switch.tsx
│ │ ├── Table
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ ├── react-table-config.d.ts
│ │ │ ├── Table.md
│ │ │ ├── Table.module.scss
│ │ │ ├── Table.spec.ts
│ │ │ ├── Table.tsx
│ │ │ ├── TableNative.tsx
│ │ │ └── useRowSelection.tsx
│ │ ├── TableOfContents
│ │ │ ├── TableOfContents.module.scss
│ │ │ ├── TableOfContents.spec.ts
│ │ │ ├── TableOfContents.tsx
│ │ │ └── TableOfContentsNative.tsx
│ │ ├── Tabs
│ │ │ ├── TabContext.tsx
│ │ │ ├── TabItem.md
│ │ │ ├── TabItem.tsx
│ │ │ ├── TabItemNative.tsx
│ │ │ ├── Tabs.md
│ │ │ ├── Tabs.module.scss
│ │ │ ├── Tabs.spec.ts
│ │ │ ├── Tabs.tsx
│ │ │ └── TabsNative.tsx
│ │ ├── Text
│ │ │ ├── Text.md
│ │ │ ├── Text.module.scss
│ │ │ ├── Text.spec.ts
│ │ │ ├── Text.tsx
│ │ │ └── TextNative.tsx
│ │ ├── TextArea
│ │ │ ├── TextArea.md
│ │ │ ├── TextArea.module.scss
│ │ │ ├── TextArea.spec.ts
│ │ │ ├── TextArea.tsx
│ │ │ ├── TextAreaNative.tsx
│ │ │ ├── TextAreaResizable.tsx
│ │ │ └── useComposedRef.ts
│ │ ├── TextBox
│ │ │ ├── TextBox.md
│ │ │ ├── TextBox.module.scss
│ │ │ ├── TextBox.spec.ts
│ │ │ ├── TextBox.tsx
│ │ │ └── TextBoxNative.tsx
│ │ ├── Theme
│ │ │ ├── NotificationToast.tsx
│ │ │ ├── Theme.md
│ │ │ ├── Theme.module.scss
│ │ │ ├── Theme.spec.ts
│ │ │ ├── Theme.tsx
│ │ │ └── ThemeNative.tsx
│ │ ├── TimeInput
│ │ │ ├── TimeInput.md
│ │ │ ├── TimeInput.module.scss
│ │ │ ├── TimeInput.spec.ts
│ │ │ ├── TimeInput.tsx
│ │ │ ├── TimeInputNative.tsx
│ │ │ └── utils.ts
│ │ ├── Timer
│ │ │ ├── Timer.md
│ │ │ ├── Timer.spec.ts
│ │ │ ├── Timer.tsx
│ │ │ └── TimerNative.tsx
│ │ ├── Toggle
│ │ │ ├── Toggle.module.scss
│ │ │ └── Toggle.tsx
│ │ ├── ToneChangerButton
│ │ │ ├── ToneChangerButton.md
│ │ │ ├── ToneChangerButton.spec.ts
│ │ │ └── ToneChangerButton.tsx
│ │ ├── ToneSwitch
│ │ │ ├── ToneSwitch.md
│ │ │ ├── ToneSwitch.module.scss
│ │ │ ├── ToneSwitch.spec.ts
│ │ │ ├── ToneSwitch.tsx
│ │ │ └── ToneSwitchNative.tsx
│ │ ├── Tooltip
│ │ │ ├── Tooltip.md
│ │ │ ├── Tooltip.module.scss
│ │ │ ├── Tooltip.spec.ts
│ │ │ ├── Tooltip.tsx
│ │ │ └── TooltipNative.tsx
│ │ ├── Tree
│ │ │ ├── testData.ts
│ │ │ ├── Tree-dynamic.spec.ts
│ │ │ ├── Tree-icons.spec.ts
│ │ │ ├── Tree.md
│ │ │ ├── Tree.spec.ts
│ │ │ ├── TreeComponent.module.scss
│ │ │ ├── TreeComponent.tsx
│ │ │ └── TreeNative.tsx
│ │ ├── TreeDisplay
│ │ │ ├── TreeDisplay.md
│ │ │ ├── TreeDisplay.module.scss
│ │ │ ├── TreeDisplay.tsx
│ │ │ └── TreeDisplayNative.tsx
│ │ ├── ValidationSummary
│ │ │ ├── ValidationSummary.module.scss
│ │ │ └── ValidationSummary.tsx
│ │ └── VisuallyHidden.tsx
│ ├── components-core
│ │ ├── abstractions
│ │ │ ├── ComponentRenderer.ts
│ │ │ ├── LoaderRenderer.ts
│ │ │ ├── standalone.ts
│ │ │ └── treeAbstractions.ts
│ │ ├── action
│ │ │ ├── actions.ts
│ │ │ ├── APICall.tsx
│ │ │ ├── FileDownloadAction.tsx
│ │ │ ├── FileUploadAction.tsx
│ │ │ ├── NavigateAction.tsx
│ │ │ └── TimedAction.tsx
│ │ ├── ApiBoundComponent.tsx
│ │ ├── appContext
│ │ │ ├── date-functions.ts
│ │ │ ├── math-function.ts
│ │ │ └── misc-utils.ts
│ │ ├── AppContext.tsx
│ │ ├── behaviors
│ │ │ ├── Behavior.tsx
│ │ │ └── CoreBehaviors.tsx
│ │ ├── component-hooks.ts
│ │ ├── ComponentDecorator.tsx
│ │ ├── ComponentViewer.tsx
│ │ ├── CompoundComponent.tsx
│ │ ├── constants.ts
│ │ ├── DebugViewProvider.tsx
│ │ ├── descriptorHelper.ts
│ │ ├── devtools
│ │ │ ├── InspectorDialog.module.scss
│ │ │ ├── InspectorDialog.tsx
│ │ │ └── InspectorDialogVisibilityContext.tsx
│ │ ├── EngineError.ts
│ │ ├── event-handlers.ts
│ │ ├── InspectorButton.module.scss
│ │ ├── InspectorContext.tsx
│ │ ├── interception
│ │ │ ├── abstractions.ts
│ │ │ ├── ApiInterceptor.ts
│ │ │ ├── ApiInterceptorProvider.tsx
│ │ │ ├── apiInterceptorWorker.ts
│ │ │ ├── Backend.ts
│ │ │ ├── Errors.ts
│ │ │ ├── IndexedDb.ts
│ │ │ ├── initMock.ts
│ │ │ ├── InMemoryDb.ts
│ │ │ ├── ReadonlyCollection.ts
│ │ │ └── useApiInterceptorContext.tsx
│ │ ├── loader
│ │ │ ├── ApiLoader.tsx
│ │ │ ├── DataLoader.tsx
│ │ │ ├── ExternalDataLoader.tsx
│ │ │ ├── Loader.tsx
│ │ │ ├── MockLoaderRenderer.tsx
│ │ │ └── PageableLoader.tsx
│ │ ├── LoaderComponent.tsx
│ │ ├── markup-check.ts
│ │ ├── parts.ts
│ │ ├── renderers.ts
│ │ ├── rendering
│ │ │ ├── AppContent.tsx
│ │ │ ├── AppRoot.tsx
│ │ │ ├── AppWrapper.tsx
│ │ │ ├── buildProxy.ts
│ │ │ ├── collectFnVarDeps.ts
│ │ │ ├── ComponentAdapter.tsx
│ │ │ ├── ComponentWrapper.tsx
│ │ │ ├── Container.tsx
│ │ │ ├── containers.ts
│ │ │ ├── ContainerWrapper.tsx
│ │ │ ├── ErrorBoundary.module.scss
│ │ │ ├── ErrorBoundary.tsx
│ │ │ ├── InvalidComponent.module.scss
│ │ │ ├── InvalidComponent.tsx
│ │ │ ├── nodeUtils.ts
│ │ │ ├── reducer.ts
│ │ │ ├── renderChild.tsx
│ │ │ ├── StandaloneComponent.tsx
│ │ │ ├── StateContainer.tsx
│ │ │ ├── UnknownComponent.module.scss
│ │ │ ├── UnknownComponent.tsx
│ │ │ └── valueExtractor.ts
│ │ ├── reportEngineError.ts
│ │ ├── RestApiProxy.ts
│ │ ├── script-runner
│ │ │ ├── asyncProxy.ts
│ │ │ ├── AttributeValueParser.ts
│ │ │ ├── bannedFunctions.ts
│ │ │ ├── BindingTreeEvaluationContext.ts
│ │ │ ├── eval-tree-async.ts
│ │ │ ├── eval-tree-common.ts
│ │ │ ├── eval-tree-sync.ts
│ │ │ ├── ParameterParser.ts
│ │ │ ├── process-statement-async.ts
│ │ │ ├── process-statement-common.ts
│ │ │ ├── process-statement-sync.ts
│ │ │ ├── ScriptingSourceTree.ts
│ │ │ ├── simplify-expression.ts
│ │ │ ├── statement-queue.ts
│ │ │ └── visitors.ts
│ │ ├── StandaloneApp.tsx
│ │ ├── StandaloneExtensionManager.ts
│ │ ├── TableOfContentsContext.tsx
│ │ ├── theming
│ │ │ ├── _themes.scss
│ │ │ ├── component-layout-resolver.ts
│ │ │ ├── extendThemeUtils.ts
│ │ │ ├── hvar.ts
│ │ │ ├── layout-resolver.ts
│ │ │ ├── parse-layout-props.ts
│ │ │ ├── StyleContext.tsx
│ │ │ ├── StyleRegistry.ts
│ │ │ ├── ThemeContext.tsx
│ │ │ ├── ThemeProvider.tsx
│ │ │ ├── themes
│ │ │ │ ├── base-utils.ts
│ │ │ │ ├── palette.ts
│ │ │ │ ├── root.ts
│ │ │ │ ├── solid.ts
│ │ │ │ ├── theme-colors.ts
│ │ │ │ └── xmlui.ts
│ │ │ ├── themeVars.module.scss
│ │ │ ├── themeVars.ts
│ │ │ ├── transformThemeVars.ts
│ │ │ └── utils.ts
│ │ ├── utils
│ │ │ ├── actionUtils.ts
│ │ │ ├── audio-utils.ts
│ │ │ ├── base64-utils.ts
│ │ │ ├── compound-utils.ts
│ │ │ ├── css-utils.ts
│ │ │ ├── DataLoaderQueryKeyGenerator.ts
│ │ │ ├── date-utils.ts
│ │ │ ├── extractParam.ts
│ │ │ ├── hooks.tsx
│ │ │ ├── LruCache.ts
│ │ │ ├── mergeProps.ts
│ │ │ ├── misc.ts
│ │ │ ├── request-params.ts
│ │ │ ├── statementUtils.ts
│ │ │ └── treeUtils.ts
│ │ └── xmlui-parser.ts
│ ├── index-standalone.ts
│ ├── index.scss
│ ├── index.ts
│ ├── language-server
│ │ ├── server-common.ts
│ │ ├── server-web-worker.ts
│ │ ├── server.ts
│ │ ├── services
│ │ │ ├── common
│ │ │ │ ├── docs-generation.ts
│ │ │ │ ├── lsp-utils.ts
│ │ │ │ ├── metadata-utils.ts
│ │ │ │ └── syntax-node-utilities.ts
│ │ │ ├── completion.ts
│ │ │ ├── diagnostic.ts
│ │ │ ├── format.ts
│ │ │ └── hover.ts
│ │ └── xmlui-metadata-generated.js
│ ├── logging
│ │ ├── LoggerContext.tsx
│ │ ├── LoggerInitializer.tsx
│ │ ├── LoggerService.ts
│ │ └── xmlui.ts
│ ├── logo.svg
│ ├── parsers
│ │ ├── common
│ │ │ ├── GenericToken.ts
│ │ │ ├── InputStream.ts
│ │ │ └── utils.ts
│ │ ├── scripting
│ │ │ ├── code-behind-collect.ts
│ │ │ ├── Lexer.ts
│ │ │ ├── modules.ts
│ │ │ ├── Parser.ts
│ │ │ ├── ParserError.ts
│ │ │ ├── ScriptingNodeTypes.ts
│ │ │ ├── TokenTrait.ts
│ │ │ ├── TokenType.ts
│ │ │ └── tree-visitor.ts
│ │ ├── style-parser
│ │ │ ├── errors.ts
│ │ │ ├── source-tree.ts
│ │ │ ├── StyleInputStream.ts
│ │ │ ├── StyleLexer.ts
│ │ │ ├── StyleParser.ts
│ │ │ └── tokens.ts
│ │ └── xmlui-parser
│ │ ├── CharacterCodes.ts
│ │ ├── diagnostics.ts
│ │ ├── fileExtensions.ts
│ │ ├── index.ts
│ │ ├── lint.ts
│ │ ├── parser.ts
│ │ ├── ParserError.ts
│ │ ├── scanner.ts
│ │ ├── syntax-kind.ts
│ │ ├── syntax-node.ts
│ │ ├── transform.ts
│ │ ├── utils.ts
│ │ ├── xmlui-serializer.ts
│ │ └── xmlui-tree.ts
│ ├── react-app-env.d.ts
│ ├── syntax
│ │ ├── monaco
│ │ │ ├── grammar.monacoLanguage.ts
│ │ │ ├── index.ts
│ │ │ ├── xmlui-dark.ts
│ │ │ ├── xmlui-light.ts
│ │ │ └── xmluiscript.monacoLanguage.ts
│ │ └── textMate
│ │ ├── index.ts
│ │ ├── xmlui-dark.json
│ │ ├── xmlui-light.json
│ │ ├── xmlui.json
│ │ └── xmlui.tmLanguage.json
│ ├── testing
│ │ ├── assertions.ts
│ │ ├── component-test-helpers.ts
│ │ ├── ComponentDrivers.ts
│ │ ├── drivers
│ │ │ ├── DateInputDriver.ts
│ │ │ ├── index.ts
│ │ │ ├── ModalDialogDriver.ts
│ │ │ ├── NumberBoxDriver.ts
│ │ │ ├── TextBoxDriver.ts
│ │ │ ├── TimeInputDriver.ts
│ │ │ ├── TimerDriver.ts
│ │ │ └── TreeDriver.ts
│ │ ├── fixtures.ts
│ │ ├── index.ts
│ │ ├── infrastructure
│ │ │ ├── index.html
│ │ │ ├── main.tsx
│ │ │ ├── public
│ │ │ │ ├── mockServiceWorker.js
│ │ │ │ ├── resources
│ │ │ │ │ ├── bell.svg
│ │ │ │ │ ├── box.svg
│ │ │ │ │ ├── doc.svg
│ │ │ │ │ ├── eye.svg
│ │ │ │ │ ├── flower-640x480.jpg
│ │ │ │ │ ├── sun.svg
│ │ │ │ │ ├── test-image-100x100.jpg
│ │ │ │ │ └── txt.svg
│ │ │ │ └── serve.json
│ │ │ └── TestBed.tsx
│ │ └── themed-app-test-helpers.ts
│ └── vite-env.d.ts
├── tests
│ ├── components
│ │ ├── CodeBlock
│ │ │ └── hightlight-code.test.ts
│ │ ├── playground-pattern.test.ts
│ │ └── Tree
│ │ └── Tree-states.test.ts
│ ├── components-core
│ │ ├── abstractions
│ │ │ └── treeAbstractions.test.ts
│ │ ├── container
│ │ │ └── buildProxy.test.ts
│ │ ├── interception
│ │ │ ├── orderBy.test.ts
│ │ │ ├── ReadOnlyCollection.test.ts
│ │ │ └── request-param-converter.test.ts
│ │ ├── scripts-runner
│ │ │ ├── AttributeValueParser.test.ts
│ │ │ ├── eval-tree-arrow-async.test.ts
│ │ │ ├── eval-tree-arrow.test.ts
│ │ │ ├── eval-tree-func-decl-async.test.ts
│ │ │ ├── eval-tree-func-decl.test.ts
│ │ │ ├── eval-tree-pre-post.test.ts
│ │ │ ├── eval-tree-regression.test.ts
│ │ │ ├── eval-tree.test.ts
│ │ │ ├── function-proxy.test.ts
│ │ │ ├── parser-regression.test.ts
│ │ │ ├── process-event.test.ts
│ │ │ ├── process-function.test.ts
│ │ │ ├── process-implicit-context.test.ts
│ │ │ ├── process-statement-asgn.test.ts
│ │ │ ├── process-statement-destruct.test.ts
│ │ │ ├── process-statement-regs.test.ts
│ │ │ ├── process-statement-sync.test.ts
│ │ │ ├── process-statement.test.ts
│ │ │ ├── process-switch-sync.test.ts
│ │ │ ├── process-switch.test.ts
│ │ │ ├── process-try-sync.test.ts
│ │ │ ├── process-try.test.ts
│ │ │ └── test-helpers.ts
│ │ ├── test-metadata-handler.ts
│ │ ├── theming
│ │ │ ├── border-segments.test.ts
│ │ │ ├── component-layout.resolver.test.ts
│ │ │ ├── layout-property-parser.test.ts
│ │ │ ├── layout-resolver.test.ts
│ │ │ ├── layout-resolver2.test.ts
│ │ │ ├── layout-vp-override.test.ts
│ │ │ └── padding-segments.test.ts
│ │ └── utils
│ │ ├── date-utils.test.ts
│ │ ├── format-human-elapsed-time.test.ts
│ │ └── LruCache.test.ts
│ ├── language-server
│ │ ├── completion.test.ts
│ │ ├── format.test.ts
│ │ ├── hover.test.ts
│ │ └── mockData.ts
│ └── parsers
│ ├── common
│ │ └── input-stream.test.ts
│ ├── markdown
│ │ └── parse-binding-expression.test.ts
│ ├── parameter-parser.test.ts
│ ├── paremeter-parser.test.ts
│ ├── scripting
│ │ ├── eval-tree-arrow.test.ts
│ │ ├── eval-tree-pre-post.test.ts
│ │ ├── eval-tree.test.ts
│ │ ├── function-proxy.test.ts
│ │ ├── lexer-literals.test.ts
│ │ ├── lexer-misc.test.ts
│ │ ├── module-parse.test.ts
│ │ ├── parser-arrow.test.ts
│ │ ├── parser-assignments.test.ts
│ │ ├── parser-binary.test.ts
│ │ ├── parser-destructuring.test.ts
│ │ ├── parser-errors.test.ts
│ │ ├── parser-expressions.test.ts
│ │ ├── parser-function.test.ts
│ │ ├── parser-literals.test.ts
│ │ ├── parser-primary.test.ts
│ │ ├── parser-regex.test.ts
│ │ ├── parser-statements.test.ts
│ │ ├── parser-unary.test.ts
│ │ ├── process-event.test.ts
│ │ ├── process-implicit-context.test.ts
│ │ ├── process-statement-asgn.test.ts
│ │ ├── process-statement-destruct.test.ts
│ │ ├── process-statement-regs.test.ts
│ │ ├── process-statement-sync.test.ts
│ │ ├── process-statement.test.ts
│ │ ├── process-switch-sync.test.ts
│ │ ├── process-switch.test.ts
│ │ ├── process-try-sync.test.ts
│ │ ├── process-try.test.ts
│ │ ├── simplify-expression.test.ts
│ │ ├── statement-hooks.test.ts
│ │ └── test-helpers.ts
│ ├── style-parser
│ │ ├── generateHvarChain.test.ts
│ │ ├── parseHVar.test.ts
│ │ ├── parser.test.ts
│ │ └── tokens.test.ts
│ └── xmlui
│ ├── lint.test.ts
│ ├── parser.test.ts
│ ├── scanner.test.ts
│ ├── transform.attr.test.ts
│ ├── transform.circular.test.ts
│ ├── transform.element.test.ts
│ ├── transform.errors.test.ts
│ ├── transform.escape.test.ts
│ ├── transform.regression.test.ts
│ ├── transform.script.test.ts
│ ├── transform.test.ts
│ └── xmlui.ts
├── tests-e2e
│ ├── api-bound-component-regression.spec.ts
│ ├── api-call-as-extracted-component.spec.ts
│ ├── assign-to-object-or-array-regression.spec.ts
│ ├── binding-regression.spec.ts
│ ├── children-as-template-context-vars.spec.ts
│ ├── compound-component.spec.ts
│ ├── context-vars-regression.spec.ts
│ ├── data-bindings.spec.ts
│ ├── datasource-and-api-usage-in-var.spec.ts
│ ├── datasource-direct-binding.spec.ts
│ ├── datasource-onLoaded-regression.spec.ts
│ ├── modify-array-item-regression.spec.ts
│ ├── namespaces.spec.ts
│ ├── push-to-array-regression.spec.ts
│ ├── screen-breakpoints.spec.ts
│ ├── scripting.spec.ts
│ ├── state-scope-in-pages.spec.ts
│ └── state-var-scopes.spec.ts
├── tsconfig.json
├── tsdown.config.ts
├── vite.config.ts
└── vitest.config.ts
```
# Files
--------------------------------------------------------------------------------
/xmlui/tests/parsers/scripting/process-statement-sync.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describe, expect, it, assert } from "vitest";
2 |
3 | import type {
4 | ArrowExpressionStatement,
5 | ExpressionStatement} from "../../../src/components-core/script-runner/ScriptingSourceTree";
6 | import {
7 | T_ARROW_EXPRESSION_STATEMENT,
8 | } from "../../../src/components-core/script-runner/ScriptingSourceTree";
9 | import { processStatementQueue } from "../../../src/components-core/script-runner/process-statement-sync";
10 | import { createEvalContext, parseStatements } from "./test-helpers";
11 | import { buildProxy } from "../../../src/components-core/rendering/buildProxy";
12 |
13 | describe("Process statements (sync)", () => {
14 | it("expression statement #1", () => {
15 | // --- Arrange
16 | const source = "x = 3 * x;";
17 | const evalContext = createEvalContext({
18 | localContext: {
19 | x: 1,
20 | },
21 | });
22 | const statements = parseStatements(source);
23 |
24 | // --- Act
25 | const diag = processStatementQueue(statements, evalContext);
26 |
27 | // --- Assertí
28 | expect(evalContext.mainThread!.blocks!.length).equal(1);
29 | expect(evalContext.localContext.x).equal(3);
30 |
31 | expect(diag.processedStatements).equal(1);
32 | expect(diag.maxLoops).equal(0);
33 | expect(diag.maxBlocks).equal(1);
34 | expect(diag.maxQueueLength).equal(1);
35 | expect(diag.clearToLabels).equal(0);
36 | expect(diag.unshiftedItems).equal(0);
37 | });
38 |
39 | it("Let statement #1", () => {
40 | // --- Arrange
41 | const source = "let y";
42 | const evalContext = createEvalContext({
43 | localContext: {
44 | x: 0,
45 | },
46 | });
47 | const statements = parseStatements(source);
48 |
49 | // --- Act
50 | const diag = processStatementQueue(statements, evalContext);
51 |
52 | // --- Assert
53 | const thread = evalContext.mainThread!;
54 | expect(thread.blocks!.length).equal(1);
55 | expect("y" in thread.blocks![0].vars).equal(true);
56 | expect(thread.blocks![0].constVars).equal(undefined);
57 |
58 | expect(diag.processedStatements).equal(1);
59 | expect(diag.maxLoops).equal(0);
60 | expect(diag.maxBlocks).equal(1);
61 | expect(diag.maxQueueLength).equal(1);
62 | expect(diag.clearToLabels).equal(0);
63 | expect(diag.unshiftedItems).equal(0);
64 | });
65 |
66 | it("Let statement #2", () => {
67 | // --- Arrange
68 | const source = "let y = 3";
69 | const evalContext = createEvalContext({
70 | localContext: {
71 | x: 0,
72 | },
73 | });
74 | const statements = parseStatements(source);
75 |
76 | // --- Act
77 | const diag = processStatementQueue(statements, evalContext);
78 |
79 | // --- Assert
80 | const thread = evalContext.mainThread!;
81 | expect(thread.blocks!.length).equal(1);
82 | expect(thread.blocks![0].vars.y).equal(3);
83 | expect(thread.blocks![0].constVars).equal(undefined);
84 |
85 | expect(diag.processedStatements).equal(1);
86 | expect(diag.maxLoops).equal(0);
87 | expect(diag.maxBlocks).equal(1);
88 | expect(diag.maxQueueLength).equal(1);
89 | expect(diag.clearToLabels).equal(0);
90 | expect(diag.unshiftedItems).equal(0);
91 | });
92 |
93 | it("Let statement #3", () => {
94 | // --- Arrange
95 | const source = "let y = 3, z = 2";
96 | const evalContext = createEvalContext({
97 | localContext: {},
98 | });
99 | const statements = parseStatements(source);
100 |
101 | // --- Act
102 | const diag = processStatementQueue(statements, evalContext);
103 |
104 | // --- Assert
105 | const thread = evalContext.mainThread!;
106 | expect(thread.blocks!.length).equal(1);
107 | expect(thread.blocks![0].vars.y).equal(3);
108 | expect(thread.blocks![0].vars.z).equal(2);
109 | expect(thread.blocks![0].constVars).equal(undefined);
110 |
111 | expect(diag.processedStatements).equal(1);
112 | expect(diag.maxLoops).equal(0);
113 | expect(diag.maxBlocks).equal(1);
114 | expect(diag.maxQueueLength).equal(1);
115 | expect(diag.clearToLabels).equal(0);
116 | expect(diag.unshiftedItems).equal(0);
117 | });
118 |
119 | it("Const statement #2", () => {
120 | // --- Arrange
121 | const source = "const y = 3";
122 | const evalContext = createEvalContext({
123 | localContext: {
124 | x: 0,
125 | },
126 | });
127 | const statements = parseStatements(source);
128 |
129 | // --- Act
130 | const diag = processStatementQueue(statements, evalContext);
131 |
132 | // --- Assert
133 | const thread = evalContext.mainThread!;
134 | expect(thread.blocks!.length).equal(1);
135 | expect(thread.blocks![0].vars.y).equal(3);
136 | expect(thread.blocks![0].constVars!.has("y")).equal(true);
137 |
138 | expect(diag.processedStatements).equal(1);
139 | expect(diag.maxLoops).equal(0);
140 | expect(diag.maxBlocks).equal(1);
141 | expect(diag.maxQueueLength).equal(1);
142 | expect(diag.clearToLabels).equal(0);
143 | expect(diag.unshiftedItems).equal(0);
144 | });
145 |
146 | it("Const write #1", () => {
147 | // --- Arrange
148 | const source = "const y = 3; y++";
149 | const evalContext = createEvalContext({
150 | localContext: {
151 | x: 0,
152 | },
153 | });
154 | const statements = parseStatements(source);
155 |
156 | // --- Act
157 | try {
158 | processStatementQueue(statements, evalContext);
159 | } catch (err) {
160 | return;
161 | }
162 | assert.fail("Exception expected");
163 | });
164 |
165 | it("Const write #2", () => {
166 | // --- Arrange
167 | const source = "const y = 3; y = 12";
168 | const evalContext = createEvalContext({
169 | localContext: {
170 | x: 0,
171 | },
172 | });
173 | const statements = parseStatements(source);
174 |
175 | // --- Act
176 | try {
177 | processStatementQueue(statements, evalContext);
178 | } catch (err) {
179 | return;
180 | }
181 | assert.fail("Exception expected");
182 | });
183 |
184 | it("Implicit block #1", () => {
185 | // --- Arrange
186 | const source = "let y = 3; x = 3 * y;";
187 | const evalContext = createEvalContext({
188 | localContext: {
189 | x: 0,
190 | },
191 | });
192 | const statements = parseStatements(source);
193 |
194 | // --- Act
195 | const diag = processStatementQueue(statements, evalContext);
196 |
197 | // --- Assert
198 | const thread = evalContext.mainThread!;
199 | expect(thread.blocks!.length).equal(1);
200 | expect(thread.blocks![0].vars.y).equal(3);
201 | expect(evalContext.localContext.x).equal(9);
202 |
203 | expect(diag.processedStatements).equal(2);
204 | expect(diag.maxLoops).equal(0);
205 | expect(diag.maxBlocks).equal(1);
206 | expect(diag.maxQueueLength).equal(2);
207 | expect(diag.clearToLabels).equal(0);
208 | expect(diag.unshiftedItems).equal(0);
209 | });
210 |
211 | it("Implicit block #2", () => {
212 | // --- Arrange
213 | const source = "let y = 3; { let z = 2 ; x = 3 * y + z; }";
214 | const evalContext = createEvalContext({
215 | localContext: {
216 | x: 0,
217 | },
218 | });
219 | const statements = parseStatements(source);
220 |
221 | // --- Act
222 | const diag = processStatementQueue(statements, evalContext);
223 |
224 | // --- Assert
225 | const thread = evalContext.mainThread!;
226 | expect(thread.blocks!.length).equal(1);
227 | expect(thread.blocks![0].vars.y).equal(3);
228 | expect(evalContext.localContext.x).equal(11);
229 |
230 | expect(diag.processedStatements).equal(5);
231 | expect(diag.maxLoops).equal(0);
232 | expect(diag.maxBlocks).equal(2);
233 | expect(diag.maxQueueLength).equal(3);
234 | expect(diag.clearToLabels).equal(0);
235 | expect(diag.unshiftedItems).equal(3);
236 | });
237 |
238 | it("Block statement #1", () => {
239 | // --- Arrange
240 | const source = "{ let y = 3; x = 3 * y; }";
241 | const evalContext = createEvalContext({
242 | localContext: {
243 | x: 0,
244 | },
245 | });
246 | const statements = parseStatements(source);
247 |
248 | // --- Act
249 | const diag = processStatementQueue(statements, evalContext);
250 |
251 | // --- Assert
252 | expect(evalContext.mainThread!.blocks!.length).equal(1);
253 | expect(evalContext.localContext.x).equal(9);
254 |
255 | expect(diag.processedStatements).equal(4);
256 | expect(diag.maxLoops).equal(0);
257 | expect(diag.maxBlocks).equal(2);
258 | expect(diag.maxQueueLength).equal(3);
259 | expect(diag.clearToLabels).equal(0);
260 | expect(diag.unshiftedItems).equal(3);
261 | });
262 |
263 | it("Block statement #2", () => {
264 | // --- Arrange
265 | const source = "{ let y = 3; { let z = 2 ; x = 3 * y + z; } }";
266 | const evalContext = createEvalContext({
267 | localContext: {
268 | x: 0,
269 | },
270 | });
271 | const statements = parseStatements(source);
272 |
273 | // --- Act
274 | const diag = processStatementQueue(statements, evalContext);
275 |
276 | // --- Assert
277 | expect(evalContext.mainThread!.blocks!.length).equal(1);
278 | expect(evalContext.localContext.x).equal(11);
279 |
280 | expect(diag.processedStatements).equal(7);
281 | expect(diag.maxLoops).equal(0);
282 | expect(diag.maxBlocks).equal(3);
283 | expect(diag.maxQueueLength).equal(4);
284 | expect(diag.clearToLabels).equal(0);
285 | expect(diag.unshiftedItems).equal(6);
286 | });
287 |
288 | it("Block statement #3", () => {
289 | // --- Arrange
290 | const source = "{ let y = 3; { let z = 2 ; { x = 3 * y + z; } } }";
291 | const evalContext = createEvalContext({
292 | localContext: {
293 | x: 0,
294 | },
295 | });
296 | const statements = parseStatements(source);
297 |
298 | // --- Act
299 | const diag = processStatementQueue(statements, evalContext);
300 |
301 | // --- Assert
302 | expect(evalContext.mainThread!.blocks!.length).equal(1);
303 | expect(evalContext.localContext.x).equal(11);
304 |
305 | expect(diag.processedStatements).equal(9);
306 | expect(diag.maxLoops).equal(0);
307 | expect(diag.maxBlocks).equal(4);
308 | expect(diag.maxQueueLength).equal(4);
309 | expect(diag.clearToLabels).equal(0);
310 | expect(diag.unshiftedItems).equal(8);
311 | });
312 |
313 | it("Block statement #4", () => {
314 | // --- Arrange
315 | const source = "{ let y = 3; { let z = 2 ; { let z = 3; x = 3 * y + z; } } }";
316 | const evalContext = createEvalContext({
317 | localContext: {
318 | x: 0,
319 | },
320 | });
321 | const statements = parseStatements(source);
322 |
323 | // --- Act
324 | const diag = processStatementQueue(statements, evalContext);
325 |
326 | // --- Assert
327 | expect(evalContext.mainThread!.blocks!.length).equal(1);
328 | expect(evalContext.localContext.x).equal(12);
329 |
330 | expect(diag.processedStatements).equal(10);
331 | expect(diag.maxLoops).equal(0);
332 | expect(diag.maxBlocks).equal(4);
333 | expect(diag.maxQueueLength).equal(5);
334 | expect(diag.clearToLabels).equal(0);
335 | expect(diag.unshiftedItems).equal(9);
336 | });
337 |
338 | it("If statement #1", () => {
339 | // --- Arrange
340 | const source = "if (x === 0) x = 3";
341 | const evalContext = createEvalContext({
342 | localContext: {
343 | x: 0,
344 | },
345 | });
346 | const statements = parseStatements(source);
347 |
348 | // --- Act
349 | const diag = processStatementQueue(statements, evalContext);
350 |
351 | // --- Assert
352 | expect(evalContext.mainThread!.blocks!.length).equal(1);
353 | expect(evalContext.localContext.x).equal(3);
354 |
355 | expect(diag.processedStatements).equal(2);
356 | expect(diag.maxLoops).equal(0);
357 | expect(diag.maxBlocks).equal(1);
358 | expect(diag.maxQueueLength).equal(1);
359 | expect(diag.clearToLabels).equal(0);
360 | expect(diag.unshiftedItems).equal(1);
361 | });
362 |
363 | it("If statement #2", () => {
364 | // --- Arrange
365 | const source = "if (x === 0) {x = 3}";
366 | const evalContext = createEvalContext({
367 | localContext: {
368 | x: 0,
369 | },
370 | });
371 | const statements = parseStatements(source);
372 |
373 | // --- Act
374 | const diag = processStatementQueue(statements, evalContext);
375 |
376 | // --- Assert
377 | expect(evalContext.mainThread!.blocks!.length).equal(1);
378 | expect(evalContext.localContext.x).equal(3);
379 |
380 | expect(diag.processedStatements).equal(4);
381 | expect(diag.maxLoops).equal(0);
382 | expect(diag.maxBlocks).equal(2);
383 | expect(diag.maxQueueLength).equal(2);
384 | expect(diag.clearToLabels).equal(0);
385 | expect(diag.unshiftedItems).equal(3);
386 | });
387 |
388 | it("If statement #3", () => {
389 | // --- Arrange
390 | const source = "if (x === 0) x = 3; else x = 2";
391 | const evalContext = createEvalContext({
392 | localContext: {
393 | x: 1,
394 | },
395 | });
396 | const statements = parseStatements(source);
397 |
398 | // --- Act
399 | const diag = processStatementQueue(statements, evalContext);
400 |
401 | // --- Assert
402 | expect(evalContext.mainThread!.blocks!.length).equal(1);
403 | expect(evalContext.localContext.x).equal(2);
404 |
405 | expect(diag.processedStatements).equal(2);
406 | expect(diag.maxLoops).equal(0);
407 | expect(diag.maxBlocks).equal(1);
408 | expect(diag.maxQueueLength).equal(1);
409 | expect(diag.clearToLabels).equal(0);
410 | expect(diag.unshiftedItems).equal(1);
411 | });
412 |
413 | it("If statement #4", () => {
414 | // --- Arrange
415 | const source = "if (x === 0) x = 3; else { x = 2 }";
416 | const evalContext = createEvalContext({
417 | localContext: {
418 | x: 1,
419 | },
420 | });
421 | const statements = parseStatements(source);
422 |
423 | // --- Act
424 | const diag = processStatementQueue(statements, evalContext);
425 |
426 | // --- Assert
427 | expect(evalContext.mainThread!.blocks!.length).equal(1);
428 | expect(evalContext.localContext.x).equal(2);
429 |
430 | expect(diag.processedStatements).equal(4);
431 | expect(diag.maxLoops).equal(0);
432 | expect(diag.maxBlocks).equal(2);
433 | expect(diag.maxQueueLength).equal(2);
434 | expect(diag.clearToLabels).equal(0);
435 | expect(diag.unshiftedItems).equal(3);
436 | });
437 |
438 | it("If statement #5", () => {
439 | // --- Arrange
440 | const source = "if (x === 0) {x = 3;} else { x = 2 }";
441 | const evalContext = createEvalContext({
442 | localContext: {
443 | x: 0,
444 | },
445 | });
446 | const statements = parseStatements(source);
447 |
448 | // --- Act
449 | const diag = processStatementQueue(statements, evalContext);
450 |
451 | // --- Assert
452 | expect(evalContext.mainThread!.blocks!.length).equal(1);
453 | expect(evalContext.localContext.x).equal(3);
454 |
455 | expect(diag.processedStatements).equal(4);
456 | expect(diag.maxLoops).equal(0);
457 | expect(diag.maxBlocks).equal(2);
458 | expect(diag.maxQueueLength).equal(2);
459 | expect(diag.clearToLabels).equal(0);
460 | expect(diag.unshiftedItems).equal(3);
461 | });
462 |
463 | it("If statement #6", () => {
464 | // --- Arrange
465 | const source = "if (x === 0) {x = 3;} else { x = 2 }";
466 | const evalContext = createEvalContext({
467 | localContext: {
468 | x: 1,
469 | },
470 | });
471 | const statements = parseStatements(source);
472 |
473 | // --- Act
474 | const diag = processStatementQueue(statements, evalContext);
475 |
476 | // --- Assert
477 | expect(evalContext.mainThread!.blocks!.length).equal(1);
478 | expect(evalContext.localContext.x).equal(2);
479 |
480 | expect(diag.processedStatements).equal(4);
481 | expect(diag.maxLoops).equal(0);
482 | expect(diag.maxBlocks).equal(2);
483 | expect(diag.maxQueueLength).equal(2);
484 | expect(diag.clearToLabels).equal(0);
485 | expect(diag.unshiftedItems).equal(3);
486 | });
487 |
488 | it("while statement #1", () => {
489 | // --- Arrange
490 | const source = "while (x < 3) x++;";
491 | const evalContext = createEvalContext({
492 | localContext: {
493 | x: 0,
494 | },
495 | });
496 | const statements = parseStatements(source);
497 |
498 | // --- Act
499 | const diag = processStatementQueue(statements, evalContext);
500 |
501 | // --- Assert
502 | expect(evalContext.mainThread!.blocks!.length).equal(1);
503 | expect(evalContext.localContext.x).equal(3);
504 |
505 | expect(diag.processedStatements).equal(7);
506 | expect(diag.maxLoops).equal(1);
507 | expect(diag.maxBlocks).equal(1);
508 | expect(diag.maxQueueLength).equal(2);
509 | expect(diag.clearToLabels).equal(0);
510 | expect(diag.unshiftedItems).equal(6);
511 | });
512 |
513 | it("while statement #2", () => {
514 | // --- Arrange
515 | const source = "let x = 0; while (x < 3) x++;";
516 | const evalContext = createEvalContext({
517 | localContext: {},
518 | });
519 | const statements = parseStatements(source);
520 |
521 | // --- Act
522 | const diag = processStatementQueue(statements, evalContext);
523 |
524 | // --- Assert
525 | const thread = evalContext.mainThread!;
526 | expect(thread.blocks!.length).equal(1);
527 | expect(thread.blocks![0].vars.x).equal(3);
528 |
529 | expect(diag.processedStatements).equal(8);
530 | expect(diag.maxLoops).equal(1);
531 | expect(diag.maxBlocks).equal(1);
532 | expect(diag.maxQueueLength).equal(2);
533 | expect(diag.clearToLabels).equal(0);
534 | expect(diag.unshiftedItems).equal(6);
535 | });
536 |
537 | it("while statement #3", () => {
538 | // --- Arrange
539 | const source = "let x = 0; while (x < 8) {let y = 2; x += y;}";
540 | const evalContext = createEvalContext({
541 | localContext: {},
542 | });
543 | const statements = parseStatements(source);
544 |
545 | // --- Act
546 | const diag = processStatementQueue(statements, evalContext);
547 |
548 | // --- Assert
549 | const thread = evalContext.mainThread!;
550 | expect(thread.blocks!.length).equal(1);
551 | expect(thread.blocks![0].vars.x).equal(8);
552 |
553 | expect(diag.processedStatements).equal(22);
554 | expect(diag.maxLoops).equal(1);
555 | expect(diag.maxBlocks).equal(2);
556 | expect(diag.maxQueueLength).equal(4);
557 | expect(diag.clearToLabels).equal(0);
558 | expect(diag.unshiftedItems).equal(20);
559 | });
560 |
561 | it("while statement #4", () => {
562 | // --- Arrange
563 | const source = "let x = 0; while (x < 18) {let y = 0; while (y < 3) {x += y; y++;} }";
564 | const evalContext = createEvalContext({
565 | localContext: {},
566 | });
567 | const statements = parseStatements(source);
568 |
569 | // --- Act
570 | const diag = processStatementQueue(statements, evalContext);
571 |
572 | // --- Assert
573 | const thread = evalContext.mainThread!;
574 | expect(thread.blocks!.length).equal(1);
575 | expect(thread.blocks![0].vars.x).equal(18);
576 |
577 | expect(diag.processedStatements).equal(122);
578 | expect(diag.maxLoops).equal(2);
579 | expect(diag.maxBlocks).equal(3);
580 | expect(diag.maxQueueLength).equal(6);
581 | expect(diag.clearToLabels).equal(0);
582 | expect(diag.unshiftedItems).equal(120);
583 | });
584 |
585 | it("while with break #1", () => {
586 | // --- Arrange
587 | const source = "let x = 0; while (true) {x++ ; if (x > 3) break;}";
588 | const evalContext = createEvalContext({
589 | localContext: {},
590 | });
591 | const statements = parseStatements(source);
592 |
593 | // --- Act
594 | const diag = processStatementQueue(statements, evalContext);
595 |
596 | // --- Assert
597 | const thread = evalContext.mainThread!;
598 | expect(thread.blocks!.length).equal(1);
599 | expect(thread.blocks![0].vars.x).equal(4);
600 |
601 | expect(diag.processedStatements).equal(21);
602 | expect(diag.maxLoops).equal(1);
603 | expect(diag.maxBlocks).equal(2);
604 | expect(diag.maxQueueLength).equal(4);
605 | expect(diag.clearToLabels).equal(1);
606 | expect(diag.unshiftedItems).equal(21);
607 | });
608 |
609 | it("while with break #2", () => {
610 | // --- Arrange
611 | const source = "let x = 0; while (true) {x++ ; if (x > 3) break;}; x++";
612 | const evalContext = createEvalContext({
613 | localContext: {},
614 | });
615 | const statements = parseStatements(source);
616 |
617 | // --- Act
618 | const diag = processStatementQueue(statements, evalContext);
619 |
620 | // --- Assert
621 | const thread = evalContext.mainThread!;
622 | expect(thread.blocks!.length).equal(1);
623 | expect(thread.blocks![0].vars.x).equal(5);
624 |
625 | expect(diag.processedStatements).equal(22);
626 | expect(diag.maxLoops).equal(1);
627 | expect(diag.maxBlocks).equal(2);
628 | expect(diag.maxQueueLength).equal(5);
629 | expect(diag.clearToLabels).equal(1);
630 | expect(diag.unshiftedItems).equal(21);
631 | });
632 |
633 | it("while with continue #1", () => {
634 | // --- Arrange
635 | const source = "let y = 0; let x = 0; while (x < 6) {x++; if (x == 3) continue; y += x; }";
636 | const evalContext = createEvalContext({
637 | localContext: {},
638 | });
639 | const statements = parseStatements(source);
640 |
641 | // --- Act
642 | const diag = processStatementQueue(statements, evalContext);
643 |
644 | // --- Assert
645 | const thread = evalContext.mainThread!;
646 | expect(thread.blocks!.length).equal(1);
647 | expect(thread.blocks![0].vars.y).equal(18);
648 |
649 | expect(diag.processedStatements).equal(38);
650 | expect(diag.maxLoops).equal(1);
651 | expect(diag.maxBlocks).equal(2);
652 | expect(diag.maxQueueLength).equal(5);
653 | expect(diag.clearToLabels).equal(1);
654 | expect(diag.unshiftedItems).equal(37);
655 | });
656 |
657 | it("do-while statement #1", () => {
658 | // --- Arrange
659 | const source = "do x++; while (x < 3)";
660 | const evalContext = createEvalContext({
661 | localContext: {
662 | x: 0,
663 | },
664 | });
665 | const statements = parseStatements(source);
666 |
667 | // --- Act
668 | const diag = processStatementQueue(statements, evalContext);
669 |
670 | // --- Assert
671 | expect(evalContext.mainThread!.blocks!.length).equal(1);
672 | expect(evalContext.localContext.x).equal(3);
673 |
674 | expect(diag.processedStatements).equal(7);
675 | expect(diag.maxLoops).equal(1);
676 | expect(diag.maxBlocks).equal(1);
677 | expect(diag.maxQueueLength).equal(2);
678 | expect(diag.clearToLabels).equal(0);
679 | expect(diag.unshiftedItems).equal(6);
680 | });
681 |
682 | it("do-while statement #2", () => {
683 | // --- Arrange
684 | const source = "do x++; while (x < 0)";
685 | const evalContext = createEvalContext({
686 | localContext: {
687 | x: 0,
688 | },
689 | });
690 | const statements = parseStatements(source);
691 |
692 | // --- Act
693 | const diag = processStatementQueue(statements, evalContext);
694 |
695 | // --- Assert
696 | expect(evalContext.mainThread!.blocks!.length).equal(1);
697 | expect(evalContext.localContext.x).equal(1);
698 |
699 | expect(diag.processedStatements).equal(3);
700 | expect(diag.maxLoops).equal(1);
701 | expect(diag.maxBlocks).equal(1);
702 | expect(diag.maxQueueLength).equal(2);
703 | expect(diag.clearToLabels).equal(0);
704 | expect(diag.unshiftedItems).equal(2);
705 | });
706 |
707 | it("do-while statement #3", () => {
708 | // --- Arrange
709 | const source = "do { x++;} while (x < 3)";
710 | const evalContext = createEvalContext({
711 | localContext: {
712 | x: 0,
713 | },
714 | });
715 | const statements = parseStatements(source);
716 |
717 | // --- Act
718 | const diag = processStatementQueue(statements, evalContext);
719 |
720 | // --- Assert
721 | expect(evalContext.mainThread!.blocks!.length).equal(1);
722 | expect(evalContext.localContext.x).equal(3);
723 |
724 | expect(diag.processedStatements).equal(13);
725 | expect(diag.maxLoops).equal(1);
726 | expect(diag.maxBlocks).equal(2);
727 | expect(diag.maxQueueLength).equal(3);
728 | expect(diag.clearToLabels).equal(0);
729 | expect(diag.unshiftedItems).equal(12);
730 | });
731 |
732 | it("do-while statement #4", () => {
733 | // --- Arrange
734 | const source = "let x = 0; do {let y = 2; x += y;} while (x < 8) ";
735 | const evalContext = createEvalContext({
736 | localContext: {},
737 | });
738 | const statements = parseStatements(source);
739 |
740 | // --- Act
741 | const diag = processStatementQueue(statements, evalContext);
742 |
743 | // --- Assert
744 | const thread = evalContext.mainThread!;
745 | expect(thread.blocks!.length).equal(1);
746 | expect(thread.blocks![0].vars.x).equal(8);
747 |
748 | expect(diag.processedStatements).equal(22);
749 | expect(diag.maxLoops).equal(1);
750 | expect(diag.maxBlocks).equal(2);
751 | expect(diag.maxQueueLength).equal(4);
752 | expect(diag.clearToLabels).equal(0);
753 | expect(diag.unshiftedItems).equal(20);
754 | });
755 |
756 | it("do-while statement #5", () => {
757 | // --- Arrange
758 | const source = "let x = 0; do {let y = 0; while (y < 3) {x += y; y++;} } while (x < 18)";
759 | const evalContext = createEvalContext({
760 | localContext: {},
761 | });
762 | const statements = parseStatements(source);
763 |
764 | // --- Act
765 | const diag = processStatementQueue(statements, evalContext);
766 |
767 | // --- Assert
768 | const thread = evalContext.mainThread!;
769 | expect(thread.blocks!.length).equal(1);
770 | expect(thread.blocks![0].vars.x).equal(18);
771 |
772 | expect(diag.processedStatements).equal(122);
773 | expect(diag.maxLoops).equal(2);
774 | expect(diag.maxBlocks).equal(3);
775 | expect(diag.maxQueueLength).equal(6);
776 | expect(diag.clearToLabels).equal(0);
777 | expect(diag.unshiftedItems).equal(120);
778 | });
779 |
780 | it("do-while with break #1", () => {
781 | // --- Arrange
782 | const source = "let x = 0; do {x++ ; if (x > 3) break;} while (true)";
783 | const evalContext = createEvalContext({
784 | localContext: {},
785 | });
786 | const statements = parseStatements(source);
787 |
788 | // --- Act
789 | const diag = processStatementQueue(statements, evalContext);
790 |
791 | // --- Assert
792 | const thread = evalContext.mainThread!;
793 | expect(thread.blocks!.length).equal(1);
794 | expect(thread.blocks![0].vars.x).equal(4);
795 |
796 | expect(diag.processedStatements).equal(21);
797 | expect(diag.maxLoops).equal(1);
798 | expect(diag.maxBlocks).equal(2);
799 | expect(diag.maxQueueLength).equal(4);
800 | expect(diag.clearToLabels).equal(1);
801 | expect(diag.unshiftedItems).equal(21);
802 | });
803 |
804 | it("do-while with continue #1", () => {
805 | // --- Arrange
806 | const source = "let y = 0; let x = 0; do {x++; if (x == 3) continue; y += x; } while (x < 6)";
807 | const evalContext = createEvalContext({
808 | localContext: {},
809 | });
810 | const statements = parseStatements(source);
811 |
812 | // --- Act
813 | const diag = processStatementQueue(statements, evalContext);
814 |
815 | // --- Assert
816 | const thread = evalContext.mainThread!;
817 | expect(thread.blocks!.length).equal(1);
818 | expect(thread.blocks![0].vars.y).equal(18);
819 |
820 | expect(diag.processedStatements).equal(38);
821 | expect(diag.maxLoops).equal(1);
822 | expect(diag.maxBlocks).equal(2);
823 | expect(diag.maxQueueLength).equal(5);
824 | expect(diag.clearToLabels).equal(1);
825 | expect(diag.unshiftedItems).equal(37);
826 | });
827 |
828 | it("for-loop #1", () => {
829 | // --- Arrange
830 | const source = "let y = 0; for (let i = 0; i < 4; i++) y += i;";
831 | const evalContext = createEvalContext({
832 | localContext: {},
833 | });
834 | const statements = parseStatements(source);
835 |
836 | // --- Act
837 | const diag = processStatementQueue(statements, evalContext);
838 |
839 | // --- Assert
840 | const thread = evalContext.mainThread!;
841 | expect(thread.blocks!.length).equal(1);
842 | expect(thread.blocks![0].vars.y).equal(6);
843 |
844 | expect(diag.processedStatements).equal(16);
845 | expect(diag.maxLoops).equal(1);
846 | expect(diag.maxBlocks).equal(2);
847 | expect(diag.maxQueueLength).equal(3);
848 | expect(diag.clearToLabels).equal(0);
849 | expect(diag.unshiftedItems).equal(14);
850 | });
851 |
852 | it("for-loop #2", () => {
853 | // --- Arrange
854 | const source = "let y = 0; for (let i = 0; i < 4; i++) {y += i;}";
855 | const evalContext = createEvalContext({
856 | localContext: {},
857 | });
858 | const statements = parseStatements(source);
859 |
860 | // --- Act
861 | const diag = processStatementQueue(statements, evalContext);
862 |
863 | // --- Assert
864 | const thread = evalContext.mainThread!;
865 | expect(thread.blocks!.length).equal(1);
866 | expect(thread.blocks![0].vars.y).equal(6);
867 |
868 | expect(diag.processedStatements).equal(24);
869 | expect(diag.maxLoops).equal(1);
870 | expect(diag.maxBlocks).equal(3);
871 | expect(diag.maxQueueLength).equal(4);
872 | expect(diag.clearToLabels).equal(0);
873 | expect(diag.unshiftedItems).equal(22);
874 | });
875 |
876 | it("for-loop #3", () => {
877 | // --- Arrange
878 | const source = "let y = 0; for (let i = 0; i < 4; i++) { break; }; y++";
879 | const evalContext = createEvalContext({
880 | localContext: {},
881 | });
882 | const statements = parseStatements(source);
883 |
884 | // --- Act
885 | const diag = processStatementQueue(statements, evalContext);
886 |
887 | // --- Assert
888 | const thread = evalContext.mainThread!;
889 | expect(thread.blocks!.length).equal(1);
890 | expect(thread.blocks![0].vars.y).equal(1);
891 |
892 | expect(diag.processedStatements).equal(7);
893 | expect(diag.maxLoops).equal(1);
894 | expect(diag.maxBlocks).equal(3);
895 | expect(diag.maxQueueLength).equal(5);
896 | expect(diag.clearToLabels).equal(1);
897 | expect(diag.unshiftedItems).equal(7);
898 | });
899 |
900 | it("for-loop #4", () => {
901 | // --- Arrange
902 | const source = "let y = 0; for (let i = 0, j = 0; i < 4; i++, j+=2) {y += i + j}";
903 | const evalContext = createEvalContext({
904 | localContext: {},
905 | });
906 | const statements = parseStatements(source);
907 |
908 | // --- Act
909 | const diag = processStatementQueue(statements, evalContext);
910 |
911 | // --- Assert
912 | const thread = evalContext.mainThread!;
913 | expect(thread.blocks!.length).equal(1);
914 | expect(thread.blocks![0].vars.y).equal(18);
915 |
916 | expect(diag.processedStatements).equal(24);
917 | expect(diag.maxLoops).equal(1);
918 | expect(diag.maxBlocks).equal(3);
919 | expect(diag.maxQueueLength).equal(4);
920 | expect(diag.clearToLabels).equal(0);
921 | expect(diag.unshiftedItems).equal(22);
922 | });
923 |
924 | it("for-loop #5", () => {
925 | // --- Arrange
926 | const source = "let y = 0; let i = 0; for (; i < 4; i++) {y += i}";
927 | const evalContext = createEvalContext({
928 | localContext: {},
929 | });
930 | const statements = parseStatements(source);
931 |
932 | // --- Act
933 | const diag = processStatementQueue(statements, evalContext);
934 |
935 | // --- Assert
936 | const thread = evalContext.mainThread!;
937 | expect(thread.blocks!.length).equal(1);
938 | expect(thread.blocks![0].vars.y).equal(6);
939 |
940 | expect(diag.processedStatements).equal(24);
941 | expect(diag.maxLoops).equal(1);
942 | expect(diag.maxBlocks).equal(3);
943 | expect(diag.maxQueueLength).equal(4);
944 | expect(diag.clearToLabels).equal(0);
945 | expect(diag.unshiftedItems).equal(21);
946 | });
947 |
948 | it("for-loop with continue", () => {
949 | // --- Arrange
950 | const source = "let y = 0; for (let i = 0; i < 10; i++) {if (i % 3 === 0) continue; y += i; }";
951 | const evalContext = createEvalContext({
952 | localContext: {},
953 | });
954 | const statements = parseStatements(source);
955 |
956 | // --- Act
957 | const diag = processStatementQueue(statements, evalContext);
958 |
959 | // --- Assert
960 | const thread = evalContext.mainThread!;
961 | expect(thread.blocks!.length).equal(1);
962 | expect(thread.blocks![0].vars.y).equal(27);
963 |
964 | expect(diag.processedStatements).equal(60);
965 | expect(diag.maxLoops).equal(1);
966 | expect(diag.maxBlocks).equal(3);
967 | expect(diag.maxQueueLength).equal(5);
968 | expect(diag.clearToLabels).equal(4);
969 | expect(diag.unshiftedItems).equal(66);
970 | });
971 |
972 | it("Arrow function body #1", () => {
973 | // --- Arrange
974 | const source = "(() => {return 2})()";
975 | const evalContext = createEvalContext({
976 | localContext: {},
977 | });
978 | const statements = parseStatements(source);
979 |
980 | // --- Act
981 | const diag = processStatementQueue(statements, evalContext);
982 |
983 | // --- Assert
984 | const thread = evalContext.mainThread!;
985 | expect(thread.blocks!.length).equal(1);
986 | expect(thread.blocks![0].returnValue).equal(2);
987 |
988 | expect(diag.processedStatements).equal(1);
989 | expect(diag.maxLoops).equal(0);
990 | expect(diag.maxBlocks).equal(1);
991 | expect(diag.maxQueueLength).equal(1);
992 | expect(diag.clearToLabels).equal(0);
993 | expect(diag.unshiftedItems).equal(0);
994 | });
995 |
996 | it("Arrow function body #2", () => {
997 | // --- Arrange
998 | const source = "let arr = () => {return 2}; let x = arr();";
999 | const evalContext = createEvalContext({
1000 | localContext: {},
1001 | });
1002 | const statements = parseStatements(source);
1003 |
1004 | // --- Act
1005 | const diag = processStatementQueue(statements, evalContext);
1006 |
1007 | // --- Assert
1008 | const thread = evalContext.mainThread!;
1009 | expect(thread.blocks!.length).equal(1);
1010 | expect(thread.blocks![0].vars.x).equal(2);
1011 |
1012 | expect(diag.processedStatements).equal(2);
1013 | expect(diag.maxLoops).equal(0);
1014 | expect(diag.maxBlocks).equal(1);
1015 | expect(diag.maxQueueLength).equal(2);
1016 | expect(diag.clearToLabels).equal(0);
1017 | expect(diag.unshiftedItems).equal(0);
1018 | });
1019 |
1020 | it("Arrow function body #3", () => {
1021 | // --- Arrange
1022 | const source =
1023 | "let arr = (x, y) => { let sum = 0; for (let i = x; i <= y; i++) sum+= i; return sum }; arr(1, 5);";
1024 | const evalContext = createEvalContext({
1025 | localContext: {},
1026 | });
1027 | const statements = parseStatements(source);
1028 |
1029 | // --- Act
1030 | const diag = processStatementQueue(statements, evalContext);
1031 |
1032 | // --- Assert
1033 | const thread = evalContext.mainThread!;
1034 | expect(thread.blocks!.length).equal(1);
1035 | expect(thread.blocks![0].returnValue).equal(15);
1036 |
1037 | expect(diag.processedStatements).equal(2);
1038 | expect(diag.maxLoops).equal(0);
1039 | expect(diag.maxBlocks).equal(1);
1040 | expect(diag.maxQueueLength).equal(2);
1041 | expect(diag.clearToLabels).equal(0);
1042 | expect(diag.unshiftedItems).equal(0);
1043 | });
1044 |
1045 | it("Arrow function body #4", () => {
1046 | // --- Arrange
1047 | const source =
1048 | "let arr = (x, y) => { let sum = 0; for (let i = x; i <= y; i++) sum+= i; return sum }; z = arr(1, 5);";
1049 | const evalContext = createEvalContext({
1050 | localContext: {
1051 | z: 0,
1052 | },
1053 | });
1054 | const statements = parseStatements(source);
1055 |
1056 | // --- Act
1057 | const diag = processStatementQueue(statements, evalContext);
1058 |
1059 | // --- Assert
1060 | const thread = evalContext.mainThread!;
1061 | expect(thread.blocks!.length).equal(1);
1062 | expect(evalContext.localContext.z).equal(15);
1063 | expect(thread.blocks![0].returnValue).equal(15);
1064 |
1065 | expect(diag.processedStatements).equal(2);
1066 | expect(diag.maxLoops).equal(0);
1067 | expect(diag.maxBlocks).equal(1);
1068 | expect(diag.maxQueueLength).equal(2);
1069 | expect(diag.clearToLabels).equal(0);
1070 | expect(diag.unshiftedItems).equal(0);
1071 | });
1072 |
1073 | it("return #1", () => {
1074 | // --- Arrange
1075 | const source = "return 123";
1076 | const evalContext = createEvalContext({});
1077 | const statements = parseStatements(source);
1078 |
1079 | // --- Act
1080 | const diag = processStatementQueue(statements, evalContext);
1081 |
1082 | // --- Assert
1083 | const thread = evalContext.mainThread!;
1084 | expect(thread.blocks!.length).equal(1);
1085 | expect(thread.returnValue).equal(123);
1086 |
1087 | expect(diag.processedStatements).equal(1);
1088 | expect(diag.maxLoops).equal(0);
1089 | expect(diag.maxBlocks).equal(1);
1090 | expect(diag.maxQueueLength).equal(1);
1091 | expect(diag.clearToLabels).equal(1);
1092 | expect(diag.unshiftedItems).equal(0);
1093 | });
1094 |
1095 | it("return #2", () => {
1096 | // --- Arrange
1097 | const source = "x = 1; return 123; x = 2";
1098 | const evalContext = createEvalContext({
1099 | localContext: {
1100 | x: 0,
1101 | },
1102 | });
1103 | const statements = parseStatements(source);
1104 |
1105 | // --- Act
1106 | const diag = processStatementQueue(statements, evalContext);
1107 |
1108 | // --- Assert
1109 | const thread = evalContext.mainThread!;
1110 | expect(thread.blocks!.length).equal(1);
1111 | expect(evalContext.localContext.x).equal(1);
1112 | expect(thread.returnValue).equal(123);
1113 |
1114 | expect(diag.processedStatements).equal(2);
1115 | expect(diag.maxLoops).equal(0);
1116 | expect(diag.maxBlocks).equal(1);
1117 | expect(diag.maxQueueLength).equal(3);
1118 | expect(diag.clearToLabels).equal(1);
1119 | expect(diag.unshiftedItems).equal(0);
1120 | });
1121 |
1122 | it("return #3", () => {
1123 | // --- Arrange
1124 | const source = "return";
1125 | const evalContext = createEvalContext({});
1126 | const statements = parseStatements(source);
1127 |
1128 | // --- Act
1129 | const diag = processStatementQueue(statements, evalContext);
1130 |
1131 | // --- Assert
1132 | const thread = evalContext.mainThread!;
1133 | expect(thread.blocks!.length).equal(1);
1134 | expect(thread.returnValue).equal(undefined);
1135 |
1136 | expect(diag.processedStatements).equal(1);
1137 | expect(diag.maxLoops).equal(0);
1138 | expect(diag.maxBlocks).equal(1);
1139 | expect(diag.maxQueueLength).equal(1);
1140 | expect(diag.clearToLabels).equal(1);
1141 | expect(diag.unshiftedItems).equal(0);
1142 | });
1143 |
1144 | it("Body with timeout", () => {
1145 | // --- Arrange
1146 | const source = "while (true);";
1147 | const evalContext = createEvalContext({
1148 | localContext: {},
1149 | });
1150 | const statements = parseStatements(source);
1151 |
1152 | // --- Act
1153 | try {
1154 | processStatementQueue(statements, evalContext);
1155 | } catch (err: any) {
1156 | // eslint-disable-next-line jest/no-conditional-expect
1157 | expect(err.toString()).contains("timeout");
1158 | return;
1159 | }
1160 | assert.fail("Exception expected");
1161 | });
1162 |
1163 | it("ArrowS", () => {
1164 | // --- Arrange
1165 | const source = "(arg)=> { return arg + 2 }";
1166 | const evalContext = createEvalContext({
1167 | localContext: {},
1168 | eventArgs: [4],
1169 | });
1170 |
1171 | const statements = parseStatements(source);
1172 | const arrowStmt = {
1173 | type: T_ARROW_EXPRESSION_STATEMENT,
1174 | expr: (statements[0] as ExpressionStatement).expr,
1175 | } as ArrowExpressionStatement;
1176 |
1177 | // --- Act
1178 | processStatementQueue([arrowStmt], evalContext);
1179 | const thread = evalContext.mainThread!;
1180 |
1181 | expect(thread.blocks![0].returnValue).equal(6);
1182 | });
1183 |
1184 | it("Read-only write #1", () => {
1185 | // --- Arrange
1186 | const source = "$x = 3";
1187 | const evalContext = createEvalContext({
1188 | localContext: getComponentStateClone({
1189 | $x: 0,
1190 | }),
1191 | // syncUpdateWithExternalStore: checkReadOnlyOnUpdate,
1192 | // isReadOnlyVar: isReadOnlyField
1193 | });
1194 | const statements = parseStatements(source);
1195 |
1196 | // --- Act
1197 | try {
1198 | processStatementQueue(statements, evalContext);
1199 | } catch (err: any) {
1200 | expect(err.toString().includes("read-only")).equal(true);
1201 | return;
1202 | }
1203 | assert.fail("Exception expected");
1204 | });
1205 |
1206 | it("Read-only write #2", () => {
1207 | // --- Arrange
1208 | const source = "$x.a[0].y = 3";
1209 | const evalContext = createEvalContext({
1210 | localContext: getComponentStateClone({
1211 | $x: {
1212 | a: [
1213 | {
1214 | y: 0,
1215 | },
1216 | ],
1217 | },
1218 | }),
1219 | });
1220 | const statements = parseStatements(source);
1221 |
1222 | // --- Act
1223 | try {
1224 | processStatementQueue(statements, evalContext);
1225 | } catch (err: any) {
1226 | expect(err.toString().includes("read-only")).equal(true);
1227 | return;
1228 | }
1229 | assert.fail("Exception expected");
1230 | });
1231 |
1232 | it("Read-only write #3", () => {
1233 | // --- Arrange
1234 | const source = "$x++";
1235 | const evalContext = createEvalContext({
1236 | localContext: getComponentStateClone({
1237 | $x: 0,
1238 | }),
1239 | });
1240 | const statements = parseStatements(source);
1241 |
1242 | // --- Act
1243 | try {
1244 | processStatementQueue(statements, evalContext);
1245 | } catch (err: any) {
1246 | expect(err.toString().includes("read-only")).equal(true);
1247 | return;
1248 | }
1249 | assert.fail("Exception expected");
1250 | });
1251 |
1252 | it("Read-only write #4", () => {
1253 | // --- Arrange
1254 | const source = "$x.a[0].y--";
1255 | const evalContext = createEvalContext({
1256 | localContext: getComponentStateClone({
1257 | $x: {
1258 | a: [
1259 | {
1260 | y: 0,
1261 | },
1262 | ],
1263 | },
1264 | }),
1265 | });
1266 | const statements = parseStatements(source);
1267 |
1268 | // --- Act
1269 | try {
1270 | processStatementQueue(statements, evalContext);
1271 | } catch (err: any) {
1272 | expect(err.toString().includes("read-only")).equal(true);
1273 | return;
1274 | }
1275 | assert.fail("Exception expected");
1276 | });
1277 |
1278 | it("Read-only detects change through reference #1", () => {
1279 | // --- Arrange
1280 | const source = "let n = $x; n.a[0].y++;";
1281 | const evalContext = createEvalContext({
1282 | localContext: getComponentStateClone({
1283 | $x: {
1284 | a: [
1285 | {
1286 | y: 0,
1287 | },
1288 | ],
1289 | },
1290 | }),
1291 | });
1292 | const statements = parseStatements(source);
1293 |
1294 | // --- Act
1295 | try {
1296 | processStatementQueue(statements, evalContext);
1297 | } catch (err: any) {
1298 | expect(err.toString().includes("read-only")).equal(true);
1299 | return;
1300 | }
1301 | assert.fail("Exception expected");
1302 | });
1303 |
1304 | it("Read-only detects change through reference #2", () => {
1305 | // --- Arrange
1306 | const source = "let n = $x; n.a[0].y += 3;";
1307 | const evalContext = createEvalContext({
1308 | localContext: getComponentStateClone({
1309 | $x: {
1310 | a: [
1311 | {
1312 | y: 0,
1313 | },
1314 | ],
1315 | },
1316 | }),
1317 | });
1318 | const statements = parseStatements(source);
1319 |
1320 | // --- Act
1321 | try {
1322 | processStatementQueue(statements, evalContext);
1323 | } catch (err: any) {
1324 | expect(err.toString().includes("read-only")).equal(true);
1325 | return;
1326 | }
1327 | assert.fail("Exception expected");
1328 | });
1329 |
1330 | it("for..in loop with 'none' var binding - null", () => {
1331 | // --- Arrange
1332 | const source = "let y; let res =''; for (y in obj) res += obj[y]; return res";
1333 | const evalContext = createEvalContext({
1334 | localContext: {
1335 | obj: null,
1336 | },
1337 | });
1338 | const statements = parseStatements(source);
1339 |
1340 | // --- Act
1341 | processStatementQueue(statements, evalContext);
1342 |
1343 | // --- Assert
1344 | const thread = evalContext.mainThread!;
1345 | expect(thread.blocks!.length).equal(1);
1346 | expect(thread.returnValue).equal("");
1347 | });
1348 |
1349 | it("for..in loop with 'none' var binding - undefined", () => {
1350 | // --- Arrange
1351 | const source = "let y; let res =''; for (y in obj) res += obj[y]; return res";
1352 | const evalContext = createEvalContext({
1353 | localContext: {
1354 | obj: null,
1355 | },
1356 | });
1357 | const statements = parseStatements(source);
1358 |
1359 | // --- Act
1360 | processStatementQueue(statements, evalContext);
1361 |
1362 | // --- Assert
1363 | const thread = evalContext.mainThread!;
1364 | expect(thread.blocks!.length).equal(1);
1365 | expect(thread.returnValue).equal("");
1366 | });
1367 |
1368 | it("for..in loop with 'none' var binding", () => {
1369 | // --- Arrange
1370 | const source = "let y; let res =''; for (y in obj) res += obj[y]; return res";
1371 | const evalContext = createEvalContext({
1372 | localContext: {
1373 | obj: { one: "1", two: 2, three: 3 },
1374 | },
1375 | });
1376 | const statements = parseStatements(source);
1377 |
1378 | // --- Act
1379 | processStatementQueue(statements, evalContext);
1380 |
1381 | // --- Assert
1382 | const thread = evalContext.mainThread!;
1383 | expect(thread.blocks!.length).equal(1);
1384 | expect(thread.returnValue).equal("123");
1385 | });
1386 |
1387 | it("for..in loop with 'none' var binding - break", () => {
1388 | // --- Arrange
1389 | const source = `
1390 | let y;
1391 | let res ='';
1392 | for (y in obj) {
1393 | if (y === 'two') break;
1394 | res += obj[y];
1395 | }
1396 | return res;`;
1397 | const evalContext = createEvalContext({
1398 | localContext: {
1399 | obj: { one: "1", two: 2, three: 3 },
1400 | },
1401 | });
1402 | const statements = parseStatements(source);
1403 |
1404 | // --- Act
1405 | processStatementQueue(statements, evalContext);
1406 |
1407 | // --- Assert
1408 | const thread = evalContext.mainThread!;
1409 | expect(thread.blocks!.length).equal(1);
1410 | expect(thread.returnValue).equal("1");
1411 | });
1412 |
1413 | it("for..in loop with 'none' var binding - continue", () => {
1414 | // --- Arrange
1415 | const source = `
1416 | let y;
1417 | let res ='';
1418 | for (y in obj) {
1419 | if (y === 'two') continue;
1420 | res += obj[y];
1421 | }
1422 | return res;`;
1423 | const evalContext = createEvalContext({
1424 | localContext: {
1425 | obj: { one: "1", two: 2, three: 3 },
1426 | },
1427 | });
1428 | const statements = parseStatements(source);
1429 |
1430 | // --- Act
1431 | processStatementQueue(statements, evalContext);
1432 |
1433 | // --- Assert
1434 | const thread = evalContext.mainThread!;
1435 | expect(thread.blocks!.length).equal(1);
1436 | expect(thread.returnValue).equal("13");
1437 | });
1438 |
1439 | it("for..in loop with 'let' var binding - null", () => {
1440 | // --- Arrange
1441 | const source = "let res =''; for (let y in obj) res += obj[y]; return res";
1442 | const evalContext = createEvalContext({
1443 | localContext: {
1444 | obj: null,
1445 | },
1446 | });
1447 | const statements = parseStatements(source);
1448 |
1449 | // --- Act
1450 | processStatementQueue(statements, evalContext);
1451 |
1452 | // --- Assert
1453 | const thread = evalContext.mainThread!;
1454 | expect(thread.blocks!.length).equal(1);
1455 | expect(thread.returnValue).equal("");
1456 | });
1457 |
1458 | it("for..in loop with 'let' var binding - undefined", () => {
1459 | // --- Arrange
1460 | const source = "let res =''; for (let y in obj) res += obj[y]; return res";
1461 | const evalContext = createEvalContext({
1462 | localContext: {
1463 | obj: null,
1464 | },
1465 | });
1466 | const statements = parseStatements(source);
1467 |
1468 | // --- Act
1469 | processStatementQueue(statements, evalContext);
1470 |
1471 | // --- Assert
1472 | const thread = evalContext.mainThread!;
1473 | expect(thread.blocks!.length).equal(1);
1474 | expect(thread.returnValue).equal("");
1475 | });
1476 |
1477 | it("for..in loop with 'let' var binding", () => {
1478 | // --- Arrange
1479 | const source = "let res =''; for (let y in obj) res += obj[y]; return res";
1480 | const evalContext = createEvalContext({
1481 | localContext: {
1482 | obj: { one: "1", two: 2, three: 3 },
1483 | },
1484 | });
1485 | const statements = parseStatements(source);
1486 |
1487 | // --- Act
1488 | processStatementQueue(statements, evalContext);
1489 |
1490 | // --- Assert
1491 | const thread = evalContext.mainThread!;
1492 | expect(thread.blocks!.length).equal(1);
1493 | expect(thread.returnValue).equal("123");
1494 | });
1495 |
1496 | it("for..in loop with 'let' var binding - break", () => {
1497 | // --- Arrange
1498 | const source = `
1499 | let res ='';
1500 | for (let y in obj) {
1501 | if (y === 'two') break;
1502 | res += obj[y];
1503 | }
1504 | return res;`;
1505 | const evalContext = createEvalContext({
1506 | localContext: {
1507 | obj: { one: "1", two: 2, three: 3 },
1508 | },
1509 | });
1510 | const statements = parseStatements(source);
1511 |
1512 | // --- Act
1513 | processStatementQueue(statements, evalContext);
1514 |
1515 | // --- Assert
1516 | const thread = evalContext.mainThread!;
1517 | expect(thread.blocks!.length).equal(1);
1518 | expect(thread.returnValue).equal("1");
1519 | });
1520 |
1521 | it("for..in loop with 'let' var binding - continue", () => {
1522 | // --- Arrange
1523 | const source = `
1524 | let res ='';
1525 | for (let y in obj) {
1526 | if (y === 'two') continue;
1527 | res += obj[y];
1528 | }
1529 | return res;`;
1530 | const evalContext = createEvalContext({
1531 | localContext: {
1532 | obj: { one: "1", two: 2, three: 3 },
1533 | },
1534 | });
1535 | const statements = parseStatements(source);
1536 |
1537 | // --- Act
1538 | processStatementQueue(statements, evalContext);
1539 |
1540 | // --- Assert
1541 | const thread = evalContext.mainThread!;
1542 | expect(thread.blocks!.length).equal(1);
1543 | expect(thread.returnValue).equal("13");
1544 | });
1545 |
1546 | it("for..in loop with 'let' can write binding ", () => {
1547 | // --- Arrange
1548 | const source = `
1549 | let res ='';
1550 | for (let y in obj) {
1551 | res += obj[y];
1552 | y = 345;
1553 | }
1554 | return res`;
1555 | const evalContext = createEvalContext({
1556 | localContext: {
1557 | obj: { one: "1", two: 2, three: 3 },
1558 | },
1559 | });
1560 | const statements = parseStatements(source);
1561 |
1562 | // --- Act
1563 | processStatementQueue(statements, evalContext);
1564 |
1565 | // --- Assert
1566 | const thread = evalContext.mainThread!;
1567 | expect(thread.blocks!.length).equal(1);
1568 | expect(thread.returnValue).equal("123");
1569 | });
1570 |
1571 | it("for..in loop with 'const' var binding - null", () => {
1572 | // --- Arrange
1573 | const source = "let res =''; for (const y in obj) res += obj[y]; return res";
1574 | const evalContext = createEvalContext({
1575 | localContext: {
1576 | obj: null,
1577 | },
1578 | });
1579 | const statements = parseStatements(source);
1580 |
1581 | // --- Act
1582 | processStatementQueue(statements, evalContext);
1583 |
1584 | // --- Assert
1585 | const thread = evalContext.mainThread!;
1586 | expect(thread.blocks!.length).equal(1);
1587 | expect(thread.returnValue).equal("");
1588 | });
1589 |
1590 | it("for..in loop with 'const' var binding - undefined", () => {
1591 | // --- Arrange
1592 | const source = "let res =''; for (const y in obj) res += obj[y]; return res";
1593 | const evalContext = createEvalContext({
1594 | localContext: {
1595 | obj: null,
1596 | },
1597 | });
1598 | const statements = parseStatements(source);
1599 |
1600 | // --- Act
1601 | processStatementQueue(statements, evalContext);
1602 |
1603 | // --- Assert
1604 | const thread = evalContext.mainThread!;
1605 | expect(thread.blocks!.length).equal(1);
1606 | expect(thread.returnValue).equal("");
1607 | });
1608 |
1609 | it("for..in loop with 'const' var binding", () => {
1610 | // --- Arrange
1611 | const source = "let res =''; for (const y in obj) res += obj[y]; return res";
1612 | const evalContext = createEvalContext({
1613 | localContext: {
1614 | obj: { one: "1", two: 2, three: 3 },
1615 | },
1616 | });
1617 | const statements = parseStatements(source);
1618 |
1619 | // --- Act
1620 | processStatementQueue(statements, evalContext);
1621 |
1622 | // --- Assert
1623 | const thread = evalContext.mainThread!;
1624 | expect(thread.blocks!.length).equal(1);
1625 | expect(thread.returnValue).equal("123");
1626 | });
1627 |
1628 | it("for..in loop with 'const' var binding - break", () => {
1629 | // --- Arrange
1630 | const source = `
1631 | let res ='';
1632 | for (const y in obj) {
1633 | if (y === 'two') break;
1634 | res += obj[y];
1635 | }
1636 | return res;`;
1637 | const evalContext = createEvalContext({
1638 | localContext: {
1639 | obj: { one: "1", two: 2, three: 3 },
1640 | },
1641 | });
1642 | const statements = parseStatements(source);
1643 |
1644 | // --- Act
1645 | processStatementQueue(statements, evalContext);
1646 |
1647 | // --- Assert
1648 | const thread = evalContext.mainThread!;
1649 | expect(thread.blocks!.length).equal(1);
1650 | expect(thread.returnValue).equal("1");
1651 | });
1652 |
1653 | it("for..in loop with 'const' var binding - continue", () => {
1654 | // --- Arrange
1655 | const source = `
1656 | let res ='';
1657 | for (const y in obj) {
1658 | if (y === 'two') continue;
1659 | res += obj[y];
1660 | }
1661 | return res;`;
1662 | const evalContext = createEvalContext({
1663 | localContext: {
1664 | obj: { one: "1", two: 2, three: 3 },
1665 | },
1666 | });
1667 | const statements = parseStatements(source);
1668 |
1669 | // --- Act
1670 | processStatementQueue(statements, evalContext);
1671 |
1672 | // --- Assert
1673 | const thread = evalContext.mainThread!;
1674 | expect(thread.blocks!.length).equal(1);
1675 | expect(thread.returnValue).equal("13");
1676 | });
1677 |
1678 | it("for..in loop with 'const' disallows write binding ", () => {
1679 | // --- Arrange
1680 | const source = `
1681 | let res ='';
1682 | for (const y in obj) {
1683 | res += obj[y];
1684 | y = 345;
1685 | }
1686 | return res`;
1687 | const evalContext = createEvalContext({
1688 | localContext: {
1689 | obj: { one: "1", two: 2, three: 3 },
1690 | },
1691 | });
1692 | const statements = parseStatements(source);
1693 |
1694 | // --- Act/Assert
1695 | try {
1696 | processStatementQueue(statements, evalContext);
1697 | } catch (err: any) {
1698 | expect(err.toString().includes("const")).equal(true);
1699 | return;
1700 | }
1701 | assert.fail("Exception expected");
1702 | });
1703 |
1704 | it("for..of loop with not iterable #1", () => {
1705 | // --- Arrange
1706 | const source = "for (y of obj) res += obj[y]; return res";
1707 | const evalContext = createEvalContext({
1708 | localContext: {
1709 | obj: null,
1710 | },
1711 | });
1712 | const statements = parseStatements(source);
1713 |
1714 | // --- Act/Assert
1715 | try {
1716 | processStatementQueue(statements, evalContext);
1717 | } catch (err: any) {
1718 | expect(err.toString().includes("Iterator expected"));
1719 | return;
1720 | }
1721 | assert.fail("Exception expected");
1722 | });
1723 |
1724 | it("for..of loop with not iterable #2", () => {
1725 | // --- Arrange
1726 | const source = "for (y of obj) res += obj[y]; return res";
1727 | const evalContext = createEvalContext({
1728 | localContext: {
1729 | obj: 123,
1730 | },
1731 | });
1732 | const statements = parseStatements(source);
1733 |
1734 | // --- Act/Assert
1735 | try {
1736 | processStatementQueue(statements, evalContext);
1737 | } catch (err: any) {
1738 | expect(err.toString().includes("Iterator expected"));
1739 | return;
1740 | }
1741 | assert.fail("Exception expected");
1742 | });
1743 |
1744 | it("for..of loop with 'none' var binding", () => {
1745 | // --- Arrange
1746 | const source = "let y; let res =''; for (y of obj) res += y; return res";
1747 | const evalContext = createEvalContext({
1748 | localContext: {
1749 | obj: [1, 2, 3],
1750 | },
1751 | });
1752 | const statements = parseStatements(source);
1753 |
1754 | // --- Act
1755 | processStatementQueue(statements, evalContext);
1756 |
1757 | // --- Assert
1758 | const thread = evalContext.mainThread!;
1759 | expect(thread.blocks!.length).equal(1);
1760 | expect(thread.returnValue).equal("123");
1761 | });
1762 |
1763 | it("for..of loop with 'none' var binding - break", () => {
1764 | // --- Arrange
1765 | const source = `
1766 | let y;
1767 | let res ='';
1768 | for (y of obj) {
1769 | if (y === 2) break;
1770 | res += y;
1771 | }
1772 | return res;`;
1773 | const evalContext = createEvalContext({
1774 | localContext: {
1775 | obj: [1, 2, 3],
1776 | },
1777 | });
1778 | const statements = parseStatements(source);
1779 |
1780 | // --- Act
1781 | processStatementQueue(statements, evalContext);
1782 |
1783 | // --- Assert
1784 | const thread = evalContext.mainThread!;
1785 | expect(thread.blocks!.length).equal(1);
1786 | expect(thread.returnValue).equal("1");
1787 | });
1788 |
1789 | it("for..of loop with 'none' var binding - continue", () => {
1790 | // --- Arrange
1791 | const source = `
1792 | let y;
1793 | let res ='';
1794 | for (y of obj) {
1795 | if (y === 2) continue;
1796 | res += y;
1797 | }
1798 | return res;`;
1799 | const evalContext = createEvalContext({
1800 | localContext: {
1801 | obj: [1, 2, 3],
1802 | },
1803 | });
1804 | const statements = parseStatements(source);
1805 |
1806 | // --- Act
1807 | processStatementQueue(statements, evalContext);
1808 |
1809 | // --- Assert
1810 | const thread = evalContext.mainThread!;
1811 | expect(thread.blocks!.length).equal(1);
1812 | expect(thread.returnValue).equal("13");
1813 | });
1814 |
1815 | it("for..of loop with 'let' var binding", () => {
1816 | // --- Arrange
1817 | const source = "let res =''; for (let y of obj) res += y; return res";
1818 | const evalContext = createEvalContext({
1819 | localContext: {
1820 | obj: [1, 2, 3],
1821 | },
1822 | });
1823 | const statements = parseStatements(source);
1824 |
1825 | // --- Act
1826 | processStatementQueue(statements, evalContext);
1827 |
1828 | // --- Assert
1829 | const thread = evalContext.mainThread!;
1830 | expect(thread.blocks!.length).equal(1);
1831 | expect(thread.returnValue).equal("123");
1832 | });
1833 |
1834 | it("for..of loop with 'let' var binding - break", () => {
1835 | // --- Arrange
1836 | const source = `
1837 | let res ='';
1838 | for (let y of obj) {
1839 | if (y === 2) break;
1840 | res += y;
1841 | }
1842 | return res;`;
1843 | const evalContext = createEvalContext({
1844 | localContext: {
1845 | obj: [1, 2, 3],
1846 | },
1847 | });
1848 | const statements = parseStatements(source);
1849 |
1850 | // --- Act
1851 | processStatementQueue(statements, evalContext);
1852 |
1853 | // --- Assert
1854 | const thread = evalContext.mainThread!;
1855 | expect(thread.blocks!.length).equal(1);
1856 | expect(thread.returnValue).equal("1");
1857 | });
1858 |
1859 | it("for..of loop with 'let' var binding - continue", () => {
1860 | // --- Arrange
1861 | const source = `
1862 | let res ='';
1863 | for (let y of obj) {
1864 | if (y === 2) continue;
1865 | res += y;
1866 | }
1867 | return res;`;
1868 | const evalContext = createEvalContext({
1869 | localContext: {
1870 | obj: [1, 2, 3],
1871 | },
1872 | });
1873 | const statements = parseStatements(source);
1874 |
1875 | // --- Act
1876 | processStatementQueue(statements, evalContext);
1877 |
1878 | // --- Assert
1879 | const thread = evalContext.mainThread!;
1880 | expect(thread.blocks!.length).equal(1);
1881 | expect(thread.returnValue).equal("13");
1882 | });
1883 |
1884 | it("for..of loop with 'let' can write binding ", () => {
1885 | // --- Arrange
1886 | const source = `
1887 | let res ='';
1888 | for (let y of obj) {
1889 | res += y;
1890 | y = 345;
1891 | }
1892 | return res`;
1893 | const evalContext = createEvalContext({
1894 | localContext: {
1895 | obj: [1, 2, 3],
1896 | },
1897 | });
1898 | const statements = parseStatements(source);
1899 |
1900 | // --- Act
1901 | processStatementQueue(statements, evalContext);
1902 |
1903 | // --- Assert
1904 | const thread = evalContext.mainThread!;
1905 | expect(thread.blocks!.length).equal(1);
1906 | expect(thread.returnValue).equal("123");
1907 | });
1908 |
1909 | it("for..of loop with 'const' var binding", () => {
1910 | // --- Arrange
1911 | const source = "let res =''; for (const y of obj) res += y; return res";
1912 | const evalContext = createEvalContext({
1913 | localContext: {
1914 | obj: [1, 2, 3],
1915 | },
1916 | });
1917 | const statements = parseStatements(source);
1918 |
1919 | // --- Act
1920 | processStatementQueue(statements, evalContext);
1921 |
1922 | // --- Assert
1923 | const thread = evalContext.mainThread!;
1924 | expect(thread.blocks!.length).equal(1);
1925 | expect(thread.returnValue).equal("123");
1926 | });
1927 |
1928 | it("for..of loop with 'const' var binding - break", () => {
1929 | // --- Arrange
1930 | const source = `
1931 | let res ='';
1932 | for (const y of obj) {
1933 | if (y === 2) break;
1934 | res += y;
1935 | }
1936 | return res;`;
1937 | const evalContext = createEvalContext({
1938 | localContext: {
1939 | obj: [1, 2, 3],
1940 | },
1941 | });
1942 | const statements = parseStatements(source);
1943 |
1944 | // --- Act
1945 | processStatementQueue(statements, evalContext);
1946 |
1947 | // --- Assert
1948 | const thread = evalContext.mainThread!;
1949 | expect(thread.blocks!.length).equal(1);
1950 | expect(thread.returnValue).equal("1");
1951 | });
1952 |
1953 | it("for..of loop with 'const' var binding - continue", () => {
1954 | // --- Arrange
1955 | const source = `
1956 | let res ='';
1957 | for (const y of obj) {
1958 | if (y === 2) continue;
1959 | res += y;
1960 | }
1961 | return res;`;
1962 | const evalContext = createEvalContext({
1963 | localContext: {
1964 | obj: [1, 2, 3],
1965 | },
1966 | });
1967 | const statements = parseStatements(source);
1968 |
1969 | // --- Act
1970 | processStatementQueue(statements, evalContext);
1971 |
1972 | // --- Assert
1973 | const thread = evalContext.mainThread!;
1974 | expect(thread.blocks!.length).equal(1);
1975 | expect(thread.returnValue).equal("13");
1976 | });
1977 |
1978 | it("for..of loop with 'const' disallows write binding ", () => {
1979 | // --- Arrange
1980 | const source = `
1981 | let res ='';
1982 | for (const y of obj) {
1983 | res += y;
1984 | y = 345;
1985 | }
1986 | return res`;
1987 | const evalContext = createEvalContext({
1988 | localContext: {
1989 | obj: [1, 2, 3],
1990 | },
1991 | });
1992 | const statements = parseStatements(source);
1993 |
1994 | // --- Act/Assert
1995 | try {
1996 | processStatementQueue(statements, evalContext);
1997 | } catch (err: any) {
1998 | expect(err.toString().includes("const")).equal(true);
1999 | return;
2000 | }
2001 | assert.fail("Exception expected");
2002 | });
2003 | });
2004 |
2005 | function getComponentStateClone(orig: any): any {
2006 | const poj = structuredClone(orig);
2007 | return buildProxy(poj, (changeInfo) => {
2008 | const idRoot = changeInfo.pathArray?.[0];
2009 | if (idRoot?.toString()?.startsWith("$")) {
2010 | throw new Error("Cannot update a read-only variable");
2011 | }
2012 | });
2013 | }
2014 |
```