Skip to content

Commit a9cd808

Browse files
committed
update HasCurrent to be atomic, dont re-render on ref update, ensure abs paths for env vars, dont pass position back for refs
1 parent b5e358e commit a9cd808

6 files changed

Lines changed: 69 additions & 25 deletions

File tree

tsunami/app/defaultclient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ func DeepCopy[T any](v T) T {
167167
// If the ref is nil or not current, the operation is ignored.
168168
// This function must be called within a component context.
169169
func QueueRefOp(ref *vdom.VDomRef, op vdom.VDomRefOperation) {
170-
if ref == nil || !ref.HasCurrent {
170+
if ref == nil || !ref.HasCurrent.Load() {
171171
return
172172
}
173173
if op.RefId == "" {

tsunami/cmd/main-tsunami.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,22 @@ func validateEnvironmentVars(opts *build.BuildOpts) error {
4141
if scaffoldPath == "" {
4242
return fmt.Errorf("%s environment variable must be set", EnvTsunamiScaffoldPath)
4343
}
44+
absScaffoldPath, err := filepath.Abs(scaffoldPath)
45+
if err != nil {
46+
return fmt.Errorf("failed to resolve %s to absolute path: %w", EnvTsunamiScaffoldPath, err)
47+
}
4448

4549
sdkReplacePath := os.Getenv(EnvTsunamiSdkReplacePath)
4650
if sdkReplacePath == "" {
4751
return fmt.Errorf("%s environment variable must be set", EnvTsunamiSdkReplacePath)
4852
}
53+
absSdkReplacePath, err := filepath.Abs(sdkReplacePath)
54+
if err != nil {
55+
return fmt.Errorf("failed to resolve %s to absolute path: %w", EnvTsunamiSdkReplacePath, err)
56+
}
4957

50-
opts.ScaffoldPath = scaffoldPath
51-
opts.SdkReplacePath = sdkReplacePath
58+
opts.ScaffoldPath = absScaffoldPath
59+
opts.SdkReplacePath = absSdkReplacePath
5260

5361
// NodePath is optional
5462
if nodePath := os.Getenv(EnvTsunamiNodePath); nodePath != "" {

tsunami/engine/rootelem.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,8 @@ func (r *RootElem) UpdateRef(updateRef rpctypes.VDomRefUpdate) {
443443
if !ok {
444444
return
445445
}
446-
ref.HasCurrent = updateRef.HasCurrent
446+
ref.HasCurrent.Store(updateRef.HasCurrent)
447447
ref.Position = updateRef.Position
448-
r.addRenderWork(waveId)
449448
}
450449

451450
func (r *RootElem) QueueRefOp(op vdom.VDomRefOperation) {

tsunami/frontend/src/types/vdom.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ type VDomRef = {
103103
type: "ref";
104104
refid: string;
105105
trackposition?: boolean;
106-
position?: VDomRefPosition;
107106
hascurrent?: boolean;
108107
};
109108

tsunami/templates/package.json.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"email": "info@commandline.dev"
1111
},
1212
"dependencies": {
13-
"@tailwindcss/cli": "^4.1.13",
14-
"tailwindcss": "^4.1.13"
13+
"@tailwindcss/cli": "^4.2.1",
14+
"tailwindcss": "^4.2.1"
1515
}
1616
}

tsunami/vdom/vdom_types.go

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
// Copyright 2025, Command Line Inc.
1+
// Copyright 2026, Command Line Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

44
package vdom
55

6+
import (
7+
"encoding/json"
8+
"sync/atomic"
9+
)
10+
611
const TextTag = "#text"
712
const WaveTextTag = "wave:text"
813
const WaveNullTag = "wave:null"
@@ -36,8 +41,41 @@ type VDomRef struct {
3641
Type string `json:"type" tstype:"\"ref\""`
3742
RefId string `json:"refid"`
3843
TrackPosition bool `json:"trackposition,omitempty"`
39-
Position *VDomRefPosition `json:"position,omitempty"`
40-
HasCurrent bool `json:"hascurrent,omitempty"`
44+
Position *VDomRefPosition `json:"-"`
45+
HasCurrent atomic.Bool `json:"-"`
46+
}
47+
48+
func (r *VDomRef) MarshalJSON() ([]byte, error) {
49+
type vdomRefAlias struct {
50+
Type string `json:"type"`
51+
RefId string `json:"refid"`
52+
TrackPosition bool `json:"trackposition,omitempty"`
53+
HasCurrent bool `json:"hascurrent,omitempty"`
54+
}
55+
return json.Marshal(vdomRefAlias{
56+
Type: r.Type,
57+
RefId: r.RefId,
58+
TrackPosition: r.TrackPosition,
59+
HasCurrent: r.HasCurrent.Load(),
60+
})
61+
}
62+
63+
func (r *VDomRef) UnmarshalJSON(data []byte) error {
64+
type vdomRefAlias struct {
65+
Type string `json:"type"`
66+
RefId string `json:"refid"`
67+
TrackPosition bool `json:"trackposition,omitempty"`
68+
HasCurrent bool `json:"hascurrent,omitempty"`
69+
}
70+
var alias vdomRefAlias
71+
if err := json.Unmarshal(data, &alias); err != nil {
72+
return err
73+
}
74+
r.Type = alias.Type
75+
r.RefId = alias.RefId
76+
r.TrackPosition = alias.TrackPosition
77+
r.HasCurrent.Store(alias.HasCurrent)
78+
return nil
4179
}
4280

4381
type VDomSimpleRef[T any] struct {
@@ -66,14 +104,14 @@ type VDomEvent struct {
66104
WaveId string `json:"waveid"`
67105
EventType string `json:"eventtype"` // usually the prop name (e.g. onClick, onKeyDown)
68106
GlobalEventType string `json:"globaleventtype,omitempty"`
69-
TargetValue string `json:"targetvalue,omitempty"` // set for onChange events on input/textarea/select
107+
TargetValue string `json:"targetvalue,omitempty"` // set for onChange events on input/textarea/select
70108
TargetChecked bool `json:"targetchecked,omitempty"` // set for onChange events on checkbox/radio inputs
71-
TargetName string `json:"targetname,omitempty"` // target element's name attribute
72-
TargetId string `json:"targetid,omitempty"` // target element's id attribute
73-
TargetFiles []VDomFileData `json:"targetfiles,omitempty"` // set for onChange events on file inputs
74-
KeyData *VDomKeyboardEvent `json:"keydata,omitempty"` // set for onKeyDown events
75-
MouseData *VDomPointerData `json:"mousedata,omitempty"` // set for onClick, onMouseDown, onMouseUp, onDoubleClick events
76-
FormData *VDomFormData `json:"formdata,omitempty"` // set for onSubmit events on forms
109+
TargetName string `json:"targetname,omitempty"` // target element's name attribute
110+
TargetId string `json:"targetid,omitempty"` // target element's id attribute
111+
TargetFiles []VDomFileData `json:"targetfiles,omitempty"` // set for onChange events on file inputs
112+
KeyData *VDomKeyboardEvent `json:"keydata,omitempty"` // set for onKeyDown events
113+
MouseData *VDomPointerData `json:"mousedata,omitempty"` // set for onClick, onMouseDown, onMouseUp, onDoubleClick events
114+
FormData *VDomFormData `json:"formdata,omitempty"` // set for onSubmit events on forms
77115
}
78116

79117
type VDomKeyboardEvent struct {
@@ -115,13 +153,13 @@ type VDomPointerData struct {
115153
}
116154

117155
type VDomFormData struct {
118-
Action string `json:"action,omitempty"`
119-
Method string `json:"method"`
120-
Enctype string `json:"enctype"`
121-
FormId string `json:"formid,omitempty"`
122-
FormName string `json:"formname,omitempty"`
123-
Fields map[string][]string `json:"fields"`
124-
Files map[string][]VDomFileData `json:"files"`
156+
Action string `json:"action,omitempty"`
157+
Method string `json:"method"`
158+
Enctype string `json:"enctype"`
159+
FormId string `json:"formid,omitempty"`
160+
FormName string `json:"formname,omitempty"`
161+
Fields map[string][]string `json:"fields"`
162+
Files map[string][]VDomFileData `json:"files"`
125163
}
126164

127165
func (f *VDomFormData) GetField(fieldName string) string {

0 commit comments

Comments
 (0)