updated ebiten version from 2.7.9 to 2.9.9

This commit is contained in:
2026-06-15 19:06:55 +02:00
parent 21edbc41c4
commit db1b625069
405 changed files with 31913 additions and 12595 deletions
+143 -72
View File
@@ -24,13 +24,24 @@ import (
)
type FileEntryFS struct {
rootEntry js.Value
rootEntries []js.Value
}
func NewFileEntryFS(root js.Value) *FileEntryFS {
return &FileEntryFS{
rootEntry: root,
func NewFileEntryFS(rootEntries []js.Value) (*FileEntryFS, error) {
// Check all the full paths are the same.
var fullpath string
for _, ent := range rootEntries {
if fullpath == "" {
fullpath = ent.Get("fullPath").String()
continue
}
if fullpath != ent.Get("fullPath").String() {
return nil, errors.New("file: all the full paths must be the same")
}
}
return &FileEntryFS{
rootEntries: rootEntries,
}, nil
}
func (f *FileEntryFS) Open(name string) (fs.File, error) {
@@ -43,33 +54,55 @@ func (f *FileEntryFS) Open(name string) (fs.File, error) {
}
if name == "." {
return &dir{entry: f.rootEntry}, nil
var dirName string
for _, ent := range f.rootEntries {
if dirName == "" {
dirName = ent.Get("name").String()
continue
}
if dirName != ent.Get("name").String() {
return nil, &fs.PathError{
Op: "open",
Path: name,
Err: errors.New("invalid directory"),
}
}
}
return &dir{
name: dirName,
dirEntries: f.rootEntries,
}, nil
}
var chEntry chan js.Value
cbSuccess := js.FuncOf(func(this js.Value, args []js.Value) any {
chEntry <- args[0]
close(chEntry)
return nil
})
defer cbSuccess.Release()
for _, ent := range f.rootEntries {
var chEntry chan js.Value
cbSuccess := js.FuncOf(func(this js.Value, args []js.Value) any {
chEntry <- args[0]
close(chEntry)
return nil
})
defer cbSuccess.Release()
cbFailure := js.FuncOf(func(this js.Value, args []js.Value) any {
close(chEntry)
return nil
})
defer cbFailure.Release()
cbFailure := js.FuncOf(func(this js.Value, args []js.Value) any {
close(chEntry)
return nil
})
defer cbFailure.Release()
chEntry = make(chan js.Value)
f.rootEntry.Call("getFile", name, nil, cbSuccess, cbFailure)
if entry := <-chEntry; entry.Truthy() {
return &file{entry: entry}, nil
}
chEntry = make(chan js.Value)
ent.Call("getFile", name, nil, cbSuccess, cbFailure)
if entry := <-chEntry; entry.Truthy() {
return &file{entry: entry}, nil
}
chEntry = make(chan js.Value)
f.rootEntry.Call("getDirectory", name, nil, cbSuccess, cbFailure)
if entry := <-chEntry; entry.Truthy() {
return &dir{entry: entry}, nil
chEntry = make(chan js.Value)
ent.Call("getDirectory", name, nil, cbSuccess, cbFailure)
if entry := <-chEntry; entry.Truthy() {
return &dir{
name: entry.Get("name").String(),
dirEntries: []js.Value{entry},
}, nil
}
}
return nil, &fs.PathError{
@@ -79,6 +112,33 @@ func (f *FileEntryFS) Open(name string) (fs.File, error) {
}
}
func (f *FileEntryFS) ReadDir(name string) ([]fs.DirEntry, error) {
if !fs.ValidPath(name) {
return nil, &fs.PathError{
Op: "readdir",
Path: name,
Err: fs.ErrNotExist,
}
}
ent, err := f.Open(name)
if err != nil {
return nil, err
}
defer func() {
_ = ent.Close()
}()
d, ok := ent.(*dir)
if !ok {
return nil, &fs.PathError{
Op: "readdir",
Path: name,
Err: fs.ErrInvalid,
}
}
return d.ReadDir(-1)
}
type file struct {
entry js.Value
file js.Value
@@ -109,8 +169,8 @@ func (f *file) ensureFile() js.Value {
func (f *file) Stat() (fs.FileInfo, error) {
return &fileInfo{
entry: f.entry,
file: f.ensureFile(),
name: f.entry.Get("name").String(),
file: f.ensureFile(),
}, nil
}
@@ -163,21 +223,22 @@ func (f *file) Close() error {
}
type dir struct {
entry js.Value
entries []js.Value
offset int
name string
dirEntries []js.Value
fileEntries []js.Value
offset int
}
func (d *dir) Stat() (fs.FileInfo, error) {
return &fileInfo{
entry: d.entry,
name: d.name,
}, nil
}
func (d *dir) Read(buf []byte) (int, error) {
return 0, &fs.PathError{
Op: "read",
Path: d.entry.Get("name").String(),
Path: d.name,
Err: errors.New("is a directory"),
}
}
@@ -187,43 +248,52 @@ func (d *dir) Close() error {
}
func (d *dir) ReadDir(count int) ([]fs.DirEntry, error) {
if d.entries == nil {
ch := make(chan struct{})
var rec js.Func
cb := js.FuncOf(func(this js.Value, args []js.Value) any {
entries := args[0]
if entries.Length() == 0 {
close(ch)
if d.fileEntries == nil {
names := map[string]struct{}{}
for _, dirEntry := range d.dirEntries {
ch := make(chan struct{})
var rec js.Func
cb := js.FuncOf(func(this js.Value, args []js.Value) any {
entries := args[0]
if entries.Length() == 0 {
close(ch)
return nil
}
for i := 0; i < entries.Length(); i++ {
ent := entries.Index(i)
name := ent.Get("name").String()
// A name can be empty when this directory is a root directory.
if name == "" {
continue
}
// Avoid entry duplications. Entry duplications happen when multiple files are dropped on Chrome.
if _, ok := names[name]; ok {
continue
}
if !ent.Get("isFile").Bool() && !ent.Get("isDirectory").Bool() {
continue
}
d.fileEntries = append(d.fileEntries, ent)
names[name] = struct{}{}
}
rec.Value.Call("call")
return nil
}
for i := 0; i < entries.Length(); i++ {
ent := entries.Index(i)
// A name can be empty when this directory is a root directory.
if ent.Get("name").String() == "" {
continue
}
if !ent.Get("isFile").Bool() && !ent.Get("isDirectory").Bool() {
continue
}
d.entries = append(d.entries, ent)
}
})
defer cb.Release()
reader := dirEntry.Call("createReader")
rec = js.FuncOf(func(this js.Value, args []js.Value) any {
reader.Call("readEntries", cb)
return nil
})
defer rec.Release()
rec.Value.Call("call")
return nil
})
defer cb.Release()
reader := d.entry.Call("createReader")
rec = js.FuncOf(func(this js.Value, args []js.Value) any {
reader.Call("readEntries", cb)
return nil
})
defer rec.Release()
rec.Value.Call("call")
<-ch
<-ch
}
}
n := len(d.entries) - d.offset
n := len(d.fileEntries) - d.offset
if n == 0 {
if count <= 0 {
@@ -238,11 +308,12 @@ func (d *dir) ReadDir(count int) ([]fs.DirEntry, error) {
ents := make([]fs.DirEntry, n)
for i := range ents {
entry := d.fileEntries[d.offset+i]
fi := &fileInfo{
entry: d.entries[d.offset+i],
name: entry.Get("name").String(),
}
if fi.entry.Get("isFile").Bool() {
fi.file = getFile(fi.entry)
if entry.Get("isFile").Bool() {
fi.file = getFile(entry)
}
ents[i] = fs.FileInfoToDirEntry(fi)
}
@@ -252,12 +323,12 @@ func (d *dir) ReadDir(count int) ([]fs.DirEntry, error) {
}
type fileInfo struct {
entry js.Value
file js.Value
name string
file js.Value
}
func (f *fileInfo) Name() string {
return f.entry.Get("name").String()
return f.name
}
func (f *fileInfo) Size() int64 {
+44 -1
View File
@@ -54,6 +54,12 @@ func (v *VirtualFS) Open(name string) (fs.File, error) {
}
}
// It is implicitly assumed that all the real paths are under the same directory.
// For name == ".", return a special virtual root directory.
// Unfortunately it is not possible to return a real directory here because
// v.paths might not include some files in the same directory.
// TODO: Calculate the common ancestor directory of v.paths and use it.
if name == "." {
return v.newRootFS(), nil
}
@@ -64,7 +70,8 @@ func (v *VirtualFS) Open(name string) (fs.File, error) {
if filepath.Base(realPath) != es[0] {
continue
}
// TODO: Does this work on Windows?
// os.File should implement fs.File interface, so this should be fine even on Windows.
// See https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/os/file.go;l=695-710
return os.Open(filepath.Join(append([]string{realPath}, es[1:]...)...))
}
@@ -75,6 +82,42 @@ func (v *VirtualFS) Open(name string) (fs.File, error) {
}
}
func (v *VirtualFS) ReadDir(name string) ([]fs.DirEntry, error) {
if !fs.ValidPath(name) {
return nil, &fs.PathError{
Op: "readdir",
Path: name,
Err: fs.ErrNotExist,
}
}
if name == "." {
root := v.newRootFS()
return root.ReadDir(-1)
}
es := strings.Split(name, "/")
for _, realPath := range v.paths {
if filepath.Base(realPath) != es[0] {
continue
}
f, err := os.Open(filepath.Join(append([]string{realPath}, es[1:]...)...))
if err != nil {
return nil, err
}
defer func() {
_ = f.Close
}()
return f.ReadDir(-1)
}
return nil, &fs.PathError{
Op: "readdir",
Path: name,
Err: fs.ErrNotExist,
}
}
type virtualFSRoot struct {
realPaths []string
offset int