Skip to content

Commit

Permalink
Rebuilds
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Oct 13, 2024
1 parent c91b32b commit 14d08fe
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 42 deletions.
49 changes: 23 additions & 26 deletions resources/resource_transformers/js/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"encoding/json"
"fmt"
"os"
"path"
"path/filepath"
"strings"

Expand Down Expand Up @@ -256,10 +255,12 @@ func createBuildPlugins(c *Client, depsManager identity.Manager, opts Options) (

resolveImport := func(args api.OnResolveArgs) (api.OnResolveResult, error) {
impPath := args.Path
shimmed := false
if opts.Shims != nil {
override, found := opts.Shims[impPath]
if found {
impPath = override
shimmed = true
}
}

Expand All @@ -269,42 +270,38 @@ func createBuildPlugins(c *Client, depsManager identity.Manager, opts Options) (
}
}

dodebug := strings.Contains(impPath, "css")
if dodebug {
// impPath = strings.TrimPrefix(impPath, "/")
}
importer := args.Importer
// TODO1 todelido.
if false && dodebug {
impPath = path.Join("js/hugoheadlessui/components", impPath)
} else {
isStdin := importer == stdinImporter
var relDir string
if !isStdin {
if strings.HasPrefix(importer, "@hugo-virtual") {
// TODO1 constants.
relDir = filepath.Dir(strings.TrimPrefix(importer, "@hugo-virtual"))
} else {
rel, found := fs.MakePathRelative(importer, true)

if !found {
isStdin := importer == stdinImporter
var relDir string
if !isStdin {
if strings.HasPrefix(importer, "@hugo-virtual") {
// TODO1 constants.
relDir = filepath.Dir(strings.TrimPrefix(importer, "@hugo-virtual"))
} else {
rel, found := fs.MakePathRelative(importer, true)

if !found {
if shimmed {
relDir = opts.SourceDir
} else {
// Not in any of the /assets folders.
// This is an import from a node_modules, let
// ESBuild resolve this.
return api.OnResolveResult{}, nil
}

} else {
relDir = filepath.Dir(rel)
}
} else {
relDir = opts.SourceDir
}
} else {
relDir = opts.SourceDir
}

// Imports not starting with a "." is assumed to live relative to /assets.
// Hugo makes no assumptions about the directory structure below /assets.
if relDir != "" && strings.HasPrefix(impPath, ".") {
impPath = filepath.Join(relDir, impPath)
}
// Imports not starting with a "." is assumed to live relative to /assets.
// Hugo makes no assumptions about the directory structure below /assets.
if relDir != "" && strings.HasPrefix(impPath, ".") {
impPath = filepath.Join(relDir, impPath)
}

m := resolveComponentInAssets(fs.Fs, impPath)
Expand Down
91 changes: 76 additions & 15 deletions tpl/js/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import (
"os"
"path"
"path/filepath"
"reflect"
"sort"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/evanw/esbuild/pkg/api"
Expand Down Expand Up @@ -431,15 +433,22 @@ func (b *batcher) Config() OptionsSetter {
return b.configOptions.Get()
}

var _ resource.StaleInfo = (*options)(nil)

type options struct {
getOnce[*optionsSetter]
}

func (o *options) Reset() {
mu := o.once.ResetWithLock()
o.v.staleVersion.Store(0)
defer mu.Unlock()
}

func (o *options) StaleVersion() uint32 {
return o.v.staleVersion.Load()
}

// func (o ScriptOptions) Compile(m map[string]any) (*ScriptOptions, error) {

func newOptions() *options {
Expand All @@ -449,11 +458,46 @@ func newOptions() *options {
}

type optionsSetter struct {
opts map[string]any
staleVersion atomic.Uint32
opts map[string]any
}

// TODO1 try to avoid stale page resources when changing the head.
func (o *optionsSetter) SetOptions(m map[string]any) string {
fmt.Println("SetOptions", m) // TODO1
if o.opts != nil {
if reflect.DeepEqual(o.opts, m) {
return ""
}
var isStale bool
for k, v := range m {

vv, found := o.opts[k]
if !found {
isStale = true
} else {
if si, ok := vv.(resource.StaleInfo); ok {
isStale = si.StaleVersion() > 0
} else {
if k == "importContext" {
fmt.Println("importContext", v, vv)
// TODO1
continue
}
isStale = !reflect.DeepEqual(v, vv)
}
}

if isStale {
break
}
}

if !isStale {
return ""
}

o.staleVersion.Add(1)
}
o.opts = m
return ""
}
Expand Down Expand Up @@ -590,6 +634,7 @@ func (p *Package) IdentifierBase() string {
return p.id
}

// TODO1 need this? We cannot cache this value for long.
func (p *Package) StaleVersion() uint32 {
p.b.mu.Lock()
defer p.b.mu.Unlock()
Expand All @@ -606,7 +651,7 @@ func (p *Package) MarkStale() {
func (p *Package) IsProbablyDependency(other identity.Identity) bool {
depsFinder := identity.NewFinder(identity.FinderConfig{})
var b bool
p.forEeachResource(func(rr resource.Resource) bool {
p.forEeachStaleInfo(func(rr resource.StaleInfo) bool {
identity.WalkIdentitiesShallow(other, func(level int, left identity.Identity) bool {
identity.WalkIdentitiesShallow(rr, func(level int, right identity.Identity) bool {
if i := depsFinder.Contains(left, right, -1); i > 0 {
Expand All @@ -624,23 +669,38 @@ func (p *Package) IsProbablyDependency(other identity.Identity) bool {
return b
}

func (p *Package) forEeachResource(f func(r resource.Resource) bool) {
for _, v := range p.b.scriptGroups.Sorted() {
// You should not depend on the invocation order when calling this.
// TODO1 check that this does not get called on first build.
func (p *Package) forEeachStaleInfo(f func(si resource.StaleInfo) bool) {
check := func(v any) bool {
if si, ok := v.(resource.StaleInfo); ok {
return f(si)
}
return false
}
for _, v := range p.b.scriptGroups {
if b := func() bool {
v.mu.Lock()
defer v.mu.Unlock()
/*callbackOptions := v.GetCallbackOptions() // TODO1 validate.
if callbackOptions != nil {
if f(callbackOptions.Resource) { // TODO1 options.

for _, vv := range v.instancesOptions {
if check(vv) {
return true
}
}
*/
for _, vv := range v.scripts.Sorted() {
if f(vv.Resource) {

for _, vv := range v.scriptsOptions {
if check(vv) {
return true
}
}

for _, vv := range v.callbacksOptions {
if check(vv) {
return true
}
}

return false
}(); b {
return
Expand All @@ -649,10 +709,10 @@ func (p *Package) forEeachResource(f func(r resource.Resource) bool) {
}

func (p *Package) calculateStaleVersion() uint32 {
// Return the first 0 zero value of the resources in this bundle.
// Return the first 0 zero value found.
var i uint32
p.forEeachResource(func(r resource.Resource) bool {
if i = resource.StaleVersion(r); i > 0 {
p.forEeachStaleInfo(func(si resource.StaleInfo) bool {
if i = si.StaleVersion(); i > 0 {
return true
}
return false
Expand Down Expand Up @@ -692,7 +752,8 @@ func (b *batcher) build() (*Package, error) {
b.mu.Lock()
defer b.mu.Unlock()

if b.prevBuild != nil {
// Use the unexported calculateStaleVersion
if b.prevBuild != nil && b.prevBuild.calculateStaleVersion() == 0 {
return b.prevBuild, nil
}

Expand Down
3 changes: 2 additions & 1 deletion tpl/js/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ func New(deps *deps.Deps) *Namespace {
bundlesCache: dynacache.GetOrCreatePartition[string, *Package](
deps.MemCache,
"/jsb1",
dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 10},
// Mark it to clear on rebuild, but each package evaluate itself for changes.
dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnRebuild, Weight: 10},
),
client: js.New(deps.BaseFs.Assets, deps.ResourceSpec),
createClient: create.New(deps.ResourceSpec),
Expand Down

0 comments on commit 14d08fe

Please sign in to comment.