This is page 163 of 181. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/assets/img/%7Bsrc%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.yml
│ ├── deploy-docs-optimized.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
│ ├── layout-changes.md
│ ├── package.json
│ ├── public
│ │ ├── blog
│ │ │ ├── images
│ │ │ │ ├── blog-page-component.png
│ │ │ │ ├── blog-scrabble.png
│ │ │ │ ├── integrated-blog-search.png
│ │ │ │ └── lorem-ipsum.png
│ │ │ ├── lorem-ipsum.md
│ │ │ ├── newest-post.md
│ │ │ ├── older-post.md
│ │ │ └── welcome-to-the-xmlui-blog.md
│ │ ├── mockServiceWorker.js
│ │ ├── resources
│ │ │ ├── favicon.ico
│ │ │ ├── files
│ │ │ │ └── for-download
│ │ │ │ └── xmlui
│ │ │ │ └── xmlui-standalone.umd.js
│ │ │ ├── github.svg
│ │ │ ├── llms.txt
│ │ │ ├── logo-dark.svg
│ │ │ ├── logo.svg
│ │ │ ├── pg-popout.svg
│ │ │ ├── rss.svg
│ │ │ └── xmlui-logo.svg
│ │ ├── serve.json
│ │ └── web.config
│ ├── scripts
│ │ ├── download-latest-xmlui.js
│ │ ├── generate-rss.js
│ │ ├── get-releases.js
│ │ └── utils.js
│ ├── src
│ │ ├── components
│ │ │ ├── BlogOverview.xmlui
│ │ │ ├── BlogPage.xmlui
│ │ │ └── PageNotFound.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
│ │ ├── HelloMd.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
│ │ │ │ ├── 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
│ │ │ ├── github.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
│ │ └── 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
│ │ │ ├── NameValue.xmlui
│ │ │ ├── PageNotFound.xmlui
│ │ │ ├── PaletteItem.xmlui
│ │ │ ├── Palettes.xmlui
│ │ │ ├── SectionHeader.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
│ ├── 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
│ │ └── tsconfig.json
│ ├── 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
│ │ ├── tsconfig.json
│ │ └── 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
│ │ └── tsconfig.json
│ ├── 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
│ │ └── tsconfig.json
│ ├── 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
│ │ └── tsconfig.json
│ ├── 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.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.module.scss
│ │ │ │ ├── Preview.tsx
│ │ │ │ ├── Select.module.scss
│ │ │ │ ├── StandalonePlayground.tsx
│ │ │ │ ├── StandalonePlaygroundNative.module.scss
│ │ │ │ ├── StandalonePlaygroundNative.tsx
│ │ │ │ ├── ThemeSwitcher.module.scss
│ │ │ │ ├── ThemeSwitcher.tsx
│ │ │ │ ├── ToneSwitcher.tsx
│ │ │ │ ├── Tooltip.module.scss
│ │ │ │ ├── Tooltip.tsx
│ │ │ │ └── utils.ts
│ │ │ ├── providers
│ │ │ │ ├── Toast.module.scss
│ │ │ │ └── ToastProvider.tsx
│ │ │ ├── state
│ │ │ │ └── store.ts
│ │ │ ├── themes
│ │ │ │ └── theme.ts
│ │ │ └── utils
│ │ │ └── helpers.ts
│ │ └── tsconfig.json
│ ├── 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
│ │ └── tsconfig.json
│ ├── xmlui-spreadsheet
│ │ ├── .gitignore
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── index.tsx
│ │ │ ├── Spreadsheet.tsx
│ │ │ └── SpreadsheetNative.tsx
│ │ └── tsconfig.json
│ └── 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.tsx
│ │ │ └── HeroSectionNative.tsx
│ │ ├── index.tsx
│ │ ├── ScrollToTop
│ │ │ ├── ScrollToTop.module.scss
│ │ │ ├── ScrollToTop.tsx
│ │ │ └── ScrollToTopNative.tsx
│ │ └── vite-env.d.ts
│ └── tsconfig.json
├── 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.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
│ ├── 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
│ ├── ud-components.md
│ └── xmlui-repo.md
├── package.json
├── playwright.config.ts
├── scripts
│ ├── coverage-only.js
│ ├── e2e-test-summary.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
│ ├── get-langserver-metadata.mjs
│ ├── 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.spec.ts
│ │ │ │ ├── LabelList.tsx
│ │ │ │ ├── LabelListNative.module.scss
│ │ │ │ └── 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
│ │ ├── 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.mjs
│ ├── 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
│ │ │ ├── ModalDialogDriver.ts
│ │ │ ├── NumberBoxDriver.ts
│ │ │ ├── TextBoxDriver.ts
│ │ │ ├── TimeInputDriver.ts
│ │ │ ├── TimerDriver.ts
│ │ │ └── TreeDriver.ts
│ │ ├── fixtures.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.bin.json
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── vitest.config.ts
```
# Files
--------------------------------------------------------------------------------
/xmlui/tests/components-core/scripts-runner/process-statement.test.ts:
--------------------------------------------------------------------------------
```typescript
1 | import { describe, expect, it, assert } from "vitest";
2 |
3 | import { processStatementQueueAsync } from "../../../src/components-core/script-runner/process-statement-async";
4 | import { createEvalContext, parseStatements } from "./test-helpers";
5 | import { buildProxy } from "../../../src/components-core/rendering/buildProxy";
6 |
7 | describe("Process statements (exp)", () => {
8 | it("expression statement #1", async () => {
9 | // --- Arrange
10 | const source = "x = 3 * x;";
11 | const evalContext = createEvalContext({
12 | localContext: {
13 | x: 1,
14 | },
15 | });
16 | const statements = parseStatements(source);
17 |
18 | // --- Act
19 | const diag = await processStatementQueueAsync(statements, evalContext);
20 |
21 | // --- Assert
22 | expect(evalContext.mainThread!.blocks!.length).equal(1);
23 | expect(evalContext.localContext.x).equal(3);
24 |
25 | expect(diag.processedStatements).equal(1);
26 | expect(diag.maxLoops).equal(0);
27 | expect(diag.maxBlocks).equal(1);
28 | expect(diag.maxQueueLength).equal(1);
29 | expect(diag.clearToLabels).equal(0);
30 | expect(diag.unshiftedItems).equal(0);
31 | });
32 |
33 | it("Let statement #1", async () => {
34 | // --- Arrange
35 | const source = "let y";
36 | const evalContext = createEvalContext({
37 | localContext: {
38 | x: 0,
39 | },
40 | });
41 | const statements = parseStatements(source);
42 |
43 | // --- Act
44 | const diag = await processStatementQueueAsync(statements, evalContext);
45 |
46 | // --- Assert
47 | const thread = evalContext.mainThread!;
48 | expect(thread.blocks!.length).equal(1);
49 | expect("y" in thread.blocks![0].vars).equal(true);
50 | expect(thread.blocks![0].constVars).equal(undefined);
51 |
52 | expect(diag.processedStatements).equal(1);
53 | expect(diag.maxLoops).equal(0);
54 | expect(diag.maxBlocks).equal(1);
55 | expect(diag.maxQueueLength).equal(1);
56 | expect(diag.clearToLabels).equal(0);
57 | expect(diag.unshiftedItems).equal(0);
58 | });
59 |
60 | it("Let statement #2", async () => {
61 | // --- Arrange
62 | const source = "let y = 3";
63 | const evalContext = createEvalContext({
64 | localContext: {
65 | x: 0,
66 | },
67 | });
68 | const statements = parseStatements(source);
69 |
70 | // --- Act
71 | const diag = await processStatementQueueAsync(statements, evalContext);
72 |
73 | // --- Assert
74 | const thread = evalContext.mainThread!;
75 | expect(thread.blocks!.length).equal(1);
76 | expect(thread.blocks![0].vars.y).equal(3);
77 | expect(thread.blocks![0].constVars).equal(undefined);
78 |
79 | expect(diag.processedStatements).equal(1);
80 | expect(diag.maxLoops).equal(0);
81 | expect(diag.maxBlocks).equal(1);
82 | expect(diag.maxQueueLength).equal(1);
83 | expect(diag.clearToLabels).equal(0);
84 | expect(diag.unshiftedItems).equal(0);
85 | });
86 |
87 | it("Let statement #3", async () => {
88 | // --- Arrange
89 | const source = "let y = 3, z = 2";
90 | const evalContext = createEvalContext({
91 | localContext: {},
92 | });
93 | const statements = parseStatements(source);
94 |
95 | // --- Act
96 | const diag = await processStatementQueueAsync(statements, evalContext);
97 |
98 | // --- Assert
99 | const thread = evalContext.mainThread!;
100 | expect(thread.blocks!.length).equal(1);
101 | expect(thread.blocks![0].vars.y).equal(3);
102 | expect(thread.blocks![0].vars.z).equal(2);
103 | expect(thread.blocks![0].constVars).equal(undefined);
104 |
105 | expect(diag.processedStatements).equal(1);
106 | expect(diag.maxLoops).equal(0);
107 | expect(diag.maxBlocks).equal(1);
108 | expect(diag.maxQueueLength).equal(1);
109 | expect(diag.clearToLabels).equal(0);
110 | expect(diag.unshiftedItems).equal(0);
111 | });
112 |
113 | it("Const statement #2", async () => {
114 | // --- Arrange
115 | const source = "const y = 3";
116 | const evalContext = createEvalContext({
117 | localContext: {
118 | x: 0,
119 | },
120 | });
121 | const statements = parseStatements(source);
122 |
123 | // --- Act
124 | const diag = await processStatementQueueAsync(statements, evalContext);
125 |
126 | // --- Assert
127 | const thread = evalContext.mainThread!;
128 | expect(thread.blocks!.length).equal(1);
129 | expect(thread.blocks![0].vars.y).equal(3);
130 | expect(thread.blocks![0].constVars!.has("y")).equal(true);
131 |
132 | expect(diag.processedStatements).equal(1);
133 | expect(diag.maxLoops).equal(0);
134 | expect(diag.maxBlocks).equal(1);
135 | expect(diag.maxQueueLength).equal(1);
136 | expect(diag.clearToLabels).equal(0);
137 | expect(diag.unshiftedItems).equal(0);
138 | });
139 |
140 | it("Const write #1", async () => {
141 | // --- Arrange
142 | const source = "const y = 3; y++";
143 | const evalContext = createEvalContext({
144 | localContext: {
145 | x: 0,
146 | },
147 | });
148 | const statements = parseStatements(source);
149 |
150 | // --- Act
151 | try {
152 | await processStatementQueueAsync(statements, evalContext);
153 | } catch (err) {
154 | return;
155 | }
156 | assert.fail("Exception expected");
157 | });
158 |
159 | it("Const write #2", async () => {
160 | // --- Arrange
161 | const source = "const y = 3; y = 12";
162 | const evalContext = createEvalContext({
163 | localContext: {
164 | x: 0,
165 | },
166 | });
167 | const statements = parseStatements(source);
168 |
169 | // --- Act
170 | try {
171 | await processStatementQueueAsync(statements, evalContext);
172 | } catch (err) {
173 | return;
174 | }
175 | assert.fail("Exception expected");
176 | });
177 |
178 | it("Implicit block #1", async () => {
179 | // --- Arrange
180 | const source = "let y = 3; x = 3 * y;";
181 | const evalContext = createEvalContext({
182 | localContext: {
183 | x: 0,
184 | },
185 | });
186 | const statements = parseStatements(source);
187 |
188 | // --- Act
189 | const diag = await processStatementQueueAsync(statements, evalContext);
190 |
191 | // --- Assert
192 | const thread = evalContext.mainThread!;
193 | expect(thread.blocks!.length).equal(1);
194 | expect(thread.blocks![0].vars.y).equal(3);
195 | expect(evalContext.localContext.x).equal(9);
196 |
197 | expect(diag.processedStatements).equal(2);
198 | expect(diag.maxLoops).equal(0);
199 | expect(diag.maxBlocks).equal(1);
200 | expect(diag.maxQueueLength).equal(2);
201 | expect(diag.clearToLabels).equal(0);
202 | expect(diag.unshiftedItems).equal(0);
203 | });
204 |
205 | it("Implicit block #2", async () => {
206 | // --- Arrange
207 | const source = "let y = 3; { let z = 2 ; x = 3 * y + z; }";
208 | const evalContext = createEvalContext({
209 | localContext: {
210 | x: 0,
211 | },
212 | });
213 | const statements = parseStatements(source);
214 |
215 | // --- Act
216 | const diag = await processStatementQueueAsync(statements, evalContext);
217 |
218 | // --- Assert
219 | const thread = evalContext.mainThread!;
220 | expect(thread.blocks!.length).equal(1);
221 | expect(thread.blocks![0].vars.y).equal(3);
222 | expect(evalContext.localContext.x).equal(11);
223 |
224 | expect(diag.processedStatements).equal(5);
225 | expect(diag.maxLoops).equal(0);
226 | expect(diag.maxBlocks).equal(2);
227 | expect(diag.maxQueueLength).equal(3);
228 | expect(diag.clearToLabels).equal(0);
229 | expect(diag.unshiftedItems).equal(3);
230 | });
231 |
232 | it("Block statement #1", async () => {
233 | // --- Arrange
234 | const source = "{ let y = 3; x = 3 * y; }";
235 | const evalContext = createEvalContext({
236 | localContext: {
237 | x: 0,
238 | },
239 | });
240 | const statements = parseStatements(source);
241 |
242 | // --- Act
243 | const diag = await processStatementQueueAsync(statements, evalContext);
244 |
245 | // --- Assert
246 | expect(evalContext.mainThread!.blocks!.length).equal(1);
247 | expect(evalContext.localContext.x).equal(9);
248 |
249 | expect(diag.processedStatements).equal(4);
250 | expect(diag.maxLoops).equal(0);
251 | expect(diag.maxBlocks).equal(2);
252 | expect(diag.maxQueueLength).equal(3);
253 | expect(diag.clearToLabels).equal(0);
254 | expect(diag.unshiftedItems).equal(3);
255 | });
256 |
257 | it("Block statement #2", async () => {
258 | // --- Arrange
259 | const source = "{ let y = 3; { let z = 2 ; x = 3 * y + z; } }";
260 | const evalContext = createEvalContext({
261 | localContext: {
262 | x: 0,
263 | },
264 | });
265 | const statements = parseStatements(source);
266 |
267 | // --- Act
268 | const diag = await processStatementQueueAsync(statements, evalContext);
269 |
270 | // --- Assert
271 | expect(evalContext.mainThread!.blocks!.length).equal(1);
272 | expect(evalContext.localContext.x).equal(11);
273 |
274 | expect(diag.processedStatements).equal(7);
275 | expect(diag.maxLoops).equal(0);
276 | expect(diag.maxBlocks).equal(3);
277 | expect(diag.maxQueueLength).equal(4);
278 | expect(diag.clearToLabels).equal(0);
279 | expect(diag.unshiftedItems).equal(6);
280 | });
281 |
282 | it("Block statement #3", async () => {
283 | // --- Arrange
284 | const source = "{ let y = 3; { let z = 2 ; { x = 3 * y + z; } } }";
285 | const evalContext = createEvalContext({
286 | localContext: {
287 | x: 0,
288 | },
289 | });
290 | const statements = parseStatements(source);
291 |
292 | // --- Act
293 | const diag = await processStatementQueueAsync(statements, evalContext);
294 |
295 | // --- Assert
296 | expect(evalContext.mainThread!.blocks!.length).equal(1);
297 | expect(evalContext.localContext.x).equal(11);
298 |
299 | expect(diag.processedStatements).equal(9);
300 | expect(diag.maxLoops).equal(0);
301 | expect(diag.maxBlocks).equal(4);
302 | expect(diag.maxQueueLength).equal(4);
303 | expect(diag.clearToLabels).equal(0);
304 | expect(diag.unshiftedItems).equal(8);
305 | });
306 |
307 | it("Block statement #4", async () => {
308 | // --- Arrange
309 | const source = "{ let y = 3; { let z = 2 ; { let z = 3; x = 3 * y + z; } } }";
310 | const evalContext = createEvalContext({
311 | localContext: {
312 | x: 0,
313 | },
314 | });
315 | const statements = parseStatements(source);
316 |
317 | // --- Act
318 | const diag = await processStatementQueueAsync(statements, evalContext);
319 |
320 | // --- Assert
321 | expect(evalContext.mainThread!.blocks!.length).equal(1);
322 | expect(evalContext.localContext.x).equal(12);
323 |
324 | expect(diag.processedStatements).equal(10);
325 | expect(diag.maxLoops).equal(0);
326 | expect(diag.maxBlocks).equal(4);
327 | expect(diag.maxQueueLength).equal(5);
328 | expect(diag.clearToLabels).equal(0);
329 | expect(diag.unshiftedItems).equal(9);
330 | });
331 |
332 | it("If statement #1", async () => {
333 | // --- Arrange
334 | const source = "if (x === 0) x = 3";
335 | const evalContext = createEvalContext({
336 | localContext: {
337 | x: 0,
338 | },
339 | });
340 | const statements = parseStatements(source);
341 |
342 | // --- Act
343 | const diag = await processStatementQueueAsync(statements, evalContext);
344 |
345 | // --- Assert
346 | expect(evalContext.mainThread!.blocks!.length).equal(1);
347 | expect(evalContext.localContext.x).equal(3);
348 |
349 | expect(diag.processedStatements).equal(2);
350 | expect(diag.maxLoops).equal(0);
351 | expect(diag.maxBlocks).equal(1);
352 | expect(diag.maxQueueLength).equal(1);
353 | expect(diag.clearToLabels).equal(0);
354 | expect(diag.unshiftedItems).equal(1);
355 | });
356 |
357 | it("If statement #2", async () => {
358 | // --- Arrange
359 | const source = "if (x === 0) {x = 3}";
360 | const evalContext = createEvalContext({
361 | localContext: {
362 | x: 0,
363 | },
364 | });
365 | const statements = parseStatements(source);
366 |
367 | // --- Act
368 | const diag = await processStatementQueueAsync(statements, evalContext);
369 |
370 | // --- Assert
371 | expect(evalContext.mainThread!.blocks!.length).equal(1);
372 | expect(evalContext.localContext.x).equal(3);
373 |
374 | expect(diag.processedStatements).equal(4);
375 | expect(diag.maxLoops).equal(0);
376 | expect(diag.maxBlocks).equal(2);
377 | expect(diag.maxQueueLength).equal(2);
378 | expect(diag.clearToLabels).equal(0);
379 | expect(diag.unshiftedItems).equal(3);
380 | });
381 |
382 | it("If statement #3", async () => {
383 | // --- Arrange
384 | const source = "if (x === 0) x = 3; else x = 2";
385 | const evalContext = createEvalContext({
386 | localContext: {
387 | x: 1,
388 | },
389 | });
390 | const statements = parseStatements(source);
391 |
392 | // --- Act
393 | const diag = await processStatementQueueAsync(statements, evalContext);
394 |
395 | // --- Assert
396 | expect(evalContext.mainThread!.blocks!.length).equal(1);
397 | expect(evalContext.localContext.x).equal(2);
398 |
399 | expect(diag.processedStatements).equal(2);
400 | expect(diag.maxLoops).equal(0);
401 | expect(diag.maxBlocks).equal(1);
402 | expect(diag.maxQueueLength).equal(1);
403 | expect(diag.clearToLabels).equal(0);
404 | expect(diag.unshiftedItems).equal(1);
405 | });
406 |
407 | it("If statement #4", async () => {
408 | // --- Arrange
409 | const source = "if (x === 0) x = 3; else { x = 2 }";
410 | const evalContext = createEvalContext({
411 | localContext: {
412 | x: 1,
413 | },
414 | });
415 | const statements = parseStatements(source);
416 |
417 | // --- Act
418 | const diag = await processStatementQueueAsync(statements, evalContext);
419 |
420 | // --- Assert
421 | expect(evalContext.mainThread!.blocks!.length).equal(1);
422 | expect(evalContext.localContext.x).equal(2);
423 |
424 | expect(diag.processedStatements).equal(4);
425 | expect(diag.maxLoops).equal(0);
426 | expect(diag.maxBlocks).equal(2);
427 | expect(diag.maxQueueLength).equal(2);
428 | expect(diag.clearToLabels).equal(0);
429 | expect(diag.unshiftedItems).equal(3);
430 | });
431 |
432 | it("If statement #5", async () => {
433 | // --- Arrange
434 | const source = "if (x === 0) {x = 3;} else { x = 2 }";
435 | const evalContext = createEvalContext({
436 | localContext: {
437 | x: 0,
438 | },
439 | });
440 | const statements = parseStatements(source);
441 |
442 | // --- Act
443 | const diag = await processStatementQueueAsync(statements, evalContext);
444 |
445 | // --- Assert
446 | expect(evalContext.mainThread!.blocks!.length).equal(1);
447 | expect(evalContext.localContext.x).equal(3);
448 |
449 | expect(diag.processedStatements).equal(4);
450 | expect(diag.maxLoops).equal(0);
451 | expect(diag.maxBlocks).equal(2);
452 | expect(diag.maxQueueLength).equal(2);
453 | expect(diag.clearToLabels).equal(0);
454 | expect(diag.unshiftedItems).equal(3);
455 | });
456 |
457 | it("If statement #6", async () => {
458 | // --- Arrange
459 | const source = "if (x === 0) {x = 3;} else { x = 2 }";
460 | const evalContext = createEvalContext({
461 | localContext: {
462 | x: 1,
463 | },
464 | });
465 | const statements = parseStatements(source);
466 |
467 | // --- Act
468 | const diag = await processStatementQueueAsync(statements, evalContext);
469 |
470 | // --- Assert
471 | expect(evalContext.mainThread!.blocks!.length).equal(1);
472 | expect(evalContext.localContext.x).equal(2);
473 |
474 | expect(diag.processedStatements).equal(4);
475 | expect(diag.maxLoops).equal(0);
476 | expect(diag.maxBlocks).equal(2);
477 | expect(diag.maxQueueLength).equal(2);
478 | expect(diag.clearToLabels).equal(0);
479 | expect(diag.unshiftedItems).equal(3);
480 | });
481 |
482 | it("while statement #1", async () => {
483 | // --- Arrange
484 | const source = "while (x < 3) x++;";
485 | const evalContext = createEvalContext({
486 | localContext: {
487 | x: 0,
488 | },
489 | });
490 | const statements = parseStatements(source);
491 |
492 | // --- Act
493 | const diag = await processStatementQueueAsync(statements, evalContext);
494 |
495 | // --- Assert
496 | expect(evalContext.mainThread!.blocks!.length).equal(1);
497 | expect(evalContext.localContext.x).equal(3);
498 |
499 | expect(diag.processedStatements).equal(7);
500 | expect(diag.maxLoops).equal(1);
501 | expect(diag.maxBlocks).equal(1);
502 | expect(diag.maxQueueLength).equal(2);
503 | expect(diag.clearToLabels).equal(0);
504 | expect(diag.unshiftedItems).equal(6);
505 | });
506 |
507 | it("while statement #2", async () => {
508 | // --- Arrange
509 | const source = "let x = 0; while (x < 3) x++;";
510 | const evalContext = createEvalContext({
511 | localContext: {},
512 | });
513 | const statements = parseStatements(source);
514 |
515 | // --- Act
516 | const diag = await processStatementQueueAsync(statements, evalContext);
517 |
518 | // --- Assert
519 | const thread = evalContext.mainThread!;
520 | expect(thread.blocks!.length).equal(1);
521 | expect(thread.blocks![0].vars.x).equal(3);
522 |
523 | expect(diag.processedStatements).equal(8);
524 | expect(diag.maxLoops).equal(1);
525 | expect(diag.maxBlocks).equal(1);
526 | expect(diag.maxQueueLength).equal(2);
527 | expect(diag.clearToLabels).equal(0);
528 | expect(diag.unshiftedItems).equal(6);
529 | });
530 |
531 | it("while statement #3", async () => {
532 | // --- Arrange
533 | const source = "let x = 0; while (x < 8) {let y = 2; x += y;}";
534 | const evalContext = createEvalContext({
535 | localContext: {},
536 | });
537 | const statements = parseStatements(source);
538 |
539 | // --- Act
540 | const diag = await processStatementQueueAsync(statements, evalContext);
541 |
542 | // --- Assert
543 | const thread = evalContext.mainThread!;
544 | expect(thread.blocks!.length).equal(1);
545 | expect(thread.blocks![0].vars.x).equal(8);
546 |
547 | expect(diag.processedStatements).equal(22);
548 | expect(diag.maxLoops).equal(1);
549 | expect(diag.maxBlocks).equal(2);
550 | expect(diag.maxQueueLength).equal(4);
551 | expect(diag.clearToLabels).equal(0);
552 | expect(diag.unshiftedItems).equal(20);
553 | });
554 |
555 | it("while statement #4", async () => {
556 | // --- Arrange
557 | const source = "let x = 0; while (x < 18) {let y = 0; while (y < 3) {x += y; y++;} }";
558 | const evalContext = createEvalContext({
559 | localContext: {},
560 | });
561 | const statements = parseStatements(source);
562 |
563 | // --- Act
564 | const diag = await processStatementQueueAsync(statements, evalContext);
565 |
566 | // --- Assert
567 | const thread = evalContext.mainThread!;
568 | expect(thread.blocks!.length).equal(1);
569 | expect(thread.blocks![0].vars.x).equal(18);
570 |
571 | expect(diag.processedStatements).equal(122);
572 | expect(diag.maxLoops).equal(2);
573 | expect(diag.maxBlocks).equal(3);
574 | expect(diag.maxQueueLength).equal(6);
575 | expect(diag.clearToLabels).equal(0);
576 | expect(diag.unshiftedItems).equal(120);
577 | });
578 |
579 | it("while with break #1", async () => {
580 | // --- Arrange
581 | const source = "let x = 0; while (true) {x++ ; if (x > 3) break;}";
582 | const evalContext = createEvalContext({
583 | localContext: {},
584 | });
585 | const statements = parseStatements(source);
586 |
587 | // --- Act
588 | const diag = await processStatementQueueAsync(statements, evalContext);
589 |
590 | // --- Assert
591 | const thread = evalContext.mainThread!;
592 | expect(thread.blocks!.length).equal(1);
593 | expect(thread.blocks![0].vars.x).equal(4);
594 |
595 | expect(diag.processedStatements).equal(21);
596 | expect(diag.maxLoops).equal(1);
597 | expect(diag.maxBlocks).equal(2);
598 | expect(diag.maxQueueLength).equal(4);
599 | expect(diag.clearToLabels).equal(1);
600 | expect(diag.unshiftedItems).equal(21);
601 | });
602 |
603 | it("while with break #2", async () => {
604 | // --- Arrange
605 | const source = "let x = 0; while (true) {x++ ; if (x > 3) break;}; x++";
606 | const evalContext = createEvalContext({
607 | localContext: {},
608 | });
609 | const statements = parseStatements(source);
610 |
611 | // --- Act
612 | const diag = await processStatementQueueAsync(statements, evalContext);
613 |
614 | // --- Assert
615 | const thread = evalContext.mainThread!;
616 | expect(thread.blocks!.length).equal(1);
617 | expect(thread.blocks![0].vars.x).equal(5);
618 |
619 | expect(diag.processedStatements).equal(22);
620 | expect(diag.maxLoops).equal(1);
621 | expect(diag.maxBlocks).equal(2);
622 | expect(diag.maxQueueLength).equal(5);
623 | expect(diag.clearToLabels).equal(1);
624 | expect(diag.unshiftedItems).equal(21);
625 | });
626 |
627 | it("while with continue #1", async () => {
628 | // --- Arrange
629 | const source = "let y = 0; let x = 0; while (x < 6) {x++; if (x == 3) continue; y += x; }";
630 | const evalContext = createEvalContext({
631 | localContext: {},
632 | });
633 | const statements = parseStatements(source);
634 |
635 | // --- Act
636 | const diag = await processStatementQueueAsync(statements, evalContext);
637 |
638 | // --- Assert
639 | const thread = evalContext.mainThread!;
640 | expect(thread.blocks!.length).equal(1);
641 | expect(thread.blocks![0].vars.y).equal(18);
642 |
643 | expect(diag.processedStatements).equal(38);
644 | expect(diag.maxLoops).equal(1);
645 | expect(diag.maxBlocks).equal(2);
646 | expect(diag.maxQueueLength).equal(5);
647 | expect(diag.clearToLabels).equal(1);
648 | expect(diag.unshiftedItems).equal(37);
649 | });
650 |
651 | it("do-while statement #1", async () => {
652 | // --- Arrange
653 | const source = "do x++; while (x < 3)";
654 | const evalContext = createEvalContext({
655 | localContext: {
656 | x: 0,
657 | },
658 | });
659 | const statements = parseStatements(source);
660 |
661 | // --- Act
662 | const diag = await processStatementQueueAsync(statements, evalContext);
663 |
664 | // --- Assert
665 | const thread = evalContext.mainThread!;
666 | expect(thread.blocks!.length).equal(1);
667 | expect(evalContext.localContext.x).equal(3);
668 |
669 | expect(diag.processedStatements).equal(7);
670 | expect(diag.maxLoops).equal(1);
671 | expect(diag.maxBlocks).equal(1);
672 | expect(diag.maxQueueLength).equal(2);
673 | expect(diag.clearToLabels).equal(0);
674 | expect(diag.unshiftedItems).equal(6);
675 | });
676 |
677 | it("do-while statement #2", async () => {
678 | // --- Arrange
679 | const source = "do x++; while (x < 0)";
680 | const evalContext = createEvalContext({
681 | localContext: {
682 | x: 0,
683 | },
684 | });
685 | const statements = parseStatements(source);
686 |
687 | // --- Act
688 | const diag = await processStatementQueueAsync(statements, evalContext);
689 |
690 | // --- Assert
691 | expect(evalContext.mainThread!.blocks!.length).equal(1);
692 | expect(evalContext.localContext.x).equal(1);
693 |
694 | expect(diag.processedStatements).equal(3);
695 | expect(diag.maxLoops).equal(1);
696 | expect(diag.maxBlocks).equal(1);
697 | expect(diag.maxQueueLength).equal(2);
698 | expect(diag.clearToLabels).equal(0);
699 | expect(diag.unshiftedItems).equal(2);
700 | });
701 |
702 | it("do-while statement #3", async () => {
703 | // --- Arrange
704 | const source = "do { x++;} while (x < 3)";
705 | const evalContext = createEvalContext({
706 | localContext: {
707 | x: 0,
708 | },
709 | });
710 | const statements = parseStatements(source);
711 |
712 | // --- Act
713 | const diag = await processStatementQueueAsync(statements, evalContext);
714 |
715 | // --- Assert
716 | expect(evalContext.mainThread!.blocks!.length).equal(1);
717 | expect(evalContext.localContext.x).equal(3);
718 |
719 | expect(diag.processedStatements).equal(13);
720 | expect(diag.maxLoops).equal(1);
721 | expect(diag.maxBlocks).equal(2);
722 | expect(diag.maxQueueLength).equal(3);
723 | expect(diag.clearToLabels).equal(0);
724 | expect(diag.unshiftedItems).equal(12);
725 | });
726 |
727 | it("do-while statement #4", async () => {
728 | // --- Arrange
729 | const source = "let x = 0; do {let y = 2; x += y;} while (x < 8) ";
730 | const evalContext = createEvalContext({
731 | localContext: {},
732 | });
733 | const statements = parseStatements(source);
734 |
735 | // --- Act
736 | const diag = await processStatementQueueAsync(statements, evalContext);
737 |
738 | // --- Assert
739 | const thread = evalContext.mainThread!;
740 | expect(thread.blocks!.length).equal(1);
741 | expect(thread.blocks![0].vars.x).equal(8);
742 |
743 | expect(diag.processedStatements).equal(22);
744 | expect(diag.maxLoops).equal(1);
745 | expect(diag.maxBlocks).equal(2);
746 | expect(diag.maxQueueLength).equal(4);
747 | expect(diag.clearToLabels).equal(0);
748 | expect(diag.unshiftedItems).equal(20);
749 | });
750 |
751 | it("do-while statement #5", async () => {
752 | // --- Arrange
753 | const source = "let x = 0; do {let y = 0; while (y < 3) {x += y; y++;} } while (x < 18)";
754 | const evalContext = createEvalContext({
755 | localContext: {},
756 | });
757 | const statements = parseStatements(source);
758 |
759 | // --- Act
760 | const diag = await processStatementQueueAsync(statements, evalContext);
761 |
762 | // --- Assert
763 | const thread = evalContext.mainThread!;
764 | expect(thread.blocks!.length).equal(1);
765 | expect(thread.blocks![0].vars.x).equal(18);
766 |
767 | expect(diag.processedStatements).equal(122);
768 | expect(diag.maxLoops).equal(2);
769 | expect(diag.maxBlocks).equal(3);
770 | expect(diag.maxQueueLength).equal(6);
771 | expect(diag.clearToLabels).equal(0);
772 | expect(diag.unshiftedItems).equal(120);
773 | });
774 |
775 | it("do-while with break #1", async () => {
776 | // --- Arrange
777 | const source = "let x = 0; do {x++ ; if (x > 3) break;} while (true)";
778 | const evalContext = createEvalContext({
779 | localContext: {},
780 | });
781 | const statements = parseStatements(source);
782 |
783 | // --- Act
784 | const diag = await processStatementQueueAsync(statements, evalContext);
785 |
786 | // --- Assert
787 | const thread = evalContext.mainThread!;
788 | expect(thread.blocks!.length).equal(1);
789 | expect(thread.blocks![0].vars.x).equal(4);
790 |
791 | expect(diag.processedStatements).equal(21);
792 | expect(diag.maxLoops).equal(1);
793 | expect(diag.maxBlocks).equal(2);
794 | expect(diag.maxQueueLength).equal(4);
795 | expect(diag.clearToLabels).equal(1);
796 | expect(diag.unshiftedItems).equal(21);
797 | });
798 |
799 | it("do-while with continue #1", async () => {
800 | // --- Arrange
801 | const source = "let y = 0; let x = 0; do {x++; if (x == 3) continue; y += x; } while (x < 6)";
802 | const evalContext = createEvalContext({
803 | localContext: {},
804 | });
805 | const statements = parseStatements(source);
806 |
807 | // --- Act
808 | const diag = await processStatementQueueAsync(statements, evalContext);
809 |
810 | // --- Assert
811 | const thread = evalContext.mainThread!;
812 | expect(thread.blocks!.length).equal(1);
813 | expect(thread.blocks![0].vars.y).equal(18);
814 |
815 | expect(diag.processedStatements).equal(38);
816 | expect(diag.maxLoops).equal(1);
817 | expect(diag.maxBlocks).equal(2);
818 | expect(diag.maxQueueLength).equal(5);
819 | expect(diag.clearToLabels).equal(1);
820 | expect(diag.unshiftedItems).equal(37);
821 | });
822 |
823 | it("for-loop #1", async () => {
824 | // --- Arrange
825 | const source = "let y = 0; for (let i = 0; i < 4; i++) y += i;";
826 | const evalContext = createEvalContext({
827 | localContext: {},
828 | });
829 | const statements = parseStatements(source);
830 |
831 | // --- Act
832 | const diag = await processStatementQueueAsync(statements, evalContext);
833 |
834 | // --- Assert
835 | const thread = evalContext.mainThread!;
836 | expect(thread.blocks!.length).equal(1);
837 | expect(thread.blocks![0].vars.y).equal(6);
838 |
839 | expect(diag.processedStatements).equal(16);
840 | expect(diag.maxLoops).equal(1);
841 | expect(diag.maxBlocks).equal(2);
842 | expect(diag.maxQueueLength).equal(3);
843 | expect(diag.clearToLabels).equal(0);
844 | expect(diag.unshiftedItems).equal(14);
845 | });
846 |
847 | it("for-loop #2", async () => {
848 | // --- Arrange
849 | const source = "let y = 0; for (let i = 0; i < 4; i++) {y += i;}";
850 | const evalContext = createEvalContext({
851 | localContext: {},
852 | });
853 | const statements = parseStatements(source);
854 |
855 | // --- Act
856 | const diag = await processStatementQueueAsync(statements, evalContext);
857 |
858 | // --- Assert
859 | const thread = evalContext.mainThread!;
860 | expect(thread.blocks!.length).equal(1);
861 | expect(thread.blocks![0].vars.y).equal(6);
862 |
863 | expect(diag.processedStatements).equal(24);
864 | expect(diag.maxLoops).equal(1);
865 | expect(diag.maxBlocks).equal(3);
866 | expect(diag.maxQueueLength).equal(4);
867 | expect(diag.clearToLabels).equal(0);
868 | expect(diag.unshiftedItems).equal(22);
869 | });
870 |
871 | it("for-loop #3", async () => {
872 | // --- Arrange
873 | const source = "let y = 0; for (let i = 0; i < 4; i++) {y += i;}; y++";
874 | const evalContext = createEvalContext({
875 | localContext: {},
876 | });
877 | const statements = parseStatements(source);
878 |
879 | // --- Act
880 | const diag = await processStatementQueueAsync(statements, evalContext);
881 |
882 | // --- Assert
883 | const thread = evalContext.mainThread!;
884 | expect(thread.blocks!.length).equal(1);
885 | expect(thread.blocks![0].vars.y).equal(7);
886 |
887 | expect(diag.processedStatements).equal(25);
888 | expect(diag.maxLoops).equal(1);
889 | expect(diag.maxBlocks).equal(3);
890 | expect(diag.maxQueueLength).equal(5);
891 | expect(diag.clearToLabels).equal(0);
892 | expect(diag.unshiftedItems).equal(22);
893 | });
894 |
895 | it("for-loop #4", async () => {
896 | // --- Arrange
897 | const source = "let y = 0; for (let i = 0, j = 0; i < 4; i++, j+=2) {y += i + j}";
898 | const evalContext = createEvalContext({
899 | localContext: {},
900 | });
901 | const statements = parseStatements(source);
902 |
903 | // --- Act
904 | const diag = await processStatementQueueAsync(statements, evalContext);
905 |
906 | // --- Assert
907 | const thread = evalContext.mainThread!;
908 | expect(thread.blocks!.length).equal(1);
909 | expect(thread.blocks![0].vars.y).equal(18);
910 |
911 | expect(diag.processedStatements).equal(24);
912 | expect(diag.maxLoops).equal(1);
913 | expect(diag.maxBlocks).equal(3);
914 | expect(diag.maxQueueLength).equal(4);
915 | expect(diag.clearToLabels).equal(0);
916 | expect(diag.unshiftedItems).equal(22);
917 | });
918 |
919 | it("for-loop #5", async () => {
920 | // --- Arrange
921 | const source = "let y = 0; let i = 0; for (; i < 4; i++) {y += i}";
922 | const evalContext = createEvalContext({
923 | localContext: {},
924 | });
925 | const statements = parseStatements(source);
926 |
927 | // --- Act
928 | const diag = await processStatementQueueAsync(statements, evalContext);
929 |
930 | // --- Assert
931 | const thread = evalContext.mainThread!;
932 | expect(thread.blocks!.length).equal(1);
933 | expect(thread.blocks![0].vars.y).equal(6);
934 |
935 | expect(diag.processedStatements).equal(24);
936 | expect(diag.maxLoops).equal(1);
937 | expect(diag.maxBlocks).equal(3);
938 | expect(diag.maxQueueLength).equal(4);
939 | expect(diag.clearToLabels).equal(0);
940 | expect(diag.unshiftedItems).equal(21);
941 | });
942 |
943 | it("for-loop with continue", async () => {
944 | // --- Arrange
945 | const source = "let y = 0; for (let i = 0; i < 10; i++) {if (i % 3 === 0) continue; y += i; }";
946 | const evalContext = createEvalContext({
947 | localContext: {},
948 | });
949 | const statements = parseStatements(source);
950 |
951 | // --- Act
952 | const diag = await processStatementQueueAsync(statements, evalContext);
953 |
954 | // --- Assert
955 | const thread = evalContext.mainThread!;
956 | expect(thread.blocks!.length).equal(1);
957 | expect(thread.blocks![0].vars.y).equal(27);
958 |
959 | expect(diag.processedStatements).equal(60);
960 | expect(diag.maxLoops).equal(1);
961 | expect(diag.maxBlocks).equal(3);
962 | expect(diag.maxQueueLength).equal(5);
963 | expect(diag.clearToLabels).equal(4);
964 | expect(diag.unshiftedItems).equal(66);
965 | });
966 |
967 | it("for-loop #6", async () => {
968 | // --- Arrange
969 | const source = "let y = 0; for (let i = 0; i < 4; i++) { break; }; y++";
970 | const evalContext = createEvalContext({
971 | localContext: {},
972 | });
973 | const statements = parseStatements(source);
974 |
975 | // --- Act
976 | const diag = await processStatementQueueAsync(statements, evalContext);
977 |
978 | // --- Assert
979 | const thread = evalContext.mainThread!;
980 | expect(thread.blocks!.length).equal(1);
981 | expect(thread.blocks![0].vars.y).equal(1);
982 |
983 | expect(diag.processedStatements).equal(7);
984 | expect(diag.maxLoops).equal(1);
985 | expect(diag.maxBlocks).equal(3);
986 | expect(diag.maxQueueLength).equal(5);
987 | expect(diag.clearToLabels).equal(1);
988 | expect(diag.unshiftedItems).equal(7);
989 | });
990 |
991 | it("Arrow function body #1", async () => {
992 | // --- Arrange
993 | const source = "(() => {return 2})()";
994 | const evalContext = createEvalContext({
995 | localContext: {},
996 | });
997 | const statements = parseStatements(source);
998 |
999 | // --- Act
1000 | const diag = await processStatementQueueAsync(statements, evalContext);
1001 |
1002 | // --- Assert
1003 | const thread = evalContext.mainThread!;
1004 | expect(thread.blocks!.length).equal(1);
1005 | expect(thread.blocks![0].returnValue).equal(2);
1006 |
1007 | expect(diag.processedStatements).equal(1);
1008 | expect(diag.maxLoops).equal(0);
1009 | expect(diag.maxBlocks).equal(1);
1010 | expect(diag.maxQueueLength).equal(1);
1011 | expect(diag.clearToLabels).equal(0);
1012 | expect(diag.unshiftedItems).equal(0);
1013 | });
1014 |
1015 | it("Arrow function body #2", async () => {
1016 | // --- Arrange
1017 | const source = "let arr = () => {return 2}; let x = arr();";
1018 | const evalContext = createEvalContext({
1019 | localContext: {},
1020 | });
1021 | const statements = parseStatements(source);
1022 |
1023 | // --- Act
1024 | const diag = await processStatementQueueAsync(statements, evalContext);
1025 |
1026 | // --- Assert
1027 | const thread = evalContext.mainThread!;
1028 | expect(thread.blocks!.length).equal(1);
1029 | expect(thread.blocks![0].vars.x).equal(2);
1030 |
1031 | expect(diag.processedStatements).equal(2);
1032 | expect(diag.maxLoops).equal(0);
1033 | expect(diag.maxBlocks).equal(1);
1034 | expect(diag.maxQueueLength).equal(2);
1035 | expect(diag.clearToLabels).equal(0);
1036 | expect(diag.unshiftedItems).equal(0);
1037 | });
1038 |
1039 | it("Arrow function body #3", async () => {
1040 | // --- Arrange
1041 | const source =
1042 | "let arr = (x, y) => { let sum = 0; for (let i = x; i <= y; i++) sum+= i; return sum }; arr(1, 5);";
1043 | const evalContext = createEvalContext({
1044 | localContext: {},
1045 | });
1046 | const statements = parseStatements(source);
1047 |
1048 | // --- Act
1049 | const diag = await processStatementQueueAsync(statements, evalContext);
1050 |
1051 | // --- Assert
1052 | const thread = evalContext.mainThread!;
1053 | expect(thread.blocks!.length).equal(1);
1054 | expect(thread.blocks![0].returnValue).equal(15);
1055 |
1056 | expect(diag.processedStatements).equal(2);
1057 | expect(diag.maxLoops).equal(0);
1058 | expect(diag.maxBlocks).equal(1);
1059 | expect(diag.maxQueueLength).equal(2);
1060 | expect(diag.clearToLabels).equal(0);
1061 | expect(diag.unshiftedItems).equal(0);
1062 | });
1063 |
1064 | it("Arrow function body #4", async () => {
1065 | // --- Arrange
1066 | const source =
1067 | "let arr = (x, y) => { let sum = 0; for (let i = x; i <= y; i++) sum+= i; return sum }; z = arr(1, 5);";
1068 | const evalContext = createEvalContext({
1069 | localContext: {
1070 | z: 0,
1071 | },
1072 | });
1073 | const statements = parseStatements(source);
1074 |
1075 | // --- Act
1076 | const diag = await processStatementQueueAsync(statements, evalContext);
1077 |
1078 | // --- Assert
1079 | const thread = evalContext.mainThread!;
1080 | expect(thread.blocks!.length).equal(1);
1081 | expect(evalContext.localContext.z).equal(15);
1082 | expect(thread.blocks![0].returnValue).equal(15);
1083 |
1084 | expect(diag.processedStatements).equal(2);
1085 | expect(diag.maxLoops).equal(0);
1086 | expect(diag.maxBlocks).equal(1);
1087 | expect(diag.maxQueueLength).equal(2);
1088 | expect(diag.clearToLabels).equal(0);
1089 | expect(diag.unshiftedItems).equal(0);
1090 | });
1091 |
1092 | it("return #1", async () => {
1093 | // --- Arrange
1094 | const source = "return 123";
1095 | const evalContext = createEvalContext({});
1096 | const statements = parseStatements(source);
1097 |
1098 | // --- Act
1099 | const diag = await processStatementQueueAsync(statements, evalContext);
1100 |
1101 | // --- Assert
1102 | const thread = evalContext.mainThread!;
1103 | expect(thread.blocks!.length).equal(1);
1104 | expect(thread.returnValue).equal(123);
1105 |
1106 | expect(diag.processedStatements).equal(1);
1107 | expect(diag.maxLoops).equal(0);
1108 | expect(diag.maxBlocks).equal(1);
1109 | expect(diag.maxQueueLength).equal(1);
1110 | expect(diag.clearToLabels).equal(1);
1111 | expect(diag.unshiftedItems).equal(0);
1112 | });
1113 |
1114 | it("return #2", async () => {
1115 | // --- Arrange
1116 | const source = "x = 1; return 123; x = 2";
1117 | const evalContext = createEvalContext({
1118 | localContext: {
1119 | x: 0,
1120 | },
1121 | });
1122 | const statements = parseStatements(source);
1123 |
1124 | // --- Act
1125 | const diag = await processStatementQueueAsync(statements, evalContext);
1126 |
1127 | // --- Assert
1128 | const thread = evalContext.mainThread!;
1129 | expect(thread.blocks!.length).equal(1);
1130 | expect(evalContext.localContext.x).equal(1);
1131 | expect(thread.returnValue).equal(123);
1132 |
1133 | expect(diag.processedStatements).equal(2);
1134 | expect(diag.maxLoops).equal(0);
1135 | expect(diag.maxBlocks).equal(1);
1136 | expect(diag.maxQueueLength).equal(3);
1137 | expect(diag.clearToLabels).equal(1);
1138 | expect(diag.unshiftedItems).equal(0);
1139 | });
1140 |
1141 | it("return #3", async () => {
1142 | // --- Arrange
1143 | const source = "return";
1144 | const evalContext = createEvalContext({});
1145 | const statements = parseStatements(source);
1146 |
1147 | // --- Act
1148 | const diag = await processStatementQueueAsync(statements, evalContext);
1149 |
1150 | // --- Assert
1151 | const thread = evalContext.mainThread!;
1152 | expect(thread.blocks!.length).equal(1);
1153 | expect(thread.returnValue).equal(undefined);
1154 |
1155 | expect(diag.processedStatements).equal(1);
1156 | expect(diag.maxLoops).equal(0);
1157 | expect(diag.maxBlocks).equal(1);
1158 | expect(diag.maxQueueLength).equal(1);
1159 | expect(diag.clearToLabels).equal(1);
1160 | expect(diag.unshiftedItems).equal(0);
1161 | });
1162 |
1163 | it("Assign to unknown object property", async () => {
1164 | // --- Arrange
1165 | const source = "const obj = {}; obj.someValue = 42;";
1166 | const evalContext = createEvalContext({});
1167 | const statements = parseStatements(source);
1168 |
1169 | // --- Act
1170 | const diag = await processStatementQueueAsync(statements, evalContext);
1171 |
1172 | // --- Assert
1173 | const thread = evalContext.mainThread!;
1174 | expect(thread.blocks!.length).equal(1);
1175 | expect(thread.blocks![0].vars.obj).eql({ someValue: 42 });
1176 | expect(thread.blocks![0].constVars!.has("obj")).equal(true);
1177 |
1178 | expect(diag.processedStatements).equal(2);
1179 | expect(diag.maxLoops).equal(0);
1180 | expect(diag.maxBlocks).equal(1);
1181 | expect(diag.maxQueueLength).equal(2);
1182 | expect(diag.clearToLabels).equal(0);
1183 | expect(diag.unshiftedItems).equal(0);
1184 | });
1185 |
1186 | it("Read-only write #1", async () => {
1187 | // --- Arrange
1188 | const source = "$x = 3";
1189 | const evalContext = createEvalContext({
1190 | localContext: getComponentStateClone({
1191 | $x: 0,
1192 | }),
1193 | });
1194 | const statements = parseStatements(source);
1195 |
1196 | // --- Act
1197 | try {
1198 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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 ", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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 ", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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 ", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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", async () => {
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 | await processStatementQueueAsync(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 ", async () => {
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 | await processStatementQueueAsync(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 | it("template literal regression", async () => {
2005 | // --- Arrange
2006 |
2007 | const source = `
2008 | return \`f\${ obj.map(item => item) }\`;
2009 | `;
2010 |
2011 | const evalContext = createEvalContext({
2012 | localContext: {
2013 | obj: [1, 2, 3],
2014 | },
2015 | });
2016 | const statements = parseStatements(source);
2017 |
2018 | // --- Act/Assert
2019 | await processStatementQueueAsync(statements, evalContext);
2020 | const thread = evalContext.mainThread!;
2021 | expect(thread.returnValue).equal("f1,2,3");
2022 | });
2023 | });
2024 |
2025 | function getComponentStateClone(orig: any): any {
2026 | const poj = structuredClone(orig);
2027 | return buildProxy(poj, (changeInfo) => {
2028 | const idRoot = changeInfo.pathArray?.[0];
2029 | if (idRoot?.toString()?.startsWith("$")) {
2030 | throw new Error("Cannot update a read-only variable");
2031 | }
2032 | });
2033 | }
2034 |
```