Compare commits

...

39 Commits

Author SHA1 Message Date
1af8a8c64f Cut release v0.9.5 (#772) 2023-10-03 17:35:16 -07:00
eb4776826b disable pip for firefox (#770)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-10-03 15:11:44 -07:00
f3dd0469d5 re-execute when we remount the app (#769)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-10-03 15:07:09 -07:00
deea74754d save actual file contents (#768)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-10-03 15:06:45 -07:00
3fd798c704 Bump @adobe/css-tools from 4.2.0 to 4.3.1 (#353)
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.2.0 to 4.3.1.
- [Changelog](https://github.com/adobe/css-tools/blob/main/History.md)
- [Commits](https://github.com/adobe/css-tools/commits)

---
updated-dependencies:
- dependency-name: "@adobe/css-tools"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2023-10-03 14:12:58 -05:00
cc9eaf2991 Bump get-func-name from 2.0.0 to 2.0.2 (#730)
Bumps [get-func-name](https://github.com/chaijs/get-func-name) from 2.0.0 to 2.0.2.
- [Release notes](https://github.com/chaijs/get-func-name/releases)
- [Commits](https://github.com/chaijs/get-func-name/commits/v2.0.2)

---
updated-dependencies:
- dependency-name: get-func-name
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 14:12:46 -05:00
6f24031220 add mit (#765)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-10-03 11:59:57 -07:00
672bcd297f Bump toml from 0.8.1 to 0.8.2 in /src-tauri (#760)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.1 to 0.8.2.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.1...toml-v0.8.2)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 07:20:21 -07:00
3bc182fe16 Bump reqwest from 0.11.20 to 0.11.21 in /src/wasm-lib (#762)
Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.20 to 0.11.21.
- [Release notes](https://github.com/seanmonstar/reqwest/releases)
- [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/seanmonstar/reqwest/compare/v0.11.20...v0.11.21)

---
updated-dependencies:
- dependency-name: reqwest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 07:20:08 -07:00
589cd39eec Cut release v0.9.4 (#759)
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2023-10-02 20:09:53 -04:00
63feebef5c add report a bug button (#758)
* add report a bug button

* format
2023-10-02 16:33:33 -07:00
65037abd9a new sample code w tangental arc (#756)
* new sample code w tangental arc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* line 6

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* make sure sample code works in test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-10-02 16:14:09 -07:00
97bc339a62 Bump tauri-plugin-fs-extra from 9af4c37 to 9b96996 in /src-tauri (#751)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `9af4c37` to `9b96996`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](9af4c3727c...9b96996b5a)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 12:27:24 -07:00
4e9a6375a5 Bump tauri-build from 1.4.1 to 1.5.0 in /src-tauri (#752)
Bumps [tauri-build](https://github.com/tauri-apps/tauri) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-build-v1.4.1...tauri-build-v1.5)

---
updated-dependencies:
- dependency-name: tauri-build
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 12:27:16 -07:00
3d19dfb800 Cut release v0.9.3 (#753) 2023-10-02 14:14:00 -04:00
d2a7b84292 Request a feature should open externally (#737)
Fixes #659
2023-10-02 13:26:23 -04:00
9e02bab155 Explicitly close the Engine Connection when ICE fails (#732)
This will avoid letting the stack think its ready until it times out,
and will hopefully help with faster retry logic in the future

Signed-off-by: Paul Tagliamonte <paul@kittycad.io>
2023-10-02 09:50:49 -04:00
7352de5a70 Bump vitest from 0.34.1 to 0.34.6 (#747)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 0.34.1 to 0.34.6.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v0.34.6/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-30 12:24:39 +10:00
9797d0cb81 Fix pipe expression start (#746) 2023-09-29 22:19:20 -04:00
83907fa9db adds tangentalArc and tangentalArcTo to the stdlib (#748)
* start of tangental arc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 14:41:14 -07:00
a367be4e2b add gizmo (#738)
* add gizmo

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix force ast execution

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 12:41:58 -07:00
056fa00adc Bump tauri from 1.4.1 to 1.5.0 in /src-tauri (#742)
Bumps [tauri](https://github.com/tauri-apps/tauri) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-v1.4.1...tauri-v1.5.0)

---
updated-dependencies:
- dependency-name: tauri
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 12:03:35 -07:00
4759fb2e6f Bump postcss from 8.4.27 to 8.4.31 (#743)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.27 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.27...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:12:08 -07:00
45f497d9cd Bump tauri-build from 1.4.0 to 1.4.1 in /src-tauri (#741)
Bumps [tauri-build](https://github.com/tauri-apps/tauri) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-build-v1.4...tauri-build-v1.4.1)

---
updated-dependencies:
- dependency-name: tauri-build
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:11:57 -07:00
dc61bdebdf Bump tauri-plugin-fs-extra from 3d27909 to 9af4c37 in /src-tauri (#740)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `3d27909` to `9af4c37`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](3d279094d4...9af4c3727c)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 11:11:42 -07:00
61943055e5 refactor a bit before more rust port (#739)
* partially there

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-29 11:11:01 -07:00
416fe0f644 Bump clap from 4.4.5 to 4.4.6 in /src/wasm-lib (#744)
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.5 to 4.4.6.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.4.5...v4.4.6)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-29 12:41:22 -04:00
708465d818 Bump kittycad from 0.2.27 to 0.2.28 in /src-tauri (#734)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.27 to 0.2.28.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.27...v0.2.28)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:56 -07:00
e706fb02d6 Bump openapitor from d3e98c4 to fa0345c in /src/wasm-lib (#733)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `d3e98c4` to `fa0345c`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](d3e98c4ec0...fa0345c514)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:46 -07:00
1bf7daa474 Bump tauri-plugin-fs-extra from 6c7a4c0 to 3d27909 in /src-tauri (#735)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `6c7a4c0` to `3d27909`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](6c7a4c0984...3d279094d4)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-28 18:09:31 -07:00
ffc47f8f40 actually use the units the user sets (#727)
* actually use the units the user sets

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update kittycad lib

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* next

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix bug

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix types

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-27 15:42:16 -07:00
768aaa84f6 Bump clap from 4.4.4 to 4.4.5 in /src/wasm-lib (#711)
Bumps [clap](https://github.com/clap-rs/clap) from 4.4.4 to 4.4.5.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/v4.4.4...v4.4.5)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 09:10:07 -07:00
f3a700eec8 Bump expectorate from 1.0.7 to 1.1.0 in /src/wasm-lib (#712)
Bumps [expectorate](https://github.com/oxidecomputer/expectorate) from 1.0.7 to 1.1.0.
- [Release notes](https://github.com/oxidecomputer/expectorate/releases)
- [Commits](https://github.com/oxidecomputer/expectorate/compare/v1.0.7...v1.1.0)

---
updated-dependencies:
- dependency-name: expectorate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:39:16 -07:00
c853637a9a Bump thiserror from 1.0.48 to 1.0.49 in /src/wasm-lib (#721)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.48 to 1.0.49.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.48...1.0.49)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:39:03 -07:00
9af30d9ef6 Bump kittycad from 0.2.26 to 0.2.27 in /src/wasm-lib (#722)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.26 to 0.2.27.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.26...v0.2.27)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:49 -07:00
6164714a6b Bump openapitor from 61a1605 to d3e98c4 in /src/wasm-lib (#723)
Bumps [openapitor](https://github.com/KittyCAD/kittycad.rs) from `61a1605` to `d3e98c4`.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](61a16059b3...d3e98c4ec0)

---
updated-dependencies:
- dependency-name: openapitor
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:37 -07:00
64ceb98eba Bump toml from 0.8.0 to 0.8.1 in /src-tauri (#724)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.0 to 0.8.1.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.0...toml-v0.8.1)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:25 -07:00
2cbf260900 Bump tauri-plugin-fs-extra from b04bde3 to 6c7a4c0 in /src-tauri (#725)
Bumps [tauri-plugin-fs-extra](https://github.com/tauri-apps/plugins-workspace) from `b04bde3` to `6c7a4c0`.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](b04bde3461...6c7a4c0984)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs-extra
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:38:14 -07:00
cfaaedf602 Bump kittycad from 0.2.26 to 0.2.27 in /src-tauri (#726)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.2.26 to 0.2.27.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.2.26...v0.2.27)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 08:37:54 -07:00
79 changed files with 3393 additions and 646 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2023 The KittyCAD Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,8 @@
* [`sqrt`](#sqrt) * [`sqrt`](#sqrt)
* [`startSketchAt`](#startSketchAt) * [`startSketchAt`](#startSketchAt)
* [`tan`](#tan) * [`tan`](#tan)
* [`tangentalArc`](#tangentalArc)
* [`tangentalArcTo`](#tangentalArcTo)
* [`tau`](#tau) * [`tau`](#tau)
* [`xLine`](#xLine) * [`xLine`](#xLine)
* [`xLineTo`](#xLineTo) * [`xLineTo`](#xLineTo)
@ -3234,6 +3236,320 @@ tan(num: number) -> number
### tangentalArc
Draw an arc.
```
tangentalArc(data: TangentalArcData, sketch_group: SketchGroup) -> SketchGroup
```
#### Arguments
* `data`: `TangentalArcData` - Data to draw a tangental arc.
```
{
// Offset of the arc, in degrees.
offset: number,
// Radius of the arc. Not to be confused with Raiders of the Lost Ark.
radius: number,
} |
{
// The tag.
tag: string,
// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [number],
} |
[number]
```
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
#### Returns
* `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
### tangentalArcTo
Draw an arc.
```
tangentalArcTo(data: TangentalArcToData, sketch_group: SketchGroup) -> SketchGroup
```
#### Arguments
* `data`: `TangentalArcToData` - Data to draw a tangental arc to a specific point.
```
{
// The tag.
tag: string,
// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [number],
} |
[number]
```
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
#### Returns
* `SketchGroup` - A sketch group is a collection of paths.
```
{
// The id of the sketch group.
id: uuid,
// The position of the sketch group.
position: [number],
// The rotation of the sketch group.
rotation: [number],
// The starting path.
start: {
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
},
// The paths in the sketch group.
value: [{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
// The x coordinate.
x: number,
// The y coordinate.
y: number,
} |
{
// The from point.
from: [number],
// The name of the path.
name: string,
// The to point.
to: [number],
type: string,
}],
}
```
### tau ### tau
Return the value of `tau`. The full circle constant (τ). Equal to 2π. Return the value of `tau`. The full circle constant (τ). Equal to 2π.

View File

@ -1,6 +1,6 @@
{ {
"name": "untitled-app", "name": "untitled-app",
"version": "0.9.2", "version": "0.9.5",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.9.0", "@codemirror/autocomplete": "^6.9.0",
@ -10,7 +10,7 @@
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.13", "@headlessui/react": "^1.7.13",
"@headlessui/tailwindcss": "^0.2.0", "@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.39", "@kittycad/lib": "^0.0.40",
"@lezer/javascript": "^1.4.7", "@lezer/javascript": "^1.4.7",
"@open-rpc/client-js": "^1.8.1", "@open-rpc/client-js": "^1.8.1",
"@react-hook/resize-observer": "^1.2.6", "@react-hook/resize-observer": "^1.2.6",
@ -48,7 +48,7 @@
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"typescript": "^4.4.2", "typescript": "^4.4.2",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vitest": "^0.34.1", "vitest": "^0.34.6",
"vscode-jsonrpc": "^8.1.0", "vscode-jsonrpc": "^8.1.0",
"vscode-languageserver-protocol": "^3.17.3", "vscode-languageserver-protocol": "^3.17.3",
"wasm-pack": "^0.12.1", "wasm-pack": "^0.12.1",
@ -116,7 +116,7 @@
"eslint-plugin-css-modules": "^2.11.0", "eslint-plugin-css-modules": "^2.11.0",
"happy-dom": "^10.8.0", "happy-dom": "^10.8.0",
"husky": "^8.0.3", "husky": "^8.0.3",
"postcss": "^8.4.19", "postcss": "^8.4.31",
"prettier": "^2.8.0", "prettier": "^2.8.0",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.2.4",

122
src-tauri/Cargo.lock generated
View File

@ -84,7 +84,7 @@ dependencies = [
"tauri-build", "tauri-build",
"tauri-plugin-fs-extra", "tauri-plugin-fs-extra",
"tokio", "tokio",
"toml 0.8.0", "toml 0.8.2",
] ]
[[package]] [[package]]
@ -1309,7 +1309,21 @@ checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148"
dependencies = [ dependencies = [
"log", "log",
"mac", "mac",
"markup5ever", "markup5ever 0.10.1",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "html5ever"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
dependencies = [
"log",
"mac",
"markup5ever 0.11.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 1.0.109",
@ -1644,9 +1658,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.26" version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2623ee601ce203476229df3f9d3a14664cb43e3f7455e9ac8ed91aacaa6163d" checksum = "35b2f9302648dbb06fd7121687f9505fc3179eba84111a06d76b246e3158f5dc"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1686,7 +1700,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358"
dependencies = [ dependencies = [
"cssparser", "cssparser",
"html5ever", "html5ever 0.25.2",
"matches",
"selectors",
]
[[package]]
name = "kuchikiki"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8"
dependencies = [
"cssparser",
"html5ever 0.26.0",
"indexmap 1.9.3",
"matches", "matches",
"selectors", "selectors",
] ]
@ -1748,9 +1775,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.18" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -1802,7 +1829,21 @@ checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd"
dependencies = [ dependencies = [
"log", "log",
"phf 0.8.0", "phf 0.8.0",
"phf_codegen", "phf_codegen 0.8.0",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "markup5ever"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
dependencies = [
"log",
"phf 0.10.1",
"phf_codegen 0.10.0",
"string_cache", "string_cache",
"string_cache_codegen", "string_cache_codegen",
"tendril", "tendril",
@ -2374,6 +2415,16 @@ dependencies = [
"phf_shared 0.8.0", "phf_shared 0.8.0",
] ]
[[package]]
name = "phf_codegen"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
dependencies = [
"phf_generator 0.10.0",
"phf_shared 0.10.0",
]
[[package]] [[package]]
name = "phf_generator" name = "phf_generator"
version = "0.8.0" version = "0.8.0"
@ -3139,7 +3190,7 @@ dependencies = [
"log", "log",
"matches", "matches",
"phf 0.8.0", "phf 0.8.0",
"phf_codegen", "phf_codegen 0.8.0",
"precomputed-hash", "precomputed-hash",
"servo_arc", "servo_arc",
"smallvec", "smallvec",
@ -3661,9 +3712,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri" name = "tauri"
version = "1.4.1" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" checksum = "72aee3277d0a0df01472cc704ab5934a51a1f25348838df17bfb3c5cb727880c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.2", "base64 0.21.2",
@ -3717,12 +3768,13 @@ dependencies = [
[[package]] [[package]]
name = "tauri-build" name = "tauri-build"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_toml", "cargo_toml",
"dirs-next",
"heck 0.4.1", "heck 0.4.1",
"json-patch", "json-patch",
"semver", "semver",
@ -3730,13 +3782,14 @@ dependencies = [
"serde_json", "serde_json",
"tauri-utils", "tauri-utils",
"tauri-winres", "tauri-winres",
"walkdir",
] ]
[[package]] [[package]]
name = "tauri-codegen" name = "tauri-codegen"
version = "1.4.0" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.2",
"brotli", "brotli",
@ -3760,9 +3813,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-macros" name = "tauri-macros"
version = "1.4.0" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af"
dependencies = [ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
@ -3775,7 +3828,7 @@ dependencies = [
[[package]] [[package]]
name = "tauri-plugin-fs-extra" name = "tauri-plugin-fs-extra"
version = "0.0.0" version = "0.0.0"
source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#b04bde3461066c709d6801cf9ca305cf889a8394" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#9b96996b5a90a6a57d587ce4312975f13a4d8bc2"
dependencies = [ dependencies = [
"log", "log",
"serde", "serde",
@ -3786,9 +3839,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime" name = "tauri-runtime"
version = "0.14.0" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769" checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43"
dependencies = [ dependencies = [
"gtk", "gtk",
"http", "http",
@ -3807,9 +3860,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-runtime-wry" name = "tauri-runtime-wry"
version = "0.14.0" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b" checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895"
dependencies = [ dependencies = [
"cocoa", "cocoa",
"gtk", "gtk",
@ -3827,19 +3880,20 @@ dependencies = [
[[package]] [[package]]
name = "tauri-utils" name = "tauri-utils"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84" checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46"
dependencies = [ dependencies = [
"brotli", "brotli",
"ctor", "ctor",
"dunce", "dunce",
"glob", "glob",
"heck 0.4.1", "heck 0.4.1",
"html5ever", "html5ever 0.26.0",
"infer", "infer",
"json-patch", "json-patch",
"kuchiki", "kuchikiki",
"log",
"memchr", "memchr",
"phf 0.10.1", "phf 0.10.1",
"proc-macro2", "proc-macro2",
@ -4024,14 +4078,14 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.0" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e" checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit 0.20.0", "toml_edit 0.20.2",
] ]
[[package]] [[package]]
@ -4058,9 +4112,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.20.0" version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
dependencies = [ dependencies = [
"indexmap 2.0.0", "indexmap 2.0.0",
"serde", "serde",
@ -4855,9 +4909,9 @@ dependencies = [
[[package]] [[package]]
name = "wry" name = "wry"
version = "0.24.3" version = "0.24.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33748f35413c8a98d45f7a08832d848c0c5915501803d1faade5a4ebcd258cea" checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"block", "block",
@ -4869,7 +4923,7 @@ dependencies = [
"gio", "gio",
"glib", "glib",
"gtk", "gtk",
"html5ever", "html5ever 0.25.2",
"http", "http",
"kuchiki", "kuchiki",
"libc", "libc",

View File

@ -12,18 +12,18 @@ rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies] [build-dependencies]
tauri-build = { version = "1.4.0", features = [] } tauri-build = { version = "1.5.0", features = [] }
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
kittycad = "0.2.26" kittycad = "0.2.28"
oauth2 = "4.4.2" oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
tauri = { version = "1.4.1", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] } tauri = { version = "1.5.0", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tokio = { version = "1.32.0", features = ["time"] } tokio = { version = "1.32.0", features = ["time"] }
toml = "0.8.0" toml = "0.8.2"
[features] [features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.

View File

@ -8,7 +8,7 @@
}, },
"package": { "package": {
"productName": "kittycad-modeling", "productName": "kittycad-modeling",
"version": "0.9.2" "version": "0.9.5"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {

View File

@ -23,10 +23,7 @@ type ActionButtonAsLink = BaseActionButtonProps &
} }
type ActionButtonAsExternal = BaseActionButtonProps & type ActionButtonAsExternal = BaseActionButtonProps &
Omit< Omit<LinkProps, keyof BaseActionButtonProps> & {
React.AnchorHTMLAttributes<HTMLAnchorElement>,
keyof BaseActionButtonProps
> & {
Element: 'externalLink' Element: 'externalLink'
} }
@ -69,12 +66,17 @@ export const ActionButton = (props: ActionButtonProps) => {
) )
} }
case 'externalLink': { case 'externalLink': {
const { Element, icon, children, className, ...rest } = props const { Element, to, icon, children, className, ...rest } = props
return ( return (
<a className={classNames} {...rest}> <Link
to={to || paths.INDEX}
className={classNames}
{...rest}
target="_blank"
>
{icon && <ActionIcon {...icon} />} {icon && <ActionIcon {...icon} />}
{children} {children}
</a> </Link>
) )
} }
default: { default: {

View File

@ -1,7 +1,5 @@
import { useEffect, useState, useRef } from 'react' import { useEffect, useState, useRef } from 'react'
import { parser_wasm } from '../lang/abstractSyntaxTree' import { parse, BinaryPart, Value, executor } from '../lang/wasm'
import { BinaryPart, Value } from '../lang/abstractSyntaxTreeTypes'
import { executor } from '../lang/executor'
import { import {
createIdentifier, createIdentifier,
createLiteral, createLiteral,
@ -140,7 +138,7 @@ export function useCalc({
useEffect(() => { useEffect(() => {
try { try {
const code = `const __result__ = ${value}\nshow(__result__)` const code = `const __result__ = ${value}\nshow(__result__)`
const ast = parser_wasm(code) const ast = parse(code)
const _programMem: any = { root: {}, return: null } const _programMem: any = { root: {}, return: null }
availableVarInfo.variables.forEach(({ key, value }) => { availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] } _programMem.root[key] = { type: 'userVal', value, __meta: [] }

View File

@ -6,8 +6,12 @@ import React from 'react'
import { useFormik } from 'formik' import { useFormik } from 'formik'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
type OutputFormat = Models['OutputFormat_type'] type OutputFormat = Models['OutputFormat_type']
type OutputTypeKey = OutputFormat['type']
type ExtractStorageTypes<T> = T extends { storage: infer U } ? U : never
type StorageUnion = ExtractStorageTypes<OutputFormat>
interface ExportButtonProps extends React.PropsWithChildren { interface ExportButtonProps extends React.PropsWithChildren {
className?: { className?: {
@ -19,9 +23,18 @@ interface ExportButtonProps extends React.PropsWithChildren {
export const ExportButton = ({ children, className }: ExportButtonProps) => { export const ExportButton = ({ children, className }: ExportButtonProps) => {
const [modalIsOpen, setIsOpen] = React.useState(false) const [modalIsOpen, setIsOpen] = React.useState(false)
const {
settings: {
state: {
context: { baseUnit },
},
},
} = useGlobalStateContext()
const defaultType = 'gltf' const defaultType = 'gltf'
const [type, setType] = React.useState(defaultType) const [type, setType] = React.useState<OutputTypeKey>(defaultType)
const defaultStorage = 'embedded'
const [storage, setStorage] = React.useState<StorageUnion>(defaultStorage)
function openModal() { function openModal() {
setIsOpen(true) setIsOpen(true)
@ -34,7 +47,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
// Default to gltf and embedded. // Default to gltf and embedded.
const initialValues: OutputFormat = { const initialValues: OutputFormat = {
type: defaultType, type: defaultType,
storage: 'embedded', storage: defaultStorage,
presentation: 'pretty', presentation: 'pretty',
} }
const formik = useFormik({ const formik = useFormik({
@ -62,6 +75,17 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
}, },
} }
} }
if (values.type === 'obj' || values.type === 'stl') {
values.units = baseUnit
}
if (
values.type === 'ply' ||
values.type === 'stl' ||
values.type === 'gltf'
) {
// Set the storage type.
values.storage = storage
}
engineCommandManager.sendSceneCommand({ engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
cmd: { cmd: {
@ -71,6 +95,7 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
// in the scene to export. In that case, you'd pass the IDs thru here. // in the scene to export. In that case, you'd pass the IDs thru here.
entity_ids: [], entity_ids: [],
format: values, format: values,
source_unit: baseUnit,
}, },
cmd_id: uuidv4(), cmd_id: uuidv4(),
}) })
@ -105,7 +130,17 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
id="type" id="type"
name="type" name="type"
onChange={(e) => { onChange={(e) => {
setType(e.target.value) setType(e.target.value as OutputTypeKey)
if (e.target.value === 'gltf') {
// Set default to embedded.
setStorage('embedded')
} else if (e.target.value === 'ply') {
// Set default to ascii.
setStorage('ascii')
} else if (e.target.value === 'stl') {
// Set default to ascii.
setStorage('ascii')
}
formik.handleChange(e) formik.handleChange(e)
}} }}
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full" className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
@ -123,10 +158,10 @@ export const ExportButton = ({ children, className }: ExportButtonProps) => {
<select <select
id="storage" id="storage"
name="storage" name="storage"
onChange={formik.handleChange} onChange={(e) => {
value={ setStorage(e.target.value as StorageUnion)
'storage' in formik.values ? formik.values.storage : '' formik.handleChange(e)
} }}
className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full" className="bg-chalkboard-20 dark:bg-chalkboard-90 w-full"
> >
{type === 'gltf' && ( {type === 'gltf' && (

View File

@ -1,7 +1,6 @@
import { processMemory } from './MemoryPanel' import { processMemory } from './MemoryPanel'
import { parser_wasm } from '../lang/abstractSyntaxTree'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
import { initPromise } from '../lang/rust' import { initPromise, parse } from '../lang/wasm'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -26,7 +25,7 @@ describe('processMemory', () => {
|> lineTo([2.15, 4.32], %) |> lineTo([2.15, 4.32], %)
// |> rx(90, %) // |> rx(90, %)
show(theExtrude, theSketch)` show(theExtrude, theSketch)`
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast, { const programMemory = await enginelessExecutor(ast, {
root: {}, root: {},
return: null, return: null,

View File

@ -2,7 +2,7 @@ import ReactJson from 'react-json-view'
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel' import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
import { useStore } from '../useStore' import { useStore } from '../useStore'
import { useMemo } from 'react' import { useMemo } from 'react'
import { ProgramMemory, Path, ExtrudeSurface } from '../lang/executor' import { ProgramMemory, Path, ExtrudeSurface } from '../lang/wasm'
import { Themes } from '../lib/theme' import { Themes } from '../lib/theme'
interface MemoryPanelProps extends CollapsiblePanelProps { interface MemoryPanelProps extends CollapsiblePanelProps {

View File

@ -2,6 +2,8 @@ import { fireEvent, render, screen } from '@testing-library/react'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import ProjectSidebarMenu from './ProjectSidebarMenu' import ProjectSidebarMenu from './ProjectSidebarMenu'
import { ProjectWithEntryPointMetadata } from '../Router' import { ProjectWithEntryPointMetadata } from '../Router'
import { GlobalStateProvider } from './GlobalStateProvider'
import CommandBarProvider from './CommandBar'
const now = new Date() const now = new Date()
const projectWellFormed = { const projectWellFormed = {
@ -38,7 +40,11 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders the project name', () => { test('Renders the project name', () => {
render( render(
<BrowserRouter> <BrowserRouter>
<ProjectSidebarMenu project={projectWellFormed} /> <CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu project={projectWellFormed} />
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter> </BrowserRouter>
) )
@ -55,7 +61,11 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders app name if given no project', () => { test('Renders app name if given no project', () => {
render( render(
<BrowserRouter> <BrowserRouter>
<ProjectSidebarMenu /> <CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu />
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter> </BrowserRouter>
) )
@ -69,7 +79,14 @@ describe('ProjectSidebarMenu tests', () => {
test('Renders as a link if set to do so', () => { test('Renders as a link if set to do so', () => {
render( render(
<BrowserRouter> <BrowserRouter>
<ProjectSidebarMenu project={projectWellFormed} renderAsLink={true} /> <CommandBarProvider>
<GlobalStateProvider>
<ProjectSidebarMenu
project={projectWellFormed}
renderAsLink={true}
/>
</GlobalStateProvider>
</CommandBarProvider>
</BrowserRouter> </BrowserRouter>
) )

View File

@ -1,6 +1,6 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTreeTypes' import { Value } from '../lang/wasm'
import { import {
AvailableVars, AvailableVars,
addToInputHelper, addToInputHelper,

View File

@ -1,6 +1,6 @@
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { Value } from '../lang/abstractSyntaxTreeTypes' import { Value } from '../lang/wasm'
import { import {
AvailableVars, AvailableVars,
addToInputHelper, addToInputHelper,

View File

@ -20,11 +20,14 @@ import {
compareVec2Epsilon, compareVec2Epsilon,
} from 'lang/std/sketch' } from 'lang/std/sketch'
import { getNodeFromPath } from 'lang/queryAst' import { getNodeFromPath } from 'lang/queryAst'
import { Program, VariableDeclarator } from 'lang/abstractSyntaxTreeTypes' import {
import { modify_ast_for_sketch } from '../wasm-lib/pkg/wasm_lib' Program,
VariableDeclarator,
rangeTypeFix,
modifyAstForSketch,
} from 'lang/wasm'
import { KCLError } from 'lang/errors' import { KCLError } from 'lang/errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError' import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { rangeTypeFix } from 'lang/abstractSyntaxTree'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
export const Stream = ({ className = '' }) => { export const Stream = ({ className = '' }) => {
@ -249,26 +252,14 @@ export const Stream = ({ className = '' }) => {
let engineId = guiMode.pathId let engineId = guiMode.pathId
try { const updatedAst: Program = await modifyAstForSketch(
const updatedAst: Program = await modify_ast_for_sketch( engineCommandManager,
engineCommandManager, ast,
JSON.stringify(ast), variableName,
variableName, engineId
engineId )
)
updateAst(updatedAst, false) updateAst(updatedAst, false)
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
return return
} }
@ -411,6 +402,7 @@ export const Stream = ({ className = '' }) => {
onWheel={handleScroll} onWheel={handleScroll}
onPlay={() => setIsLoading(false)} onPlay={() => setIsLoading(false)}
onMouseMoveCapture={handleMouseMove} onMouseMoveCapture={handleMouseMove}
disablePictureInPicture
className={`w-full h-full ${isExecuting && 'blur-md'}`} className={`w-full h-full ${isExecuting && 'blur-md'}`}
style={{ transitionDuration: '200ms', transitionProperty: 'filter' }} style={{ transitionDuration: '200ms', transitionProperty: 'filter' }}
/> />

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTreeTypes' import { Value, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTreeTypes' import { Value, VariableDeclarator } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes' import { Value } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise' import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,6 +1,6 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes' import { Value } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise' import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes' import { Value } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise' import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,11 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise' import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { import { BinaryPart, Value, VariableDeclarator } from '../../lang/wasm'
BinaryPart,
Value,
VariableDeclarator,
} from '../../lang/abstractSyntaxTreeTypes'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,
@ -21,8 +17,6 @@ import { GetInfoModal } from '../SetHorVertDistanceModal'
import { createLiteral, createVariableDeclaration } from '../../lang/modifyAst' import { createLiteral, createVariableDeclaration } from '../../lang/modifyAst'
import { removeDoubleNegatives } from '../AvailableVarsHelpers' import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { updateCursors } from '../../lang/util' import { updateCursors } from '../../lang/util'
import { ActionIcon } from 'components/ActionIcon'
import { sketchButtonClassnames } from 'Toolbar'
const getModalInfo = create(GetInfoModal as any) const getModalInfo = create(GetInfoModal as any)

View File

@ -1,7 +1,7 @@
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { create } from 'react-modal-promise' import { create } from 'react-modal-promise'
import { toolTips, useStore } from '../../useStore' import { toolTips, useStore } from '../../useStore'
import { Value } from '../../lang/abstractSyntaxTreeTypes' import { Value } from '../../lang/wasm'
import { import {
getNodePathFromSourceRange, getNodePathFromSourceRange,
getNodeFromPath, getNodeFromPath,

View File

@ -1,6 +1,11 @@
import { Popover, Transition } from '@headlessui/react' import { Popover, Transition } from '@headlessui/react'
import { ActionButton } from './ActionButton' import { ActionButton } from './ActionButton'
import { faBars, faGear, faSignOutAlt } from '@fortawesome/free-solid-svg-icons' import {
faBars,
faBug,
faGear,
faSignOutAlt,
} from '@fortawesome/free-solid-svg-icons'
import { faGithub } from '@fortawesome/free-brands-svg-icons' import { faGithub } from '@fortawesome/free-brands-svg-icons'
import { useLocation, useNavigate } from 'react-router-dom' import { useLocation, useNavigate } from 'react-router-dom'
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
@ -137,13 +142,21 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
Settings Settings
</ActionButton> </ActionButton>
<ActionButton <ActionButton
Element="link" Element="externalLink"
to="https://github.com/KittyCAD/modeling-app/discussions" to="https://github.com/KittyCAD/modeling-app/discussions"
icon={{ icon: faGithub }} icon={{ icon: faGithub }}
className="border-transparent dark:border-transparent dark:hover:border-liquid-60" className="border-transparent dark:border-transparent dark:hover:border-liquid-60"
> >
Request a feature Request a feature
</ActionButton> </ActionButton>
<ActionButton
Element="externalLink"
to="https://github.com/KittyCAD/modeling-app/issues/new"
icon={{ icon: faBug }}
className="border-transparent dark:border-transparent dark:hover:border-liquid-60"
>
Report a bug
</ActionButton>
<ActionButton <ActionButton
Element="button" Element="button"
onClick={() => send('Log out')} onClick={() => send('Log out')}

View File

@ -1,8 +1,9 @@
import { useLayoutEffect, useEffect, useRef } from 'react' import { useLayoutEffect, useEffect, useRef } from 'react'
import { _executor } from '../lang/executor' import { _executor } from '../lang/wasm'
import { useStore } from '../useStore' import { useStore } from '../useStore'
import { engineCommandManager } from '../lang/std/engineConnection' import { engineCommandManager } from '../lang/std/engineConnection'
import { deferExecution } from 'lib/utils' import { deferExecution } from 'lib/utils'
import { v4 as uuidv4 } from 'uuid'
export function useSetupEngineManager( export function useSetupEngineManager(
streamRef: React.RefObject<HTMLDivElement>, streamRef: React.RefObject<HTMLDivElement>,
@ -12,14 +13,14 @@ export function useSetupEngineManager(
setMediaStream, setMediaStream,
setIsStreamReady, setIsStreamReady,
setStreamDimensions, setStreamDimensions,
executeCode,
streamDimensions, streamDimensions,
executeCode,
} = useStore((s) => ({ } = useStore((s) => ({
setMediaStream: s.setMediaStream, setMediaStream: s.setMediaStream,
setIsStreamReady: s.setIsStreamReady, setIsStreamReady: s.setIsStreamReady,
setStreamDimensions: s.setStreamDimensions, setStreamDimensions: s.setStreamDimensions,
executeCode: s.executeCode,
streamDimensions: s.streamDimensions, streamDimensions: s.streamDimensions,
executeCode: s.executeCode,
})) }))
const streamWidth = streamRef?.current?.offsetWidth const streamWidth = streamRef?.current?.offsetWidth
@ -27,6 +28,10 @@ export function useSetupEngineManager(
const hasSetNonZeroDimensions = useRef<boolean>(false) const hasSetNonZeroDimensions = useRef<boolean>(false)
useEffect(() => {
executeCode()
}, [])
useLayoutEffect(() => { useLayoutEffect(() => {
// Load the engine command manager once with the initial width and height, // Load the engine command manager once with the initial width and height,
// then we do not want to reload it. // then we do not want to reload it.
@ -40,11 +45,9 @@ export function useSetupEngineManager(
setIsStreamReady, setIsStreamReady,
width: quadWidth, width: quadWidth,
height: quadHeight, height: quadHeight,
executeCode,
token, token,
}) })
engineCommandManager.waitForReady.then(() => {
executeCode()
})
setStreamDimensions({ setStreamDimensions({
streamWidth: quadWidth, streamWidth: quadWidth,
streamHeight: quadHeight, streamHeight: quadHeight,

View File

@ -1,12 +1,11 @@
import { parser_wasm } from './abstractSyntaxTree'
import { KCLError } from './errors' import { KCLError } from './errors'
import { initPromise } from './rust' import { initPromise, parse } from './wasm'
beforeAll(() => initPromise) beforeAll(() => initPromise)
describe('testing AST', () => { describe('testing AST', () => {
test('5 + 6', () => { test('5 + 6', () => {
const result = parser_wasm('5 +6') const result = parse('5 +6')
delete (result as any).nonCodeMeta delete (result as any).nonCodeMeta
expect(result.body).toEqual([ expect(result.body).toEqual([
{ {
@ -37,7 +36,7 @@ describe('testing AST', () => {
]) ])
}) })
test('const myVar = 5', () => { test('const myVar = 5', () => {
const { body } = parser_wasm('const myVar = 5') const { body } = parse('const myVar = 5')
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -71,7 +70,7 @@ describe('testing AST', () => {
const code = `const myVar = 5 const code = `const myVar = 5
const newVar = myVar + 1 const newVar = myVar + 1
` `
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -143,7 +142,7 @@ const newVar = myVar + 1
describe('testing function declaration', () => { describe('testing function declaration', () => {
test('fn funcN = () => {}', () => { test('fn funcN = () => {}', () => {
const { body } = parser_wasm('fn funcN = () => {}') const { body } = parse('fn funcN = () => {}')
delete (body[0] as any).declarations[0].init.body.nonCodeMeta delete (body[0] as any).declarations[0].init.body.nonCodeMeta
expect(body).toEqual([ expect(body).toEqual([
{ {
@ -179,7 +178,7 @@ describe('testing function declaration', () => {
]) ])
}) })
test('fn funcN = (a, b) => {return a + b}', () => { test('fn funcN = (a, b) => {return a + b}', () => {
const { body } = parser_wasm( const { body } = parse(
['fn funcN = (a, b) => {', ' return a + b', '}'].join('\n') ['fn funcN = (a, b) => {', ' return a + b', '}'].join('\n')
) )
delete (body[0] as any).declarations[0].init.body.nonCodeMeta delete (body[0] as any).declarations[0].init.body.nonCodeMeta
@ -256,7 +255,7 @@ describe('testing function declaration', () => {
test('call expression assignment', () => { test('call expression assignment', () => {
const code = `fn funcN = (a, b) => { return a + b } const code = `fn funcN = (a, b) => { return a + b }
const myVar = funcN(1, 2)` const myVar = funcN(1, 2)`
const { body } = parser_wasm(code) const { body } = parse(code)
delete (body[0] as any).declarations[0].init.body.nonCodeMeta delete (body[0] as any).declarations[0].init.body.nonCodeMeta
expect(body).toEqual([ expect(body).toEqual([
{ {
@ -388,7 +387,7 @@ describe('testing pipe operator special', () => {
|> lineTo([1, 1], %) |> lineTo([1, 1], %)
|> rx(45, %) |> rx(45, %)
` `
const { body } = parser_wasm(code) const { body } = parse(code)
delete (body[0] as any).declarations[0].init.nonCodeMeta delete (body[0] as any).declarations[0].init.nonCodeMeta
expect(body).toEqual([ expect(body).toEqual([
{ {
@ -404,7 +403,7 @@ describe('testing pipe operator special', () => {
id: { type: 'Identifier', start: 6, end: 14, name: 'mySketch' }, id: { type: 'Identifier', start: 6, end: 14, name: 'mySketch' },
init: { init: {
type: 'PipeExpression', type: 'PipeExpression',
start: 15, start: 17,
end: 145, end: 145,
body: [ body: [
{ {
@ -624,7 +623,7 @@ describe('testing pipe operator special', () => {
}) })
test('pipe operator with binary expression', () => { test('pipe operator with binary expression', () => {
let code = `const myVar = 5 + 6 |> myFunc(45, %)` let code = `const myVar = 5 + 6 |> myFunc(45, %)`
const { body } = parser_wasm(code) const { body } = parse(code)
delete (body as any)[0].declarations[0].init.nonCodeMeta delete (body as any)[0].declarations[0].init.nonCodeMeta
expect(body).toEqual([ expect(body).toEqual([
{ {
@ -645,7 +644,7 @@ describe('testing pipe operator special', () => {
}, },
init: { init: {
type: 'PipeExpression', type: 'PipeExpression',
start: 12, start: 14,
end: 36, end: 36,
body: [ body: [
{ {
@ -706,7 +705,7 @@ describe('testing pipe operator special', () => {
}) })
test('array expression', () => { test('array expression', () => {
let code = `const yo = [1, '2', three, 4 + 5]` let code = `const yo = [1, '2', three, 4 + 5]`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -781,7 +780,7 @@ describe('testing pipe operator special', () => {
'const three = 3', 'const three = 3',
"const yo = {aStr: 'str', anum: 2, identifier: three, binExp: 4 + 5}", "const yo = {aStr: 'str', anum: 2, identifier: three, binExp: 4 + 5}",
].join('\n') ].join('\n')
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -925,7 +924,7 @@ describe('testing pipe operator special', () => {
const code = `const yo = {key: { const code = `const yo = {key: {
key2: 'value' key2: 'value'
}}` }}`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -993,7 +992,7 @@ describe('testing pipe operator special', () => {
}) })
test('object expression with array ast', () => { test('object expression with array ast', () => {
const code = `const yo = {key: [1, '2']}` const code = `const yo = {key: [1, '2']}`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -1057,7 +1056,7 @@ describe('testing pipe operator special', () => {
}) })
test('object memberExpression simple', () => { test('object memberExpression simple', () => {
const code = `const prop = yo.one.two` const code = `const prop = yo.one.two`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -1112,7 +1111,7 @@ describe('testing pipe operator special', () => {
}) })
test('object memberExpression with square braces', () => { test('object memberExpression with square braces', () => {
const code = `const prop = yo.one["two"]` const code = `const prop = yo.one["two"]`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -1168,7 +1167,7 @@ describe('testing pipe operator special', () => {
}) })
test('object memberExpression with two square braces literal and identifier', () => { test('object memberExpression with two square braces literal and identifier', () => {
const code = `const prop = yo["one"][two]` const code = `const prop = yo["one"][two]`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body).toEqual([ expect(body).toEqual([
{ {
type: 'VariableDeclaration', type: 'VariableDeclaration',
@ -1227,7 +1226,7 @@ describe('testing pipe operator special', () => {
describe('nests binary expressions correctly', () => { describe('nests binary expressions correctly', () => {
it('works with the simple case', () => { it('works with the simple case', () => {
const code = `const yo = 1 + 2` const code = `const yo = 1 + 2`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body[0]).toEqual({ expect(body[0]).toEqual({
type: 'VariableDeclaration', type: 'VariableDeclaration',
start: 0, start: 0,
@ -1271,7 +1270,7 @@ describe('nests binary expressions correctly', () => {
it('should nest according to precedence with multiply first', () => { it('should nest according to precedence with multiply first', () => {
// should be binExp { binExp { lit-1 * lit-2 } + lit} // should be binExp { binExp { lit-1 * lit-2 } + lit}
const code = `const yo = 1 * 2 + 3` const code = `const yo = 1 * 2 + 3`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body[0]).toEqual({ expect(body[0]).toEqual({
type: 'VariableDeclaration', type: 'VariableDeclaration',
start: 0, start: 0,
@ -1328,7 +1327,7 @@ describe('nests binary expressions correctly', () => {
it('should nest according to precedence with sum first', () => { it('should nest according to precedence with sum first', () => {
// should be binExp { lit-1 + binExp { lit-2 * lit-3 } } // should be binExp { lit-1 + binExp { lit-2 * lit-3 } }
const code = `const yo = 1 + 2 * 3` const code = `const yo = 1 + 2 * 3`
const { body } = parser_wasm(code) const { body } = parse(code)
expect(body[0]).toEqual({ expect(body[0]).toEqual({
type: 'VariableDeclaration', type: 'VariableDeclaration',
start: 0, start: 0,
@ -1384,7 +1383,7 @@ describe('nests binary expressions correctly', () => {
}) })
it('should nest properly with two opperators of equal precedence', () => { it('should nest properly with two opperators of equal precedence', () => {
const code = `const yo = 1 + 2 - 3` const code = `const yo = 1 + 2 - 3`
const { body } = parser_wasm(code) const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({ expect((body[0] as any).declarations[0].init).toEqual({
type: 'BinaryExpression', type: 'BinaryExpression',
start: 11, start: 11,
@ -1421,7 +1420,7 @@ describe('nests binary expressions correctly', () => {
}) })
it('should nest properly with two opperators of equal (but higher) precedence', () => { it('should nest properly with two opperators of equal (but higher) precedence', () => {
const code = `const yo = 1 * 2 / 3` const code = `const yo = 1 * 2 / 3`
const { body } = parser_wasm(code) const { body } = parse(code)
expect((body[0] as any).declarations[0].init).toEqual({ expect((body[0] as any).declarations[0].init).toEqual({
type: 'BinaryExpression', type: 'BinaryExpression',
start: 11, start: 11,
@ -1458,7 +1457,7 @@ describe('nests binary expressions correctly', () => {
}) })
it('should nest properly with longer example', () => { it('should nest properly with longer example', () => {
const code = `const yo = 1 + 2 * (3 - 4) / 5 + 6` const code = `const yo = 1 + 2 * (3 - 4) / 5 + 6`
const { body } = parser_wasm(code) const { body } = parse(code)
const init = (body[0] as any).declarations[0].init const init = (body[0] as any).declarations[0].init
expect(init).toEqual({ expect(init).toEqual({
type: 'BinaryExpression', type: 'BinaryExpression',
@ -1520,14 +1519,12 @@ const key = 'c'`
value: 'this is a comment', value: 'this is a comment',
}, },
} }
const { nonCodeMeta } = parser_wasm(code) const { nonCodeMeta } = parse(code)
expect(nonCodeMeta.nonCodeNodes[0]).toEqual(nonCodeMetaInstance) expect(nonCodeMeta.nonCodeNodes[0]).toEqual(nonCodeMetaInstance)
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though) // extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
const codeWithExtraStartWhitespace = '\n\n\n' + code const codeWithExtraStartWhitespace = '\n\n\n' + code
const { nonCodeMeta: nonCodeMeta2 } = parser_wasm( const { nonCodeMeta: nonCodeMeta2 } = parse(codeWithExtraStartWhitespace)
codeWithExtraStartWhitespace
)
expect(nonCodeMeta2.nonCodeNodes[0].value).toStrictEqual( expect(nonCodeMeta2.nonCodeNodes[0].value).toStrictEqual(
nonCodeMetaInstance.value nonCodeMetaInstance.value
) )
@ -1545,7 +1542,7 @@ const key = 'c'`
|> close(%) |> close(%)
` `
const { body } = parser_wasm(code) const { body } = parse(code)
const indexOfSecondLineToExpression = 2 const indexOfSecondLineToExpression = 2
const sketchNonCodeMeta = (body as any)[0].declarations[0].init.nonCodeMeta const sketchNonCodeMeta = (body as any)[0].declarations[0].init.nonCodeMeta
.nonCodeNodes .nonCodeNodes
@ -1569,7 +1566,7 @@ const key = 'c'`
' |> rx(90, %)', ' |> rx(90, %)',
].join('\n') ].join('\n')
const { body } = parser_wasm(code) const { body } = parse(code)
const sketchNonCodeMeta = (body[0] as any).declarations[0].init.nonCodeMeta const sketchNonCodeMeta = (body[0] as any).declarations[0].init.nonCodeMeta
.nonCodeNodes .nonCodeNodes
expect(sketchNonCodeMeta[3]).toEqual({ expect(sketchNonCodeMeta[3]).toEqual({
@ -1587,7 +1584,7 @@ const key = 'c'`
describe('test UnaryExpression', () => { describe('test UnaryExpression', () => {
it('should parse a unary expression in simple var dec situation', () => { it('should parse a unary expression in simple var dec situation', () => {
const code = `const myVar = -min(4, 100)` const code = `const myVar = -min(4, 100)`
const { body } = parser_wasm(code) const { body } = parse(code)
const myVarInit = (body?.[0] as any).declarations[0]?.init const myVarInit = (body?.[0] as any).declarations[0]?.init
expect(myVarInit).toEqual({ expect(myVarInit).toEqual({
type: 'UnaryExpression', type: 'UnaryExpression',
@ -1613,7 +1610,7 @@ describe('test UnaryExpression', () => {
describe('testing nested call expressions', () => { describe('testing nested call expressions', () => {
it('callExp in a binExp in a callExp', () => { it('callExp in a binExp in a callExp', () => {
const code = 'const myVar = min(100, 1 + legLen(5, 3))' const code = 'const myVar = min(100, 1 + legLen(5, 3))'
const { body } = parser_wasm(code) const { body } = parse(code)
const myVarInit = (body?.[0] as any).declarations[0]?.init const myVarInit = (body?.[0] as any).declarations[0]?.init
expect(myVarInit).toEqual({ expect(myVarInit).toEqual({
type: 'CallExpression', type: 'CallExpression',
@ -1651,7 +1648,7 @@ describe('testing nested call expressions', () => {
describe('should recognise callExpresions in binaryExpressions', () => { describe('should recognise callExpresions in binaryExpressions', () => {
const code = "xLineTo(segEndX('seg02', %) + 1, %)" const code = "xLineTo(segEndX('seg02', %) + 1, %)"
it('should recognise the callExp', () => { it('should recognise the callExp', () => {
const { body } = parser_wasm(code) const { body } = parse(code)
const callExpArgs = (body?.[0] as any).expression?.arguments const callExpArgs = (body?.[0] as any).expression?.arguments
expect(callExpArgs).toEqual([ expect(callExpArgs).toEqual([
{ {
@ -1690,7 +1687,7 @@ describe('parsing errors', () => {
let _theError let _theError
try { try {
const result = expect(parser_wasm(code)) const result = expect(parse(code))
} catch (e) { } catch (e) {
_theError = e _theError = e
} }

View File

@ -1,48 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import { parse_js } from '../wasm-lib/pkg/wasm_lib'
import { initPromise } from './rust'
import { Token } from './tokeniser'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
export const rangeTypeFix = (ranges: number[][]): [number, number][] =>
ranges.map(([start, end]) => [start, end])
export const parser_wasm = (code: string): Program => {
try {
const program: Program = parse_js(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export async function asyncParser(code: string): Promise<Program> {
await initPromise
try {
const program: Program = parse_js(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export function rangeOfToken(token: Token | undefined): [number, number][] {
return token === undefined ? [] : [[token.start, token.end]]
}

View File

@ -1,37 +0,0 @@
export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value'
export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression'
export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression'
export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression'
export type { VariableDeclaration } from '../wasm-lib/kcl/bindings/VariableDeclaration'
export type { PipeSubstitution } from '../wasm-lib/kcl/bindings/PipeSubstitution'
export type { Identifier } from '../wasm-lib/kcl/bindings/Identifier'
export type { UnaryExpression } from '../wasm-lib/kcl/bindings/UnaryExpression'
export type { BinaryExpression } from '../wasm-lib/kcl/bindings/BinaryExpression'
export type { ReturnStatement } from '../wasm-lib/kcl/bindings/ReturnStatement'
export type { ExpressionStatement } from '../wasm-lib/kcl/bindings/ExpressionStatement'
export type { CallExpression } from '../wasm-lib/kcl/bindings/CallExpression'
export type { VariableDeclarator } from '../wasm-lib/kcl/bindings/VariableDeclarator'
export type { BinaryPart } from '../wasm-lib/kcl/bindings/BinaryPart'
export type { Literal } from '../wasm-lib/kcl/bindings/Literal'
export type { ArrayExpression } from '../wasm-lib/kcl/bindings/ArrayExpression'
export type SyntaxType =
| 'Program'
| 'ExpressionStatement'
| 'BinaryExpression'
| 'CallExpression'
| 'Identifier'
| 'ReturnStatement'
| 'VariableDeclaration'
| 'VariableDeclarator'
| 'MemberExpression'
| 'ArrayExpression'
| 'ObjectExpression'
| 'ObjectProperty'
| 'FunctionExpression'
| 'PipeExpression'
| 'PipeSubstitution'
| 'Literal'
| 'NonCodeNode'
| 'UnaryExpression'

View File

@ -1,5 +1,4 @@
import { parser_wasm } from './abstractSyntaxTree' import { parse, initPromise } from './wasm'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -13,7 +12,7 @@ const mySketch001 = startSketchAt([0, 0])
|> lineTo([0.46, -5.82], %) |> lineTo([0.46, -5.82], %)
// |> rx(45, %) // |> rx(45, %)
show(mySketch001)` show(mySketch001)`
const programMemory = await enginelessExecutor(parser_wasm(code)) const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore // @ts-ignore
const shown = programMemory?.return?.map( const shown = programMemory?.return?.map(
// @ts-ignore // @ts-ignore
@ -69,7 +68,7 @@ const mySketch001 = startSketchAt([0, 0])
// |> rx(45, %) // |> rx(45, %)
|> extrude(2, %) |> extrude(2, %)
show(mySketch001)` show(mySketch001)`
const programMemory = await enginelessExecutor(parser_wasm(code)) const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore // @ts-ignore
const shown = programMemory?.return?.map( const shown = programMemory?.return?.map(
// @ts-ignore // @ts-ignore
@ -109,7 +108,7 @@ const sk2 = startSketchAt([0, 0])
show(theExtrude, sk2)` show(theExtrude, sk2)`
const programMemory = await enginelessExecutor(parser_wasm(code)) const programMemory = await enginelessExecutor(parse(code))
// @ts-ignore // @ts-ignore
const geos = programMemory?.return?.map( const geos = programMemory?.return?.map(
// @ts-ignore // @ts-ignore

View File

@ -1,10 +1,7 @@
import fs from 'node:fs' import fs from 'node:fs'
import { parser_wasm } from './abstractSyntaxTree' import { parse, ProgramMemory, SketchGroup, initPromise } from './wasm'
import { ProgramMemory, SketchGroup } from './executor'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
import { vi } from 'vitest'
import { KCLError } from './errors' import { KCLError } from './errors'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -403,7 +400,7 @@ async function exe(
code: string, code: string,
programMemory: ProgramMemory = { root: {}, return: null } programMemory: ProgramMemory = { root: {}, return: null }
) { ) {
const ast = parser_wasm(code) const ast = parse(code)
const result = await enginelessExecutor(ast, programMemory) const result = await enginelessExecutor(ast, programMemory)
return result return result

View File

@ -1,81 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import {
EngineCommandManager,
ArtifactMap,
SourceRangeMap,
} from './std/engineConnection'
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
import { execute_wasm } from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import { rangeTypeFix } from './abstractSyntaxTree'
export type { SourceRange } from '../wasm-lib/kcl/bindings/SourceRange'
export type { Position } from '../wasm-lib/kcl/bindings/Position'
export type { Rotation } from '../wasm-lib/kcl/bindings/Rotation'
export type { Path } from '../wasm-lib/kcl/bindings/Path'
export type { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
export type PathToNode = [string | number, string][]
interface Memory {
[key: string]: MemoryItem
}
export interface ProgramMemory {
root: Memory
return: ProgramReturn | null
}
export const executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager,
// work around while the gemotry is still be stored on the frontend
// will be removed when the stream UI is added.
tempMapCallback: (a: {
artifactMap: ArtifactMap
sourceRangeMap: SourceRangeMap
}) => void = () => {}
): Promise<ProgramMemory> => {
engineCommandManager.startNewSession()
const _programMemory = await _executor(
node,
programMemory,
engineCommandManager
)
const { artifactMap, sourceRangeMap } =
await engineCommandManager.waitForAllCommands(node, _programMemory)
tempMapCallback({ artifactMap, sourceRangeMap })
engineCommandManager.endSession()
return _programMemory
}
export const _executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager
): Promise<ProgramMemory> => {
try {
const memory: ProgramMemory = await execute_wasm(
JSON.stringify(node),
JSON.stringify(programMemory),
engineCommandManager
)
return memory
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}

View File

@ -1,7 +1,5 @@
import { getNodePathFromSourceRange, getNodeFromPath } from './queryAst' import { getNodePathFromSourceRange, getNodeFromPath } from './queryAst'
import { parser_wasm } from './abstractSyntaxTree' import { Identifier, parse, initPromise } from './wasm'
import { initPromise } from './rust'
import { Identifier } from './abstractSyntaxTreeTypes'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -21,7 +19,7 @@ const sk3 = startSketchAt([0, 0])
lineToSubstringIndex + subStr.length, lineToSubstringIndex + subStr.length,
] ]
const ast = parser_wasm(code) const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange) const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const { node } = getNodeFromPath<any>(ast, nodePath) const { node } = getNodeFromPath<any>(ast, nodePath)
@ -46,7 +44,7 @@ const b1 = cube([0,0], 10)`
subStrIndex + 'pos'.length, subStrIndex + 'pos'.length,
] ]
const ast = parser_wasm(code) const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange) const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const node = getNodeFromPath<Identifier>(ast, nodePath).node const node = getNodeFromPath<Identifier>(ast, nodePath).node
@ -80,7 +78,7 @@ const b1 = cube([0,0], 10)`
subStrIndex + 'scale'.length, subStrIndex + 'scale'.length,
] ]
const ast = parser_wasm(code) const ast = parse(code)
const nodePath = getNodePathFromSourceRange(ast, sourceRange) const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const node = getNodeFromPath<Identifier>(ast, nodePath).node const node = getNodeFromPath<Identifier>(ast, nodePath).node
expect(nodePath).toEqual([ expect(nodePath).toEqual([

View File

@ -1,4 +1,4 @@
import { parser_wasm } from './abstractSyntaxTree' import { parse, recast, initPromise } from './wasm'
import { import {
createLiteral, createLiteral,
createIdentifier, createIdentifier,
@ -13,8 +13,6 @@ import {
giveSketchFnCallTag, giveSketchFnCallTag,
moveValueIntoNewVariable, moveValueIntoNewVariable,
} from './modifyAst' } from './modifyAst'
import { recast } from './recast'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -126,7 +124,7 @@ function giveSketchFnCallTagTestHelper(
// giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing // giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing
// this wrapper changes the input and output to code // this wrapper changes the input and output to code
// making it more of an integration test, but easier to read the test intention is the goal // making it more of an integration test, but easier to read the test intention is the goal
const ast = parser_wasm(code) const ast = parse(code)
const start = code.indexOf(searchStr) const start = code.indexOf(searchStr)
const range: [number, number] = [start, start + searchStr.length] const range: [number, number] = [start, start + searchStr.length]
const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag(ast, range) const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag(ast, range)
@ -197,7 +195,7 @@ const part001 = startSketchAt([-1.2, 4.83])
const yo2 = hmm([identifierGuy + 5]) const yo2 = hmm([identifierGuy + 5])
show(part001)` show(part001)`
it('should move a binary expression into a new variable', async () => { it('should move a binary expression into a new variable', async () => {
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('100 + 100') + 1 const startIndex = code.indexOf('100 + 100') + 1
const { modifiedAst } = moveValueIntoNewVariable( const { modifiedAst } = moveValueIntoNewVariable(
@ -211,7 +209,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`) expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
}) })
it('should move a value into a new variable', async () => { it('should move a value into a new variable', async () => {
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('2.8') + 1 const startIndex = code.indexOf('2.8') + 1
const { modifiedAst } = moveValueIntoNewVariable( const { modifiedAst } = moveValueIntoNewVariable(
@ -225,7 +223,7 @@ show(part001)`
expect(newCode).toContain(`line([newVar, 0], %)`) expect(newCode).toContain(`line([newVar, 0], %)`)
}) })
it('should move a callExpression into a new variable', async () => { it('should move a callExpression into a new variable', async () => {
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('def(') const startIndex = code.indexOf('def(')
const { modifiedAst } = moveValueIntoNewVariable( const { modifiedAst } = moveValueIntoNewVariable(
@ -239,7 +237,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`) expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
}) })
it('should move a binary expression with call expression into a new variable', async () => { it('should move a binary expression with call expression into a new variable', async () => {
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('jkl(') + 1 const startIndex = code.indexOf('jkl(') + 1
const { modifiedAst } = moveValueIntoNewVariable( const { modifiedAst } = moveValueIntoNewVariable(
@ -253,7 +251,7 @@ show(part001)`
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`) expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
}) })
it('should move a identifier into a new variable', async () => { it('should move a identifier into a new variable', async () => {
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const startIndex = code.indexOf('identifierGuy +') + 1 const startIndex = code.indexOf('identifierGuy +') + 1
const { modifiedAst } = moveValueIntoNewVariable( const { modifiedAst } = moveValueIntoNewVariable(

View File

@ -14,14 +14,15 @@ import {
ObjectExpression, ObjectExpression,
UnaryExpression, UnaryExpression,
BinaryExpression, BinaryExpression,
} from './abstractSyntaxTreeTypes' PathToNode,
ProgramMemory,
} from './wasm'
import { import {
findAllPreviousVariables, findAllPreviousVariables,
getNodeFromPath, getNodeFromPath,
getNodePathFromSourceRange, getNodePathFromSourceRange,
isNodeSafeToReplace, isNodeSafeToReplace,
} from './queryAst' } from './queryAst'
import { PathToNode, ProgramMemory } from './executor'
import { import {
addTagForSketchOnFace, addTagForSketchOnFace,
getFirstArg, getFirstArg,

View File

@ -1,11 +1,10 @@
import { parser_wasm } from './abstractSyntaxTree' import { parse, recast, initPromise } from './wasm'
import { import {
findAllPreviousVariables, findAllPreviousVariables,
isNodeSafeToReplace, isNodeSafeToReplace,
isTypeInValue, isTypeInValue,
getNodePathFromSourceRange, getNodePathFromSourceRange,
} from './queryAst' } from './queryAst'
import { initPromise } from './rust'
import { enginelessExecutor } from '../lib/testHelpers' import { enginelessExecutor } from '../lib/testHelpers'
import { import {
createArrayExpression, createArrayExpression,
@ -13,7 +12,6 @@ import {
createLiteral, createLiteral,
createPipeSubstitution, createPipeSubstitution,
} from './modifyAst' } from './modifyAst'
import { recast } from './recast'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -36,7 +34,7 @@ const variableBelowShouldNotBeIncluded = 3
show(part001)` show(part001)`
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7 const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const { variables, bodyPath, insertIndex } = findAllPreviousVariables( const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
@ -70,7 +68,7 @@ const yo = 5 + 6
const yo2 = hmm([identifierGuy + 5]) const yo2 = hmm([identifierGuy + 5])
show(part001)` show(part001)`
it('find a safe binaryExpression', () => { it('find a safe binaryExpression', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('100 + 100') + 2 const rangeStart = code.indexOf('100 + 100') + 2
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -84,7 +82,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`) expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
}) })
it('find a safe Identifier', () => { it('find a safe Identifier', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('abc') const rangeStart = code.indexOf('abc')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -92,7 +90,7 @@ show(part001)`
expect(code.slice(result.value.start, result.value.end)).toBe('abc') expect(code.slice(result.value.start, result.value.end)).toBe('abc')
}) })
it('find a safe CallExpression', () => { it('find a safe CallExpression', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('def') const rangeStart = code.indexOf('def')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -106,7 +104,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`) expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
}) })
it('find an UNsafe CallExpression, as it has a PipeSubstitution', () => { it('find an UNsafe CallExpression, as it has a PipeSubstitution', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('ghi') const rangeStart = code.indexOf('ghi')
const range: [number, number] = [rangeStart, rangeStart] const range: [number, number] = [rangeStart, rangeStart]
const result = isNodeSafeToReplace(ast, range) const result = isNodeSafeToReplace(ast, range)
@ -115,7 +113,7 @@ show(part001)`
expect(code.slice(result.value.start, result.value.end)).toBe('ghi(%)') expect(code.slice(result.value.start, result.value.end)).toBe('ghi(%)')
}) })
it('find an UNsafe Identifier, as it is a callee', () => { it('find an UNsafe Identifier, as it is a callee', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('ine([2.8,') const rangeStart = code.indexOf('ine([2.8,')
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(false) expect(result.isSafe).toBe(false)
@ -125,7 +123,7 @@ show(part001)`
) )
}) })
it("find a safe BinaryExpression that's assigned to a variable", () => { it("find a safe BinaryExpression that's assigned to a variable", () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('5 + 6') + 1 const rangeStart = code.indexOf('5 + 6') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -139,7 +137,7 @@ show(part001)`
expect(outCode).toContain(`const yo = replaceName`) expect(outCode).toContain(`const yo = replaceName`)
}) })
it('find a safe BinaryExpression that has a CallExpression within', () => { it('find a safe BinaryExpression that has a CallExpression within', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('jkl') + 1 const rangeStart = code.indexOf('jkl') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -155,7 +153,7 @@ show(part001)`
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`) expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
}) })
it('find a safe BinaryExpression within a CallExpression', () => { it('find a safe BinaryExpression within a CallExpression', () => {
const ast = parser_wasm(code) const ast = parse(code)
const rangeStart = code.indexOf('identifierGuy') + 1 const rangeStart = code.indexOf('identifierGuy') + 1
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart]) const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart])
expect(result.isSafe).toBe(true) expect(result.isSafe).toBe(true)
@ -203,7 +201,7 @@ show(part001)`
it('finds the second line when cursor is put at the end', () => { it('finds the second line when cursor is put at the end', () => {
const searchLn = `line([0.94, 2.61], %)` const searchLn = `line([0.94, 2.61], %)`
const sourceIndex = code.indexOf(searchLn) + searchLn.length const sourceIndex = code.indexOf(searchLn) + searchLn.length
const ast = parser_wasm(code) const ast = parse(code)
const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex]) const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex])
expect(result).toEqual([ expect(result).toEqual([
['body', ''], ['body', ''],
@ -218,7 +216,7 @@ show(part001)`
it('finds the last line when cursor is put at the end', () => { it('finds the last line when cursor is put at the end', () => {
const searchLn = `line([-0.21, -1.4], %)` const searchLn = `line([-0.21, -1.4], %)`
const sourceIndex = code.indexOf(searchLn) + searchLn.length const sourceIndex = code.indexOf(searchLn) + searchLn.length
const ast = parser_wasm(code) const ast = parse(code)
const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex]) const result = getNodePathFromSourceRange(ast, [sourceIndex, sourceIndex])
const expected = [ const expected = [
['body', ''], ['body', ''],

View File

@ -1,4 +1,3 @@
import { PathToNode, ProgramMemory, SketchGroup, SourceRange } from './executor'
import { Selection, ToolTip } from '../useStore' import { Selection, ToolTip } from '../useStore'
import { import {
BinaryExpression, BinaryExpression,
@ -10,7 +9,11 @@ import {
VariableDeclaration, VariableDeclaration,
ReturnStatement, ReturnStatement,
ArrayExpression, ArrayExpression,
} from './abstractSyntaxTreeTypes' PathToNode,
ProgramMemory,
SketchGroup,
SourceRange,
} from './wasm'
import { createIdentifier, splitPathAtLastIndex } from './modifyAst' import { createIdentifier, splitPathAtLastIndex } from './modifyAst'
import { getSketchSegmentFromSourceRange } from './std/sketchConstraints' import { getSketchSegmentFromSourceRange } from './std/sketchConstraints'
import { getAngle } from '../lib/utils' import { getAngle } from '../lib/utils'

View File

@ -1,8 +1,5 @@
import { recast } from './recast' import { parse, Program, recast, initPromise } from './wasm'
import { parser_wasm } from './abstractSyntaxTree'
import { Program } from './abstractSyntaxTreeTypes'
import fs from 'node:fs' import fs from 'node:fs'
import { initPromise } from './rust'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -366,6 +363,6 @@ describe('it recasts binary expression using brackets where needed', () => {
// helpers // helpers
function code2ast(code: string): { ast: Program } { function code2ast(code: string): { ast: Program } {
const ast = parser_wasm(code) const ast = parse(code)
return { ast } return { ast }
} }

View File

@ -1,13 +0,0 @@
import { Program } from './abstractSyntaxTreeTypes'
import { recast_wasm } from '../wasm-lib/pkg/wasm_lib'
export const recast = (ast: Program): string => {
try {
const s: string = recast_wasm(JSON.stringify(ast))
return s
} catch (e) {
// TODO: do something real with the error.
console.log('recast error', e)
throw e
}
}

View File

@ -1,20 +0,0 @@
import init from '../wasm-lib/pkg/wasm_lib'
const initialise = async () => {
const baseUrl =
typeof window === 'undefined'
? 'http://127.0.0.1:3000'
: window.location.origin.includes('tauri://localhost')
? 'tauri://localhost'
: window.location.origin.includes('localhost')
? 'http://localhost:3000'
: window.location.origin && window.location.origin !== 'null'
? window.location.origin
: 'http://localhost:3000'
const fullUrl = baseUrl + '/wasm_lib_bg.wasm'
const input = await fetch(fullUrl)
const buffer = await input.arrayBuffer()
return init(buffer)
}
export const initPromise = initialise()

View File

@ -1,4 +1,9 @@
import { ProgramMemory, SourceRange } from 'lang/executor' import {
ProgramMemory,
SourceRange,
Program,
VariableDeclarator,
} from 'lang/wasm'
import { Selections } from 'useStore' import { Selections } from 'useStore'
import { VITE_KC_API_WS_MODELING_URL, VITE_KC_CONNECTION_TIMEOUT_MS } from 'env' import { VITE_KC_API_WS_MODELING_URL, VITE_KC_CONNECTION_TIMEOUT_MS } from 'env'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
@ -6,7 +11,6 @@ import { exportSave } from 'lib/exportSave'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import * as Sentry from '@sentry/react' import * as Sentry from '@sentry/react'
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst' import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
import { Program, VariableDeclarator } from 'lang/abstractSyntaxTreeTypes'
let lastMessage = '' let lastMessage = ''
@ -356,6 +360,11 @@ export class EngineConnection {
if (this.shouldTrace()) { if (this.shouldTrace()) {
iceSpan.resolve?.() iceSpan.resolve?.()
} }
} else if (this.pc?.iceConnectionState === 'failed') {
// failed is a terminal state; let's explicitly kill the
// connection to the server at this point.
console.log('failed to negotiate ice connection; restarting')
this.close()
} }
}) })
@ -487,9 +496,11 @@ export class EngineConnection {
this.onDataChannelOpen(this) this.onDataChannelOpen(this)
this.onEngineConnectionOpen(this)
this.ready = true this.ready = true
this.connecting = false this.connecting = false
// Do this after we set the connection is ready to avoid errors when
// we try to send messages before the connection is ready.
this.onEngineConnectionOpen(this)
}) })
this.unreliableDataChannel.addEventListener('close', (event) => { this.unreliableDataChannel.addEventListener('close', (event) => {
@ -582,6 +593,9 @@ export class EngineCommandManager {
outSequence = 1 outSequence = 1
inSequence = 1 inSequence = 1
engineConnection?: EngineConnection engineConnection?: EngineConnection
// Folks should realize that wait for ready does not get called _everytime_
// the connection resets and restarts, it only gets called the first time.
// Be careful what you put here.
waitForReady: Promise<void> = new Promise(() => {}) waitForReady: Promise<void> = new Promise(() => {})
private resolveReady = () => {} private resolveReady = () => {}
@ -605,12 +619,14 @@ export class EngineCommandManager {
setIsStreamReady, setIsStreamReady,
width, width,
height, height,
executeCode,
token, token,
}: { }: {
setMediaStream: (stream: MediaStream) => void setMediaStream: (stream: MediaStream) => void
setIsStreamReady: (isStreamReady: boolean) => void setIsStreamReady: (isStreamReady: boolean) => void
width: number width: number
height: number height: number
executeCode: (code?: string, force?: boolean) => void
token?: string token?: string
}) { }) {
if (width === 0 || height === 0) { if (width === 0 || height === 0) {
@ -633,6 +649,32 @@ export class EngineCommandManager {
onEngineConnectionOpen: () => { onEngineConnectionOpen: () => {
this.resolveReady() this.resolveReady()
setIsStreamReady(true) setIsStreamReady(true)
// Make the axis gizmo.
// We do this after the connection opened to avoid a race condition.
// Connected opened is the last thing that happens when the stream
// is ready.
// We also do this here because we want to ensure we create the gizmo
// and execute the code everytime the stream is restarted.
const gizmoId = uuidv4()
this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: gizmoId,
cmd: {
type: 'make_axes_gizmo',
clobber: false,
// If true, axes gizmo will be placed in the corner of the screen.
// If false, it will be placed at the origin of the scene.
gizmo_mode: true,
},
})
// We execute the code here to make sure if the stream was to
// restart in a session, we want to make sure to execute the code.
// We force it to re-execute the code because we want to make sure
// the code is executed everytime the stream is restarted.
// We pass undefined for the code so it reads from the current state.
executeCode(undefined, true)
}, },
onClose: () => { onClose: () => {
setIsStreamReady(false) setIsStreamReady(false)
@ -729,10 +771,6 @@ export class EngineCommandManager {
this.engineConnection?.send(resizeCmd) this.engineConnection?.send(resizeCmd)
} }
handleModelingCommand(message: WebSocketResponse, id: string) { handleModelingCommand(message: WebSocketResponse, id: string) {
if (this.engineConnection === undefined) {
return
}
if (message.type !== 'modeling') { if (message.type !== 'modeling') {
return return
} }
@ -900,6 +938,11 @@ export class EngineCommandManager {
if (this.engineConnection === undefined) { if (this.engineConnection === undefined) {
return Promise.resolve() return Promise.resolve()
} }
if (!this.engineConnection?.isReady()) {
return Promise.resolve()
}
if ( if (
command.type === 'modeling_cmd_req' && command.type === 'modeling_cmd_req' &&
command.cmd.type !== lastMessage command.cmd.type !== lastMessage
@ -907,9 +950,6 @@ export class EngineCommandManager {
console.log('sending command', command.cmd.type) console.log('sending command', command.cmd.type)
lastMessage = command.cmd.type lastMessage = command.cmd.type
} }
if (!this.engineConnection?.isReady()) {
return Promise.resolve()
}
if (command.type !== 'modeling_cmd_req') return Promise.resolve() if (command.type !== 'modeling_cmd_req') return Promise.resolve()
const cmd = command.cmd const cmd = command.cmd
if ( if (

View File

@ -6,13 +6,9 @@ import {
getXComponent, getXComponent,
addCloseToPipe, addCloseToPipe,
} from './sketch' } from './sketch'
import { parser_wasm } from '../abstractSyntaxTree' import { parse, recast, initPromise } from '../wasm'
import { getNodePathFromSourceRange } from '../queryAst' import { getNodePathFromSourceRange } from '../queryAst'
import { recast } from '../recast'
import { enginelessExecutor } from '../../lib/testHelpers' import { enginelessExecutor } from '../../lib/testHelpers'
import { initPromise } from '../rust'
beforeAll(() => initPromise)
const eachQuad: [number, [number, number]][] = [ const eachQuad: [number, [number, number]][] = [
[-315, [1, 1]], [-315, [1, 1]],
@ -29,6 +25,8 @@ const eachQuad: [number, [number, number]][] = [
[675, [1, -1]], [675, [1, -1]],
] ]
beforeAll(() => initPromise)
describe('testing getYComponent', () => { describe('testing getYComponent', () => {
it('should return the vertical component of a vector correctly when given angles in each quadrant (and with angles < 0, or > 360)', () => { it('should return the vertical component of a vector correctly when given angles in each quadrant (and with angles < 0, or > 360)', () => {
const expected: [number, number][] = [] const expected: [number, number][] = []
@ -106,7 +104,7 @@ show(mySketch001)
` `
const code = genCode(lineToChange) const code = genCode(lineToChange)
const expectedCode = genCode(lineAfterChange) const expectedCode = genCode(lineAfterChange)
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(lineToChange) const sourceStart = code.indexOf(lineToChange)
const { modifiedAst } = changeSketchArguments( const { modifiedAst } = changeSketchArguments(
@ -144,7 +142,7 @@ const mySketch001 = startSketchAt([0, 0])
|> lineTo([-1.59, -1.54], %) |> lineTo([-1.59, -1.54], %)
|> lineTo([0.46, -5.82], %) |> lineTo([0.46, -5.82], %)
show(mySketch001)` show(mySketch001)`
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(lineToChange) const sourceStart = code.indexOf(lineToChange)
expect(sourceStart).toBe(66) expect(sourceStart).toBe(66)
@ -205,7 +203,7 @@ describe('testing addTagForSketchOnFace', () => {
show(mySketch001) show(mySketch001)
` `
const code = genCode(originalLine) const code = genCode(originalLine)
const ast = parser_wasm(code) const ast = parse(code)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const sourceStart = code.indexOf(originalLine) const sourceStart = code.indexOf(originalLine)
const sourceRange: [number, number] = [ const sourceRange: [number, number] = [

View File

@ -4,9 +4,6 @@ import {
SketchGroup, SketchGroup,
SourceRange, SourceRange,
PathToNode, PathToNode,
MemoryItem,
} from '../executor'
import {
Program, Program,
PipeExpression, PipeExpression,
CallExpression, CallExpression,
@ -14,7 +11,7 @@ import {
Value, Value,
Literal, Literal,
VariableDeclaration, VariableDeclaration,
} from '../abstractSyntaxTreeTypes' } from '../wasm'
import { import {
getNodeFromPath, getNodeFromPath,
getNodeFromPathCurry, getNodeFromPathCurry,
@ -38,7 +35,6 @@ import {
findUniqueName, findUniqueName,
} from '../modifyAst' } from '../modifyAst'
import { roundOff, getLength, getAngle } from '../../lib/utils' import { roundOff, getLength, getAngle } from '../../lib/utils'
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { perpendicularDistance } from 'sketch-helpers' import { perpendicularDistance } from 'sketch-helpers'
export type Coords2d = [number, number] export type Coords2d = [number, number]

View File

@ -1,12 +1,9 @@
import { parser_wasm } from '../abstractSyntaxTree' import { parse, SketchGroup, recast, initPromise } from '../wasm'
import { SketchGroup } from '../executor'
import { import {
ConstraintType, ConstraintType,
getTransformInfos, getTransformInfos,
transformAstSketchLines, transformAstSketchLines,
} from './sketchcombos' } from './sketchcombos'
import { recast } from '../recast'
import { initPromise } from '../rust'
import { getSketchSegmentFromSourceRange } from './sketchConstraints' import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { Selection } from '../../useStore' import { Selection } from '../../useStore'
import { enginelessExecutor } from '../../lib/testHelpers' import { enginelessExecutor } from '../../lib/testHelpers'
@ -31,7 +28,7 @@ async function testingSwapSketchFnCall({
type: 'default', type: 'default',
range: [startIndex, startIndex + callToSwap.length], range: [startIndex, startIndex + callToSwap.length],
} }
const ast = parser_wasm(inputCode) const ast = parse(inputCode)
const programMemory = await enginelessExecutor(ast) const programMemory = await enginelessExecutor(ast)
const selections = { const selections = {
codeBasedSelections: [range], codeBasedSelections: [range],
@ -381,7 +378,7 @@ const part001 = startSketchAt([0, 0.04]) // segment-in-start
|> xLine(3.54, %) |> xLine(3.54, %)
show(part001)` show(part001)`
it('normal case works', async () => { it('normal case works', async () => {
const programMemory = await enginelessExecutor(parser_wasm(code)) const programMemory = await enginelessExecutor(parse(code))
const index = code.indexOf('// normal-segment') - 7 const index = code.indexOf('// normal-segment') - 7
const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange( const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange(
programMemory.root['part001'] as SketchGroup, programMemory.root['part001'] as SketchGroup,
@ -395,7 +392,7 @@ show(part001)`
}) })
}) })
it('verify it works when the segment is in the `start` property', async () => { it('verify it works when the segment is in the `start` property', async () => {
const programMemory = await enginelessExecutor(parser_wasm(code)) const programMemory = await enginelessExecutor(parse(code))
const index = code.indexOf('// segment-in-start') - 7 const index = code.indexOf('// segment-in-start') - 7
const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange( const { __geoMeta, ...segment } = getSketchSegmentFromSourceRange(
programMemory.root['part001'] as SketchGroup, programMemory.root['part001'] as SketchGroup,

View File

@ -3,8 +3,10 @@ import {
Program, Program,
VariableDeclarator, VariableDeclarator,
CallExpression, CallExpression,
} from '../abstractSyntaxTreeTypes' SketchGroup,
import { SketchGroup, SourceRange, Path } from '../executor' SourceRange,
Path,
} from '../wasm'
export function getSketchSegmentFromSourceRange( export function getSketchSegmentFromSourceRange(
sketchGroup: SketchGroup, sketchGroup: SketchGroup,

View File

@ -1,5 +1,4 @@
import { parser_wasm } from '../abstractSyntaxTree' import { parse, Value, recast, initPromise } from '../wasm'
import { Value } from '../abstractSyntaxTreeTypes'
import { import {
getConstraintType, getConstraintType,
getTransformInfos, getTransformInfos,
@ -8,10 +7,8 @@ import {
ConstraintType, ConstraintType,
getConstraintLevelFromSourceRange, getConstraintLevelFromSourceRange,
} from './sketchcombos' } from './sketchcombos'
import { initPromise } from '../rust'
import { Selections, ToolTip } from '../../useStore' import { Selections, ToolTip } from '../../useStore'
import { enginelessExecutor } from '../../lib/testHelpers' import { enginelessExecutor } from '../../lib/testHelpers'
import { recast } from '../../lang/recast'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -63,7 +60,7 @@ describe('testing getConstraintType', () => {
function getConstraintTypeFromSourceHelper( function getConstraintTypeFromSourceHelper(
code: string code: string
): ReturnType<typeof getConstraintType> { ): ReturnType<typeof getConstraintType> {
const ast = parser_wasm(code) const ast = parse(code)
const args = (ast.body[0] as any).expression.arguments[0].elements as [ const args = (ast.body[0] as any).expression.arguments[0].elements as [
Value, Value,
Value Value
@ -74,7 +71,7 @@ function getConstraintTypeFromSourceHelper(
function getConstraintTypeFromSourceHelper2( function getConstraintTypeFromSourceHelper2(
code: string code: string
): ReturnType<typeof getConstraintType> { ): ReturnType<typeof getConstraintType> {
const ast = parser_wasm(code) const ast = parse(code)
const arg = (ast.body[0] as any).expression.arguments[0] as Value const arg = (ast.body[0] as any).expression.arguments[0] as Value
const fnName = (ast.body[0] as any).expression.callee.name as ToolTip const fnName = (ast.body[0] as any).expression.callee.name as ToolTip
return getConstraintType(arg, fnName) return getConstraintType(arg, fnName)
@ -199,7 +196,7 @@ const part001 = startSketchAt([0, 0])
show(part001) show(part001)
` `
it('should transform the ast', async () => { it('should transform the ast', async () => {
const ast = parser_wasm(inputScript) const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n') .split('\n')
.filter((ln) => ln.includes('//')) .filter((ln) => ln.includes('//'))
@ -286,7 +283,7 @@ const part001 = startSketchAt([0, 0])
|> angledLineToY([301, myVar], %) // select for vertical constraint 10 |> angledLineToY([301, myVar], %) // select for vertical constraint 10
show(part001) show(part001)
` `
const ast = parser_wasm(inputScript) const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n') .split('\n')
.filter((ln) => ln.includes('// select for horizontal constraint')) .filter((ln) => ln.includes('// select for horizontal constraint'))
@ -344,7 +341,7 @@ const part001 = startSketchAt([0, 0])
|> yLineTo(myVar, %) // select for vertical constraint 10 |> yLineTo(myVar, %) // select for vertical constraint 10
show(part001) show(part001)
` `
const ast = parser_wasm(inputScript) const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n') .split('\n')
.filter((ln) => ln.includes('// select for vertical constraint')) .filter((ln) => ln.includes('// select for vertical constraint'))
@ -435,7 +432,7 @@ async function helperThing(
linesOfInterest: string[], linesOfInterest: string[],
constraint: ConstraintType constraint: ConstraintType
): Promise<string> { ): Promise<string> {
const ast = parser_wasm(inputScript) const ast = parse(inputScript)
const selectionRanges: Selections['codeBasedSelections'] = inputScript const selectionRanges: Selections['codeBasedSelections'] = inputScript
.split('\n') .split('\n')
.filter((ln) => .filter((ln) =>
@ -498,7 +495,7 @@ const part001 = startSketchAt([-0.01, -0.05])
|> xLine(-3.43 + 0, %) // full |> xLine(-3.43 + 0, %) // full
|> angledLineOfXLength([243 + 0, 1.2 + 0], %) // full |> angledLineOfXLength([243 + 0, 1.2 + 0], %) // full
show(part001)` show(part001)`
const ast = parser_wasm(code) const ast = parse(code)
const constraintLevels: ReturnType< const constraintLevels: ReturnType<
typeof getConstraintLevelFromSourceRange typeof getConstraintLevelFromSourceRange
>[] = ['full', 'partial', 'free'] >[] = ['full', 'partial', 'free']

View File

@ -6,7 +6,9 @@ import {
Value, Value,
BinaryPart, BinaryPart,
VariableDeclarator, VariableDeclarator,
} from '../abstractSyntaxTreeTypes' PathToNode,
ProgramMemory,
} from '../wasm'
import { import {
getNodeFromPath, getNodeFromPath,
getNodeFromPathCurry, getNodeFromPathCurry,
@ -25,10 +27,8 @@ import {
giveSketchFnCallTag, giveSketchFnCallTag,
} from '../modifyAst' } from '../modifyAst'
import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch' import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
import { PathToNode, ProgramMemory } from '../executor'
import { getSketchSegmentFromSourceRange } from './sketchConstraints' import { getSketchSegmentFromSourceRange } from './sketchConstraints'
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils' import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
import { MemoryItem } from 'wasm-lib/kcl/bindings/MemoryItem'
type LineInputsType = type LineInputsType =
| 'xAbsolute' | 'xAbsolute'

View File

@ -1,6 +1,5 @@
import { parser_wasm } from '../abstractSyntaxTree' import { parse, initPromise } from '../wasm'
import { enginelessExecutor } from '../../lib/testHelpers' import { enginelessExecutor } from '../../lib/testHelpers'
import { initPromise } from '../rust'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -17,9 +16,9 @@ describe('testing angledLineThatIntersects', () => {
}, %) }, %)
const intersect = segEndX('yo2', part001) const intersect = segEndX('yo2', part001)
show(part001)` show(part001)`
const { root } = await enginelessExecutor(parser_wasm(code('-1'))) const { root } = await enginelessExecutor(parse(code('-1')))
expect(root.intersect.value).toBe(1 + Math.sqrt(2)) expect(root.intersect.value).toBe(1 + Math.sqrt(2))
const { root: noOffset } = await enginelessExecutor(parser_wasm(code('0'))) const { root: noOffset } = await enginelessExecutor(parse(code('0')))
expect(noOffset.intersect.value).toBeCloseTo(1) expect(noOffset.intersect.value).toBeCloseTo(1)
}) })
}) })

View File

@ -1,7 +1,12 @@
import { ProgramMemory, Path, SourceRange } from '../executor' import {
import { Program, Value } from '../abstractSyntaxTreeTypes' ProgramMemory,
Path,
SourceRange,
Program,
Value,
PathToNode,
} from '../wasm'
import { ToolTip } from '../../useStore' import { ToolTip } from '../../useStore'
import { PathToNode } from '../executor'
import { EngineCommandManager } from './engineConnection' import { EngineCommandManager } from './engineConnection'
export interface InternalFirstArg { export interface InternalFirstArg {

View File

@ -1,5 +1,4 @@
import { lexer, asyncLexer } from './tokeniser' import { lexer, initPromise } from './wasm'
import { initPromise } from './rust'
beforeAll(() => initPromise) beforeAll(() => initPromise)
@ -10,9 +9,9 @@ describe('testing lexer', () => {
const code3 = `const yo = 45 /* this is a comment const code3 = `const yo = 45 /* this is a comment
const ya = 6 */ const ya = 6 */
const yi=45` const yi=45`
expect(await asyncLexer(code)).toEqual(lexer(code)) expect(lexer(code)).toEqual(lexer(code))
expect(await asyncLexer(code2)).toEqual(lexer(code2)) expect(lexer(code2)).toEqual(lexer(code2))
expect(await asyncLexer(code3)).toEqual(lexer(code3)) expect(lexer(code3)).toEqual(lexer(code3))
}) })
it('test lexer', () => { it('test lexer', () => {
expect(stringSummaryLexer('1 + 2')).toEqual([ expect(stringSummaryLexer('1 + 2')).toEqual([

View File

@ -1,28 +0,0 @@
import { lexer_js } from '../wasm-lib/pkg/wasm_lib'
import { initPromise } from './rust'
import { Token } from '../wasm-lib/kcl/bindings/Token'
export type { Token } from '../wasm-lib/kcl/bindings/Token'
export async function asyncLexer(str: string): Promise<Token[]> {
await initPromise
try {
const tokens: Token[] = lexer_js(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer error', e)
throw e
}
}
export function lexer(str: string): Token[] {
try {
const tokens: Token[] = lexer_js(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer error', e)
throw e
}
}

View File

@ -1,6 +1,5 @@
import { Selections, StoreState } from '../useStore' import { Selections, StoreState } from '../useStore'
import { Program } from './abstractSyntaxTreeTypes' import { Program, PathToNode } from './wasm'
import { PathToNode } from './executor'
import { getNodeFromPath } from './queryAst' import { getNodeFromPath } from './queryAst'
export function updateCursors( export function updateCursors(

215
src/lang/wasm.ts Normal file
View File

@ -0,0 +1,215 @@
import init, {
parse_wasm,
recast_wasm,
execute_wasm,
lexer_wasm,
modify_ast_for_sketch_wasm,
} from '../wasm-lib/pkg/wasm_lib'
import { KCLError } from './errors'
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
import {
EngineCommandManager,
ArtifactMap,
SourceRangeMap,
} from './std/engineConnection'
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
import type { Program } from '../wasm-lib/kcl/bindings/Program'
import type { Token } from '../wasm-lib/kcl/bindings/Token'
export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value'
export type { ObjectExpression } from '../wasm-lib/kcl/bindings/ObjectExpression'
export type { MemberExpression } from '../wasm-lib/kcl/bindings/MemberExpression'
export type { PipeExpression } from '../wasm-lib/kcl/bindings/PipeExpression'
export type { VariableDeclaration } from '../wasm-lib/kcl/bindings/VariableDeclaration'
export type { PipeSubstitution } from '../wasm-lib/kcl/bindings/PipeSubstitution'
export type { Identifier } from '../wasm-lib/kcl/bindings/Identifier'
export type { UnaryExpression } from '../wasm-lib/kcl/bindings/UnaryExpression'
export type { BinaryExpression } from '../wasm-lib/kcl/bindings/BinaryExpression'
export type { ReturnStatement } from '../wasm-lib/kcl/bindings/ReturnStatement'
export type { ExpressionStatement } from '../wasm-lib/kcl/bindings/ExpressionStatement'
export type { CallExpression } from '../wasm-lib/kcl/bindings/CallExpression'
export type { VariableDeclarator } from '../wasm-lib/kcl/bindings/VariableDeclarator'
export type { BinaryPart } from '../wasm-lib/kcl/bindings/BinaryPart'
export type { Literal } from '../wasm-lib/kcl/bindings/Literal'
export type { ArrayExpression } from '../wasm-lib/kcl/bindings/ArrayExpression'
export type SyntaxType =
| 'Program'
| 'ExpressionStatement'
| 'BinaryExpression'
| 'CallExpression'
| 'Identifier'
| 'ReturnStatement'
| 'VariableDeclaration'
| 'VariableDeclarator'
| 'MemberExpression'
| 'ArrayExpression'
| 'ObjectExpression'
| 'ObjectProperty'
| 'FunctionExpression'
| 'PipeExpression'
| 'PipeSubstitution'
| 'Literal'
| 'NonCodeNode'
| 'UnaryExpression'
export type { SourceRange } from '../wasm-lib/kcl/bindings/SourceRange'
export type { Position } from '../wasm-lib/kcl/bindings/Position'
export type { Rotation } from '../wasm-lib/kcl/bindings/Rotation'
export type { Path } from '../wasm-lib/kcl/bindings/Path'
export type { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
// Initialise the wasm module.
const initialise = async () => {
const baseUrl =
typeof window === 'undefined'
? 'http://127.0.0.1:3000'
: window.location.origin.includes('tauri://localhost')
? 'tauri://localhost'
: window.location.origin.includes('localhost')
? 'http://localhost:3000'
: window.location.origin && window.location.origin !== 'null'
? window.location.origin
: 'http://localhost:3000'
const fullUrl = baseUrl + '/wasm_lib_bg.wasm'
const input = await fetch(fullUrl)
const buffer = await input.arrayBuffer()
return init(buffer)
}
export const initPromise = initialise()
export const rangeTypeFix = (ranges: number[][]): [number, number][] =>
ranges.map(([start, end]) => [start, end])
export const parse = (code: string): Program => {
try {
const program: Program = parse_wasm(code)
return program
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export type PathToNode = [string | number, string][]
interface Memory {
[key: string]: MemoryItem
}
export interface ProgramMemory {
root: Memory
return: ProgramReturn | null
}
export const executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager,
// work around while the gemotry is still be stored on the frontend
// will be removed when the stream UI is added.
tempMapCallback: (a: {
artifactMap: ArtifactMap
sourceRangeMap: SourceRangeMap
}) => void = () => {}
): Promise<ProgramMemory> => {
engineCommandManager.startNewSession()
const _programMemory = await _executor(
node,
programMemory,
engineCommandManager
)
const { artifactMap, sourceRangeMap } =
await engineCommandManager.waitForAllCommands(node, _programMemory)
tempMapCallback({ artifactMap, sourceRangeMap })
engineCommandManager.endSession()
return _programMemory
}
export const _executor = async (
node: Program,
programMemory: ProgramMemory = { root: {}, return: null },
engineCommandManager: EngineCommandManager
): Promise<ProgramMemory> => {
try {
const memory: ProgramMemory = await execute_wasm(
JSON.stringify(node),
JSON.stringify(programMemory),
engineCommandManager
)
return memory
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}
export const recast = (ast: Program): string => {
try {
const s: string = recast_wasm(JSON.stringify(ast))
return s
} catch (e) {
// TODO: do something real with the error.
console.log('recast error', e)
throw e
}
}
export function lexer(str: string): Token[] {
try {
const tokens: Token[] = lexer_wasm(str)
return tokens
} catch (e) {
// TODO: do something real with the error.
console.log('lexer error', e)
throw e
}
}
export const modifyAstForSketch = async (
engineCommandManager: EngineCommandManager,
ast: Program,
variableName: string,
engineId: string
): Promise<Program> => {
try {
const updatedAst: Program = await modify_ast_for_sketch_wasm(
engineCommandManager,
JSON.stringify(ast),
variableName,
engineId
)
return updatedAst
} catch (e: any) {
const parsed: RustKclError = JSON.parse(e.toString())
const kclError = new KCLError(
parsed.kind,
parsed.msg,
rangeTypeFix(parsed.sourceRanges)
)
console.log(kclError)
throw kclError
}
}

View File

@ -1,19 +1,27 @@
export const bracket = `// Material: 6061-T6 Aluminum export const bracket = `const sigmaAllow = 15000 // psi
const sigmaAllow = 35000 // psi const width = 11 // inch
const width = 9 // inch
const p = 150 // Force on shelf - lbs const p = 150 // Force on shelf - lbs
const distance = 6 // inches const distance = 12 // inches
const FOS = 2 const FOS = 2
const thickness = sqrt(distance * p * FOS * 6 / ( sigmaAllow * width ))
const filletR = thickness * 2
const shelfMountL = 9
const wallMountL = 8
const leg1 = 5 // inches
const leg2 = 8 // inches
const thickness = sqrt(distance * p * FOS * 6 / sigmaAllow / width) // inches
const bracket = startSketchAt([0, 0]) const bracket = startSketchAt([0, 0])
|> line([0, leg1], %) |> line([0, wallMountL], %)
|> line([leg2, 0], %) |> tangentalArc({
radius: filletR,
offset: 90
}, %)
|> line([-shelfMountL, 0], %)
|> line([0, -thickness], %) |> line([0, -thickness], %)
|> line([-leg2 + thickness, 0], %) |> line([shelfMountL, 0], %)
|> line([0, -leg1 + thickness], %) |> tangentalArc({
radius: filletR - thickness,
offset: -90
}, %)
|> line([0, -wallMountL], %)
|> close(%) |> close(%)
|> extrude(width, %) |> extrude(width, %)

View File

@ -25,7 +25,7 @@ export async function exportSave(data: ArrayBuffer) {
} }
// Write the file. // Write the file.
await writeBinaryFile(filePath, uintArray) await writeBinaryFile(filePath, file.contents)
} else { } else {
// Download the file to the user's computer. // Download the file to the user's computer.
// Now we need to download the files to the user's downloads folder. // Now we need to download the files to the user's downloads folder.

View File

@ -1,10 +1,8 @@
import { Program } from '../lang/abstractSyntaxTreeTypes' import { Program, ProgramMemory, _executor, SourceRange } from '../lang/wasm'
import { ProgramMemory, _executor } from '../lang/executor'
import { import {
EngineCommandManager, EngineCommandManager,
EngineCommand, EngineCommand,
} from '../lang/std/engineConnection' } from '../lang/std/engineConnection'
import { SourceRange } from 'lang/executor'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
type WebSocketResponse = Models['OkWebSocketResponseData_type'] type WebSocketResponse = Models['OkWebSocketResponseData_type']
@ -81,6 +79,7 @@ export async function executor(
setMediaStream: () => {}, setMediaStream: () => {},
width: 0, width: 0,
height: 0, height: 0,
executeCode: () => {},
}) })
await engineCommandManager.waitForReady await engineCommandManager.waitForReady
engineCommandManager.startNewSession() engineCommandManager.startNewSession()

View File

@ -1,5 +1,5 @@
import { isOverlap, roundOff } from './utils' import { isOverlap, roundOff } from './utils'
import { SourceRange } from '../lang/executor' import { SourceRange } from '../lang/wasm'
describe('testing isOverlapping', () => { describe('testing isOverlapping', () => {
testBothOrders([0, 3], [3, 10]) testBothOrders([0, 3], [3, 10])

View File

@ -1,4 +1,4 @@
import { SourceRange } from '../lang/executor' import { SourceRange } from '../lang/wasm'
export function isOverlap(a: SourceRange, b: SourceRange) { export function isOverlap(a: SourceRange, b: SourceRange) {
const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a] const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a]

View File

@ -2,6 +2,7 @@ import { assign, createMachine } from 'xstate'
import { CommandBarMeta } from '../lib/commands' import { CommandBarMeta } from '../lib/commands'
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme' import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
import { CameraSystem, cameraSystems } from 'lib/cameraControls' import { CameraSystem, cameraSystems } from 'lib/cameraControls'
import { Models } from '@kittycad/lib'
export const DEFAULT_PROJECT_NAME = 'project-$nnn' export const DEFAULT_PROJECT_NAME = 'project-$nnn'
@ -11,11 +12,11 @@ export enum UnitSystem {
} }
export const baseUnits = { export const baseUnits = {
imperial: ['in', 'ft'], imperial: ['in', 'ft', 'yd'],
metric: ['mm', 'cm', 'm'], metric: ['mm', 'cm', 'm'],
} as const } as const
export type BaseUnit = 'in' | 'ft' | 'mm' | 'cm' | 'm' export type BaseUnit = Models['UnitLength_type']
export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v) export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v)

View File

@ -1,23 +1,23 @@
import { create } from 'zustand' import { create } from 'zustand'
import { persist } from 'zustand/middleware' import { persist } from 'zustand/middleware'
import { addLineHighlight, EditorView } from './editor/highlightextension' import { addLineHighlight, EditorView } from './editor/highlightextension'
import { parser_wasm } from './lang/abstractSyntaxTree'
import { Program } from './lang/abstractSyntaxTreeTypes'
import { getNodeFromPath } from './lang/queryAst'
import { enginelessExecutor } from './lib/testHelpers'
import { import {
parse,
Program,
_executor,
recast,
ProgramMemory, ProgramMemory,
Position, Position,
PathToNode, PathToNode,
Rotation, Rotation,
SourceRange, SourceRange,
} from './lang/executor' } from './lang/wasm'
import { recast } from './lang/recast' import { getNodeFromPath } from './lang/queryAst'
import { enginelessExecutor } from './lib/testHelpers'
import { EditorSelection } from '@codemirror/state' import { EditorSelection } from '@codemirror/state'
import { EngineCommandManager } from './lang/std/engineConnection' import { EngineCommandManager } from './lang/std/engineConnection'
import { KCLError } from './lang/errors' import { KCLError } from './lang/errors'
import { deferExecution } from 'lib/utils' import { deferExecution } from 'lib/utils'
import { _executor } from './lang/executor'
import { bracket } from 'lib/exampleKcl' import { bracket } from 'lib/exampleKcl'
import { engineCommandManager } from './lang/std/engineConnection' import { engineCommandManager } from './lang/std/engineConnection'
@ -157,7 +157,7 @@ export interface StoreState {
code: string code: string
setCode: (code: string) => void setCode: (code: string) => void
deferredSetCode: (code: string) => void deferredSetCode: (code: string) => void
executeCode: (code?: string) => void executeCode: (code?: string, force?: boolean) => void
formatCode: () => void formatCode: () => void
programMemory: ProgramMemory programMemory: ProgramMemory
setProgramMemory: (programMemory: ProgramMemory) => void setProgramMemory: (programMemory: ProgramMemory) => void
@ -221,11 +221,12 @@ export const useStore = create<StoreState>()(
editorView.dispatch({ effects: addLineHighlight.of(selection) }) editorView.dispatch({ effects: addLineHighlight.of(selection) })
} }
}, },
executeCode: async (code) => { executeCode: async (code, force) => {
const result = await executeCode({ const result = await executeCode({
code: code || get().code, code: code || get().code,
lastAst: get().ast, lastAst: get().ast,
engineCommandManager: engineCommandManager, engineCommandManager: engineCommandManager,
force,
}) })
if (!result.isChange) { if (!result.isChange) {
return return
@ -366,7 +367,7 @@ export const useStore = create<StoreState>()(
{ focusPath, callBack = () => {} } = {} { focusPath, callBack = () => {} } = {}
) => { ) => {
const newCode = recast(ast) const newCode = recast(ast)
const astWithUpdatedSource = parser_wasm(newCode) const astWithUpdatedSource = parse(newCode)
callBack(astWithUpdatedSource) callBack(astWithUpdatedSource)
set({ set({
@ -422,7 +423,7 @@ export const useStore = create<StoreState>()(
}, },
formatCode: async () => { formatCode: async () => {
const code = get().code const code = get().code
const ast = parser_wasm(code) const ast = parse(code)
const newCode = recast(ast) const newCode = recast(ast)
set({ code: newCode, ast }) set({ code: newCode, ast })
}, },
@ -511,10 +512,12 @@ async function executeCode({
engineCommandManager, engineCommandManager,
code, code,
lastAst, lastAst,
force,
}: { }: {
code: string code: string
lastAst: Program lastAst: Program
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
force?: boolean
}): Promise< }): Promise<
| { | {
logs: string[] logs: string[]
@ -527,7 +530,7 @@ async function executeCode({
> { > {
let ast: Program let ast: Program
try { try {
ast = parser_wasm(code) ast = parse(code)
} catch (e) { } catch (e) {
let errors: KCLError[] = [] let errors: KCLError[] = []
let logs: string[] = [JSON.stringify(e)] let logs: string[] = [JSON.stringify(e)]
@ -557,7 +560,7 @@ async function executeCode({
} }
// Check if the ast we have is equal to the ast in the storage. // Check if the ast we have is equal to the ast in the storage.
// If it is, we don't need to update the ast. // If it is, we don't need to update the ast.
if (JSON.stringify(ast) === JSON.stringify(lastAst)) if (JSON.stringify(ast) === JSON.stringify(lastAst) && !force)
return { isChange: false } return { isChange: false }
const { logs, errors, programMemory } = await executeAst({ const { logs, errors, programMemory } = await executeAst({

View File

@ -6,10 +6,10 @@
serial-integration = { max-threads = 4 } serial-integration = { max-threads = 4 }
[profile.default] [profile.default]
slow-timeout = { period = "10s", terminate-after = 1 } slow-timeout = { period = "60s", terminate-after = 1 }
[profile.ci] [profile.ci]
slow-timeout = { period = "60s", terminate-after = 10 } slow-timeout = { period = "120s", terminate-after = 10 }
[[profile.default.overrides]] [[profile.default.overrides]]
filter = "test(serial_test_)" filter = "test(serial_test_)"

View File

@ -71,9 +71,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.5.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" checksum = "f6cd65a4b849ace0b7f6daeebcc1a1d111282227ca745458c61dbf670e52a597"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
@ -109,9 +109,9 @@ dependencies = [
[[package]] [[package]]
name = "anstyle-wincon" name = "anstyle-wincon"
version = "2.1.0" version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" checksum = "0238ca56c96dfa37bdf7c373c8886dd591322500aceeeccdb2216fe06dc2f796"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"windows-sys 0.48.0", "windows-sys 0.48.0",
@ -440,9 +440,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.4" version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -450,9 +450,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.4" version = "4.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -695,6 +695,20 @@ dependencies = [
"syn 2.0.37", "syn 2.0.37",
] ]
[[package]]
name = "derive-docs"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c357dec14992ba88803535217ed83d6f6cd80efcb8fa8e3f8a30a9b84fadc1c7"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"serde",
"serde_tokenstream",
"syn 2.0.37",
]
[[package]] [[package]]
name = "diff" name = "diff"
version = "0.1.13" version = "0.1.13"
@ -788,9 +802,9 @@ dependencies = [
[[package]] [[package]]
name = "expectorate" name = "expectorate"
version = "1.0.7" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "710ab6a2d57038a835d66f78d5af3fa5d27c1ec4682f823b9203c48826cb0591" checksum = "de6f19b25bdfa2747ae775f37cd109c31f1272d4e4c83095be0727840aa1d75f"
dependencies = [ dependencies = [
"console", "console",
"newline-converter", "newline-converter",
@ -1376,7 +1390,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.1.31" version = "0.1.32"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-recursion", "async-recursion",
@ -1385,7 +1399,7 @@ dependencies = [
"clap", "clap",
"criterion", "criterion",
"dashmap", "dashmap",
"derive-docs", "derive-docs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"expectorate", "expectorate",
"futures", "futures",
"itertools 0.11.0", "itertools 0.11.0",
@ -1412,9 +1426,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.26" version = "0.2.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2623ee601ce203476229df3f9d3a14664cb43e3f7455e9ac8ed91aacaa6163d" checksum = "35b2f9302648dbb06fd7121687f9505fc3179eba84111a06d76b246e3158f5dc"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1719,7 +1733,7 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]] [[package]]
name = "openapitor" name = "openapitor"
version = "0.0.9" version = "0.0.9"
source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#61a16059b3eaf8793a2a2e1edbc0d770f284fea3" source = "git+https://github.com/KittyCAD/kittycad.rs?branch=main#fa0345c514fcc9ae6cd74ae35c8e5c2800fec34f"
dependencies = [ dependencies = [
"Inflector", "Inflector",
"anyhow", "anyhow",
@ -2203,9 +2217,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.20" version = "0.11.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" checksum = "78fdbab6a7e1d7b13cc8ff10197f47986b41c639300cc3c8158cac7847c9bbef"
dependencies = [ dependencies = [
"base64 0.21.4", "base64 0.21.4",
"bytes", "bytes",
@ -2230,6 +2244,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"system-configuration",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tower-service", "tower-service",
@ -2879,6 +2894,27 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "take_mut" name = "take_mut"
version = "0.2.2" version = "0.2.2"
@ -2945,18 +2981,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -11,7 +11,7 @@ crate-type = ["cdylib"]
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] } bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
gloo-utils = "0.2.0" gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" } kcl-lib = { path = "kcl" }
kittycad = { version = "0.2.25", default-features = false, features = ["js"] } kittycad = { version = "0.2.27", default-features = false, features = ["js"] }
serde_json = "1.0.107" serde_json = "1.0.107"
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.87" wasm-bindgen = "0.2.87"
@ -20,9 +20,9 @@ wasm-bindgen-futures = "0.4.37"
[dev-dependencies] [dev-dependencies]
anyhow = "1" anyhow = "1"
image = "0.24.7" image = "0.24.7"
kittycad = "0.2.25" kittycad = "0.2.27"
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
reqwest = { version = "0.11.20", default-features = false } reqwest = { version = "0.11.21", default-features = false }
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }
twenty-twenty = "0.6.1" twenty-twenty = "0.6.1"
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }

View File

@ -19,6 +19,6 @@ serde_tokenstream = "0.2"
syn = { version = "2.0.37", features = ["full"] } syn = { version = "2.0.37", features = ["full"] }
[dev-dependencies] [dev-dependencies]
expectorate = "1.0.7" expectorate = "1.1.0"
openapitor = { git = "https://github.com/KittyCAD/kittycad.rs", branch = "main" } openapitor = { git = "https://github.com/KittyCAD/kittycad.rs", branch = "main" }
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"

View File

@ -1,7 +1,7 @@
[package] [package]
name = "kcl-lib" name = "kcl-lib"
description = "KittyCAD Language" description = "KittyCAD Language"
version = "0.1.31" version = "0.1.32"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
@ -11,17 +11,17 @@ license = "MIT"
anyhow = { version = "1.0.75", features = ["backtrace"] } anyhow = { version = "1.0.75", features = ["backtrace"] }
async-recursion = "1.0.5" async-recursion = "1.0.5"
async-trait = "0.1.73" async-trait = "0.1.73"
clap = { version = "4.4.3", features = ["cargo", "derive", "env", "unicode"], optional = true } clap = { version = "4.4.6", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3" dashmap = "5.5.3"
#derive-docs = { version = "0.1.4" } derive-docs = { version = "0.1.4" }
derive-docs = { path = "../derive-docs" } #derive-docs = { path = "../derive-docs" }
kittycad = { version = "0.2.25", default-features = false, features = ["js"] } kittycad = { version = "0.2.27", default-features = false, features = ["js"] }
lazy_static = "1.4.0" lazy_static = "1.4.0"
parse-display = "0.8.2" parse-display = "0.8.2"
schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] } schemars = { version = "0.8", features = ["impl_json_schema", "url", "uuid1"] }
serde = { version = "1.0.188", features = ["derive"] } serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
thiserror = "1.0.48" thiserror = "1.0.49"
ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] } ts-rs = { version = "7", package = "ts-rs-json-value", features = ["serde-json-impl", "schemars-impl", "uuid-impl"] }
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] } uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
winnow = "0.5.15" winnow = "0.5.15"
@ -36,7 +36,7 @@ web-sys = { version = "0.3.64", features = ["console"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bson = { version = "2.7.0", features = ["uuid-1", "chrono"] } bson = { version = "2.7.0", features = ["uuid-1", "chrono"] }
futures = { version = "0.3.28" } futures = { version = "0.3.28" }
reqwest = { version = "0.11.20", default-features = false } reqwest = { version = "0.11.21", default-features = false }
tokio = { version = "1.32.0", features = ["full"] } tokio = { version = "1.32.0", features = ["full"] }
tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] } tokio-tungstenite = { version = "0.20.0", features = ["rustls-tls-native-roots"] }
tower-lsp = { version = "0.20.0", features = ["proposed"] } tower-lsp = { version = "0.20.0", features = ["proposed"] }
@ -52,7 +52,7 @@ debug = true
[dev-dependencies] [dev-dependencies]
criterion = "0.5.1" criterion = "0.5.1"
expectorate = "1.0.7" expectorate = "1.1.0"
itertools = "0.11.0" itertools = "0.11.0"
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }

View File

@ -258,6 +258,23 @@ impl Program {
} }
} }
/// Replace a value with the new value, use the source range for matching the exact value.
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for item in &mut self.body {
match item {
BodyItem::ExpressionStatement(ref mut expression_statement) => expression_statement
.expression
.replace_value(source_range, new_value.clone()),
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
variable_declaration.replace_value(source_range, new_value.clone())
}
BodyItem::ReturnStatement(ref mut return_statement) => {
return_statement.argument.replace_value(source_range, new_value.clone())
}
}
}
}
/// Get the variable declaration with the given name. /// Get the variable declaration with the given name.
pub fn get_variable(&self, name: &str) -> Option<&VariableDeclarator> { pub fn get_variable(&self, name: &str) -> Option<&VariableDeclarator> {
for item in &self.body { for item in &self.body {
@ -393,6 +410,27 @@ impl Value {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
if source_range == self.clone().into() {
*self = new_value;
return;
}
match self {
Value::BinaryExpression(ref mut bin_exp) => bin_exp.replace_value(source_range, new_value),
Value::ArrayExpression(ref mut array_exp) => array_exp.replace_value(source_range, new_value),
Value::ObjectExpression(ref mut obj_exp) => obj_exp.replace_value(source_range, new_value),
Value::MemberExpression(_) => {}
Value::Literal(_) => {}
Value::FunctionExpression(ref mut func_exp) => func_exp.replace_value(source_range, new_value),
Value::CallExpression(ref mut call_exp) => call_exp.replace_value(source_range, new_value),
Value::Identifier(_) => {}
Value::PipeExpression(ref mut pipe_exp) => pipe_exp.replace_value(source_range, new_value),
Value::UnaryExpression(ref mut unary_exp) => unary_exp.replace_value(source_range, new_value),
Value::PipeSubstitution(_) => {}
}
}
pub fn start(&self) -> usize { pub fn start(&self) -> usize {
match self { match self {
Value::Literal(literal) => literal.start(), Value::Literal(literal) => literal.start(),
@ -538,6 +576,23 @@ impl BinaryPart {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
match self {
BinaryPart::Literal(_) => {}
BinaryPart::Identifier(_) => {}
BinaryPart::BinaryExpression(ref mut binary_expression) => {
binary_expression.replace_value(source_range, new_value)
}
BinaryPart::CallExpression(ref mut call_expression) => {
call_expression.replace_value(source_range, new_value)
}
BinaryPart::UnaryExpression(ref mut unary_expression) => {
unary_expression.replace_value(source_range, new_value)
}
BinaryPart::MemberExpression(_) => {}
}
}
fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String { fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
match &self { match &self {
BinaryPart::Literal(literal) => literal.recast(), BinaryPart::Literal(literal) => literal.recast(),
@ -801,6 +856,12 @@ impl CallExpression {
}) })
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for arg in &mut self.arguments {
arg.replace_value(source_range, new_value.clone());
}
}
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String { fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
format!( format!(
"{}({})", "{}({})",
@ -1014,6 +1075,12 @@ impl VariableDeclaration {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for declaration in &mut self.declarations {
declaration.init.replace_value(source_range, new_value.clone());
}
}
/// Returns a value that includes the given character position. /// Returns a value that includes the given character position.
pub fn get_value_for_position(&self, pos: usize) -> Option<&Value> { pub fn get_value_for_position(&self, pos: usize) -> Option<&Value> {
for declaration in &self.declarations { for declaration in &self.declarations {
@ -1367,6 +1434,12 @@ impl ArrayExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for element in &mut self.elements {
element.replace_value(source_range, new_value.clone());
}
}
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
if self.elements.is_empty() { if self.elements.is_empty() {
return ConstraintLevel::Ignore { return ConstraintLevel::Ignore {
@ -1517,6 +1590,12 @@ impl ObjectExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for property in &mut self.properties {
property.value.replace_value(source_range, new_value.clone());
}
}
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
if self.properties.is_empty() { if self.properties.is_empty() {
return ConstraintLevel::Ignore { return ConstraintLevel::Ignore {
@ -1961,6 +2040,11 @@ impl BinaryExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
self.left.replace_value(source_range, new_value.clone());
self.right.replace_value(source_range, new_value);
}
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
let left_constraint_level = self.left.get_constraint_level(); let left_constraint_level = self.left.get_constraint_level();
let right_constraint_level = self.right.get_constraint_level(); let right_constraint_level = self.right.get_constraint_level();
@ -2183,6 +2267,10 @@ impl UnaryExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
self.argument.replace_value(source_range, new_value);
}
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
self.argument.get_constraint_level() self.argument.get_constraint_level()
} }
@ -2278,6 +2366,12 @@ impl PipeExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
for value in &mut self.body {
value.replace_value(source_range, new_value.clone());
}
}
pub fn get_constraint_level(&self) -> ConstraintLevel { pub fn get_constraint_level(&self) -> ConstraintLevel {
if self.body.is_empty() { if self.body.is_empty() {
return ConstraintLevel::Ignore { return ConstraintLevel::Ignore {
@ -2420,6 +2514,10 @@ impl FunctionExpression {
} }
} }
pub fn replace_value(&mut self, source_range: SourceRange, new_value: Value) {
self.body.replace_value(source_range, new_value);
}
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String { pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
// We don't want to end with a new line inside nested functions. // We don't want to end with a new line inside nested functions.
let mut new_options = options.clone(); let mut new_options = options.clone();

View File

@ -1283,7 +1283,11 @@ impl Parser {
let end_token = self.get_token(pipe_body_result.last_index)?; let end_token = self.get_token(pipe_body_result.last_index)?;
Ok(PipeExpressionResult { Ok(PipeExpressionResult {
expression: PipeExpression { expression: PipeExpression {
start: current_token.start, start: pipe_body_result
.body
.first()
.map(|v| v.start())
.unwrap_or(current_token.start),
end: end_token.end, end: end_token.end,
body: pipe_body_result.body, body: pipe_body_result.body,
non_code_meta: pipe_body_result.non_code_meta, non_code_meta: pipe_body_result.non_code_meta,

View File

@ -61,6 +61,8 @@ impl StdLib {
Box::new(crate::std::sketch::StartSketchAt), Box::new(crate::std::sketch::StartSketchAt),
Box::new(crate::std::sketch::Close), Box::new(crate::std::sketch::Close),
Box::new(crate::std::sketch::Arc), Box::new(crate::std::sketch::Arc),
Box::new(crate::std::sketch::TangentalArc),
Box::new(crate::std::sketch::TangentalArcTo),
Box::new(crate::std::sketch::BezierCurve), Box::new(crate::std::sketch::BezierCurve),
Box::new(crate::std::math::Cos), Box::new(crate::std::math::Cos),
Box::new(crate::std::math::Sin), Box::new(crate::std::math::Sin),

View File

@ -879,6 +879,214 @@ async fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: Args) ->
Ok(new_sketch_group) Ok(new_sketch_group)
} }
/// Data to draw a tangental arc.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
#[ts(export)]
#[serde(rename_all = "camelCase", untagged)]
pub enum TangentalArcData {
RadiusAndOffset {
/// Radius of the arc.
/// Not to be confused with Raiders of the Lost Ark.
radius: f64,
/// Offset of the arc, in degrees.
offset: f64,
},
/// A point with a tag.
PointWithTag {
/// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [f64; 2],
/// The tag.
tag: String,
},
/// A point where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
Point([f64; 2]),
}
/// Draw a tangental arc.
pub async fn tangental_arc(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (TangentalArcData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_tangental_arc(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
}
/// Draw an arc.
#[stdlib {
name = "tangentalArc",
}]
async fn inner_tangental_arc(
data: TangentalArcData,
sketch_group: Box<SketchGroup>,
args: Args,
) -> Result<Box<SketchGroup>, KclError> {
let from: Point2d = sketch_group.get_coords_from_paths()?;
let id = uuid::Uuid::new_v4();
let to = match &data {
TangentalArcData::RadiusAndOffset { radius, offset } => {
// Calculate the end point from the angle and radius.
let end_angle = Angle::from_degrees(*offset);
let start_angle = Angle::from_degrees(0.0);
let (_, to) = arc_center_and_end(from, start_angle, end_angle, *radius);
args.send_modeling_cmd(
id,
ModelingCmd::ExtendPath {
path: sketch_group.id,
segment: kittycad::types::PathSegment::TangentialArc {
radius: *radius,
offset: kittycad::types::Angle {
unit: kittycad::types::UnitAngle::Degrees,
value: *offset,
},
},
},
)
.await?;
to.into()
}
TangentalArcData::PointWithTag { to, .. } => {
args.send_modeling_cmd(
id,
ModelingCmd::ExtendPath {
path: sketch_group.id,
segment: kittycad::types::PathSegment::TangentialArcTo {
angle_snap_increment: None,
to: kittycad::types::Point3D {
x: to[0],
y: to[1],
z: 0.0,
},
},
},
)
.await?;
*to
}
TangentalArcData::Point(to) => {
args.send_modeling_cmd(
id,
ModelingCmd::ExtendPath {
path: sketch_group.id,
segment: kittycad::types::PathSegment::TangentialArcTo {
angle_snap_increment: None,
to: kittycad::types::Point3D {
x: to[0],
y: to[1],
z: 0.0,
},
},
},
)
.await?;
*to
}
};
let to = [from.x + to[0], from.y + to[1]];
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
to,
name: "".to_string(),
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
};
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path);
Ok(new_sketch_group)
}
/// Data to draw a tangental arc to a specific point.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
#[ts(export)]
#[serde(rename_all = "camelCase", untagged)]
pub enum TangentalArcToData {
/// A point with a tag.
PointWithTag {
/// Where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
to: [f64; 2],
/// The tag.
tag: String,
},
/// A point where the arc should end. Must lie in the same plane as the current path pen position. Must not be colinear with current path pen position.
Point([f64; 2]),
}
/// Draw a tangental arc to a specific point.
pub async fn tangental_arc_to(args: Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (TangentalArcToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_tangental_arc_to(data, sketch_group, args).await?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
}
/// Draw an arc.
#[stdlib {
name = "tangentalArcTo",
}]
async fn inner_tangental_arc_to(
data: TangentalArcToData,
sketch_group: Box<SketchGroup>,
args: Args,
) -> Result<Box<SketchGroup>, KclError> {
let from: Point2d = sketch_group.get_coords_from_paths()?;
let to = match &data {
TangentalArcToData::PointWithTag { to, .. } => to,
TangentalArcToData::Point(to) => to,
};
let delta = [to[0] - from.x, to[1] - from.y];
let id = uuid::Uuid::new_v4();
args.send_modeling_cmd(
id,
ModelingCmd::ExtendPath {
path: sketch_group.id,
segment: kittycad::types::PathSegment::TangentialArcTo {
angle_snap_increment: None,
to: kittycad::types::Point3D {
x: delta[0],
y: delta[1],
z: 0.0,
},
},
},
)
.await?;
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
to: *to,
name: if let TangentalArcToData::PointWithTag { tag, .. } = data {
tag.to_string()
} else {
"".to_string()
},
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
};
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path);
Ok(new_sketch_group)
}
/// Data to draw a bezier curve. /// Data to draw a bezier curve.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]

View File

@ -10,6 +10,15 @@ pub struct Angle {
degrees: f64, degrees: f64,
} }
impl From<kittycad::types::Angle> for Angle {
fn from(angle: kittycad::types::Angle) -> Self {
match angle.unit {
kittycad::types::UnitAngle::Degrees => Self::from_degrees(angle.value),
kittycad::types::UnitAngle::Radians => Self::from_radians(angle.value),
}
}
}
impl Angle { impl Angle {
const ZERO: Self = Self { degrees: 0.0 }; const ZERO: Self = Self { degrees: 0.0 };
/// Make an angle of the given degrees. /// Make an angle of the given degrees.

View File

@ -36,7 +36,7 @@ pub async fn execute_wasm(
// wasm_bindgen wrapper for execute // wasm_bindgen wrapper for execute
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
#[wasm_bindgen] #[wasm_bindgen]
pub async fn modify_ast_for_sketch( pub async fn modify_ast_for_sketch_wasm(
manager: kcl_lib::engine::conn_wasm::EngineCommandManager, manager: kcl_lib::engine::conn_wasm::EngineCommandManager,
program_str: &str, program_str: &str,
sketch_name: &str, sketch_name: &str,
@ -83,13 +83,13 @@ pub fn deserialize_files(data: &[u8]) -> Result<JsValue, JsError> {
// wasm_bindgen wrapper for lexer // wasm_bindgen wrapper for lexer
// test for this function and by extension lexer are done in javascript land src/lang/tokeniser.test.ts // test for this function and by extension lexer are done in javascript land src/lang/tokeniser.test.ts
#[wasm_bindgen] #[wasm_bindgen]
pub fn lexer_js(js: &str) -> Result<JsValue, JsError> { pub fn lexer_wasm(js: &str) -> Result<JsValue, JsError> {
let tokens = kcl_lib::token::lexer(js); let tokens = kcl_lib::token::lexer(js);
Ok(JsValue::from_serde(&tokens)?) Ok(JsValue::from_serde(&tokens)?)
} }
#[wasm_bindgen] #[wasm_bindgen]
pub fn parse_js(js: &str) -> Result<JsValue, String> { pub fn parse_wasm(js: &str) -> Result<JsValue, String> {
let tokens = kcl_lib::token::lexer(js); let tokens = kcl_lib::token::lexer(js);
let parser = kcl_lib::parser::Parser::new(tokens); let parser = kcl_lib::parser::Parser::new(tokens);
let program = parser.ast().map_err(String::from)?; let program = parser.ast().map_err(String::from)?;

View File

@ -148,6 +148,41 @@ show(bracket)"#;
twenty_twenty::assert_image("tests/executor/outputs/parametric.png", &result, 1.0); twenty_twenty::assert_image("tests/executor/outputs/parametric.png", &result, 1.0);
} }
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_execute_parametric_with_tan_arc_example() {
let code = r#"const sigmaAllow = 15000 // psi
const width = 11 // inch
const p = 150 // Force on shelf - lbs
const distance = 12 // inches
const FOS = 2
const thickness = sqrt(distance * p * FOS * 6 / ( sigmaAllow * width ))
const filletR = thickness * 2
const shelfMountL = 9
const wallMountL = 8
const bracket = startSketchAt([0, 0])
|> line([0, wallMountL], %)
|> tangentalArc({
radius: filletR,
offset: 90
}, %)
|> line([-shelfMountL, 0], %)
|> line([0, -thickness], %)
|> line([shelfMountL, 0], %)
|> tangentalArc({
radius: filletR - thickness,
offset: -90
}, %)
|> line([0, -wallMountL], %)
|> close(%)
|> extrude(width, %)
show(bracket)"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/parametric_with_tan_arc.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")] #[tokio::test(flavor = "multi_thread")]
async fn serial_test_execute_engine_error_return() { async fn serial_test_execute_engine_error_return() {
let code = r#"const part001 = startSketchAt([5.5229, 5.25217]) let code = r#"const part001 = startSketchAt([5.5229, 5.25217])
@ -252,3 +287,42 @@ box(-20, -5, 10)"#;
let result = execute_and_snapshot(code).await.unwrap(); let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/negative_args.png", &result, 1.0); twenty_twenty::assert_image("tests/executor/outputs/negative_args.png", &result, 1.0);
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_basic_tangental_arc() {
let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %)
|> tangentalArc({radius: 5, offset: 90}, %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/tangental_arc.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_basic_tangental_arc_with_point() {
let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %)
|> tangentalArc([-5, 5], %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/tangental_arc_with_point.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_basic_tangental_arc_to() {
let code = r#"const boxSketch = startSketchAt([0, 0])
|> line([0, 10], %)
|> tangentalArcTo([-5, 15], %)
|> line([5, -15], %)
|> extrude(10, %)
"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/tangental_arc_to.png", &result, 1.0);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

166
yarn.lock
View File

@ -8,9 +8,9 @@
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
"@adobe/css-tools@^4.0.1": "@adobe/css-tools@^4.0.1":
version "4.2.0" version "4.3.1"
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.2.0.tgz#e1a84fca468f4b337816fcb7f0964beb620ba855" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28"
integrity sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA== integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==
"@alloc/quick-lru@^5.2.0": "@alloc/quick-lru@^5.2.0":
version "5.2.0" version "5.2.0"
@ -1530,10 +1530,10 @@
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
"@kittycad/lib@^0.0.39": "@kittycad/lib@^0.0.40":
version "0.0.39" version "0.0.40"
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.39.tgz#e548acf5ff7d45a1f1ec9ad2c61ddcfc30d159b7" resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.40.tgz#0ba00c642e76648fb7cb1337e799b9d24724312d"
integrity sha512-cB4wNjsKTMpJUn/kMK3qtkVAqB1csSglqThe+bj02nC1kWTB1XgYxksooc/Gzl1MoK1/n0OPQcbOb7Tojb836A== integrity sha512-R8sQKLWe3lQC7l7cyY49oFgeiMvRh8+bCaaoLiIVYT+YiE9TaS+uwwF1+sR7MiX6YZp/YCBBPFGj4Ci0VHC9Bg==
dependencies: dependencies:
node-fetch "3.3.2" node-fetch "3.3.2"
openapi-types "^12.0.0" openapi-types "^12.0.0"
@ -2175,44 +2175,44 @@
istanbul-reports "^3.1.5" istanbul-reports "^3.1.5"
test-exclude "^6.0.0" test-exclude "^6.0.0"
"@vitest/expect@0.34.1": "@vitest/expect@0.34.6":
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.34.1.tgz#2ba6cb96695f4b4388c6d955423a81afc79b8da0" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.34.6.tgz#608a7b7a9aa3de0919db99b4cc087340a03ea77e"
integrity sha512-q2CD8+XIsQ+tHwypnoCk8Mnv5e6afLFvinVGCq3/BOT4kQdVQmY6rRfyKkwcg635lbliLPqbunXZr+L1ssUWiQ== integrity sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==
dependencies: dependencies:
"@vitest/spy" "0.34.1" "@vitest/spy" "0.34.6"
"@vitest/utils" "0.34.1" "@vitest/utils" "0.34.6"
chai "^4.3.7" chai "^4.3.10"
"@vitest/runner@0.34.1": "@vitest/runner@0.34.6":
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.34.1.tgz#23c21ba1db8bff610988c72744db590d0fb6c4ba" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.34.6.tgz#6f43ca241fc96b2edf230db58bcde5b974b8dcaf"
integrity sha512-YfQMpYzDsYB7yqgmlxZ06NI4LurHWfrH7Wy3Pvf/z/vwUSgq1zLAb1lWcItCzQG+NVox+VvzlKQrYEXb47645g== integrity sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==
dependencies: dependencies:
"@vitest/utils" "0.34.1" "@vitest/utils" "0.34.6"
p-limit "^4.0.0" p-limit "^4.0.0"
pathe "^1.1.1" pathe "^1.1.1"
"@vitest/snapshot@0.34.1": "@vitest/snapshot@0.34.6":
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-0.34.1.tgz#814c65f8e714eaf255f47838541004b2a2ba28e6" resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-0.34.6.tgz#b4528cf683b60a3e8071cacbcb97d18b9d5e1d8b"
integrity sha512-0O9LfLU0114OqdF8lENlrLsnn024Tb1CsS9UwG0YMWY2oGTQfPtkW+B/7ieyv0X9R2Oijhi3caB1xgGgEgclSQ== integrity sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==
dependencies: dependencies:
magic-string "^0.30.1" magic-string "^0.30.1"
pathe "^1.1.1" pathe "^1.1.1"
pretty-format "^29.5.0" pretty-format "^29.5.0"
"@vitest/spy@0.34.1": "@vitest/spy@0.34.6":
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.34.1.tgz#2f77234a3d554c5dea664943f2caaab92d304f3c" resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.34.6.tgz#b5e8642a84aad12896c915bce9b3cc8cdaf821df"
integrity sha512-UT4WcI3EAPUNO8n6y9QoEqynGGEPmmRxC+cLzneFFXpmacivjHZsNbiKD88KUScv5DCHVDgdBsLD7O7s1enFcQ== integrity sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==
dependencies: dependencies:
tinyspy "^2.1.1" tinyspy "^2.1.1"
"@vitest/utils@0.34.1": "@vitest/utils@0.34.6":
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.34.1.tgz#e5545c6618775fb9a2dae2a80d94fc2f35222233" resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.34.6.tgz#38a0a7eedddb8e7291af09a2409cb8a189516968"
integrity sha512-/ql9dsFi4iuEbiNcjNHQWXBum7aL8pyhxvfnD9gNtbjR9fUKAjxhj4AA3yfLXg6gJpMGGecvtF8Au2G9y3q47Q== integrity sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==
dependencies: dependencies:
diff-sequences "^29.4.3" diff-sequences "^29.4.3"
loupe "^2.3.6" loupe "^2.3.6"
@ -2597,18 +2597,18 @@ caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001517:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz#b3ca93904cb4699c01218246c4d77a71dbe97150" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz#b3ca93904cb4699c01218246c4d77a71dbe97150"
integrity sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA== integrity sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==
chai@^4.3.7: chai@^4.3.10:
version "4.3.7" version "4.3.10"
resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384"
integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==
dependencies: dependencies:
assertion-error "^1.1.0" assertion-error "^1.1.0"
check-error "^1.0.2" check-error "^1.0.3"
deep-eql "^4.1.2" deep-eql "^4.1.3"
get-func-name "^2.0.0" get-func-name "^2.0.2"
loupe "^2.3.1" loupe "^2.3.6"
pathval "^1.1.1" pathval "^1.1.1"
type-detect "^4.0.5" type-detect "^4.0.8"
chalk@^2.0.0: chalk@^2.0.0:
version "2.4.2" version "2.4.2"
@ -2635,10 +2635,12 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
check-error@^1.0.2: check-error@^1.0.3:
version "1.0.2" version "1.0.3"
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694"
integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==
dependencies:
get-func-name "^2.0.2"
chokidar@^3.5.3: chokidar@^3.5.3:
version "3.5.3" version "3.5.3"
@ -2825,7 +2827,7 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
dependencies: dependencies:
ms "2.1.2" ms "2.1.2"
deep-eql@^4.1.2: deep-eql@^4.1.3:
version "4.1.3" version "4.1.3"
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
@ -3545,10 +3547,10 @@ gensync@^1.0.0-beta.2:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
get-func-name@^2.0.0: get-func-name@^2.0.0, get-func-name@^2.0.2:
version "2.0.0" version "2.0.2"
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1:
version "1.2.1" version "1.2.1"
@ -4271,7 +4273,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies: dependencies:
js-tokens "^3.0.0 || ^4.0.0" js-tokens "^3.0.0 || ^4.0.0"
loupe@^2.3.1, loupe@^2.3.6: loupe@^2.3.6:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53"
integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==
@ -4737,10 +4739,10 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.4.19, postcss@^8.4.23, postcss@^8.4.26: postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.31:
version "8.4.27" version "8.4.31"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
dependencies: dependencies:
nanoid "^3.3.6" nanoid "^3.3.6"
picocolors "^1.0.0" picocolors "^1.0.0"
@ -5063,10 +5065,10 @@ rollup@^2.77.2:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
rollup@^3.25.2: rollup@^3.27.1:
version "3.27.0" version "3.29.4"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.27.0.tgz#15bd07e2e1cbfa9255bf6a3f04a432621c2f3550" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981"
integrity sha512-aOltLCrYZ0FhJDm7fCqwTjIUEVjWjcydKBV/Zeid6Mn8BWgDCUBBWT5beM5ieForYNo/1ZHuGJdka26kvQ3Gzg== integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
@ -5520,7 +5522,7 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies: dependencies:
prelude-ls "^1.2.1" prelude-ls "^1.2.1"
type-detect@^4.0.0, type-detect@^4.0.5: type-detect@^4.0.0, type-detect@^4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
@ -5681,17 +5683,17 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
vite-node@0.34.1: vite-node@0.34.6:
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.34.1.tgz#144900ca4bd54cc419c501d671350bcbc07eb1ee" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.34.6.tgz#34d19795de1498562bf21541a58edcd106328a17"
integrity sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w== integrity sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==
dependencies: dependencies:
cac "^6.7.14" cac "^6.7.14"
debug "^4.3.4" debug "^4.3.4"
mlly "^1.4.0" mlly "^1.4.0"
pathe "^1.1.1" pathe "^1.1.1"
picocolors "^1.0.0" picocolors "^1.0.0"
vite "^3.0.0 || ^4.0.0" vite "^3.0.0 || ^4.0.0 || ^5.0.0-0"
vite-plugin-eslint@^1.8.1: vite-plugin-eslint@^1.8.1:
version "1.8.1" version "1.8.1"
@ -5711,34 +5713,34 @@ vite-tsconfig-paths@^4.2.0:
globrex "^0.1.2" globrex "^0.1.2"
tsconfck "^2.1.0" tsconfck "^2.1.0"
"vite@^3.0.0 || ^4.0.0", vite@^4.4.3: "vite@^3.0.0 || ^4.0.0 || ^5.0.0-0", "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0", vite@^4.4.3:
version "4.4.8" version "4.4.9"
resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.8.tgz#31e4a438f8748695c68bd57ffd262ba93540fdf7" resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.9.tgz#1402423f1a2f8d66fd8d15e351127c7236d29d3d"
integrity sha512-LONawOUUjxQridNWGQlNizfKH89qPigK36XhMI7COMGztz8KNY0JHim7/xDd71CZwGT4HtSRgI7Hy+RlhG0Gvg== integrity sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==
dependencies: dependencies:
esbuild "^0.18.10" esbuild "^0.18.10"
postcss "^8.4.26" postcss "^8.4.27"
rollup "^3.25.2" rollup "^3.27.1"
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" fsevents "~2.3.2"
vitest@^0.34.1: vitest@^0.34.6:
version "0.34.1" version "0.34.6"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.34.1.tgz#3ad7f845e7a9fb0d72ab703cae832a54b8469e1e" resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.34.6.tgz#44880feeeef493c04b7f795ed268f24a543250d7"
integrity sha512-G1PzuBEq9A75XSU88yO5G4vPT20UovbC/2osB2KEuV/FisSIIsw7m5y2xMdB7RsAGHAfg2lPmp2qKr3KWliVlQ== integrity sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==
dependencies: dependencies:
"@types/chai" "^4.3.5" "@types/chai" "^4.3.5"
"@types/chai-subset" "^1.3.3" "@types/chai-subset" "^1.3.3"
"@types/node" "*" "@types/node" "*"
"@vitest/expect" "0.34.1" "@vitest/expect" "0.34.6"
"@vitest/runner" "0.34.1" "@vitest/runner" "0.34.6"
"@vitest/snapshot" "0.34.1" "@vitest/snapshot" "0.34.6"
"@vitest/spy" "0.34.1" "@vitest/spy" "0.34.6"
"@vitest/utils" "0.34.1" "@vitest/utils" "0.34.6"
acorn "^8.9.0" acorn "^8.9.0"
acorn-walk "^8.2.0" acorn-walk "^8.2.0"
cac "^6.7.14" cac "^6.7.14"
chai "^4.3.7" chai "^4.3.10"
debug "^4.3.4" debug "^4.3.4"
local-pkg "^0.4.3" local-pkg "^0.4.3"
magic-string "^0.30.1" magic-string "^0.30.1"
@ -5748,8 +5750,8 @@ vitest@^0.34.1:
strip-literal "^1.0.1" strip-literal "^1.0.1"
tinybench "^2.5.0" tinybench "^2.5.0"
tinypool "^0.7.0" tinypool "^0.7.0"
vite "^3.0.0 || ^4.0.0" vite "^3.1.0 || ^4.0.0 || ^5.0.0-0"
vite-node "0.34.1" vite-node "0.34.6"
why-is-node-running "^2.2.2" why-is-node-running "^2.2.2"
vscode-jsonrpc@8.1.0, vscode-jsonrpc@^8.1.0: vscode-jsonrpc@8.1.0, vscode-jsonrpc@^8.1.0: