-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterpreter.go
More file actions
68 lines (56 loc) · 1.63 KB
/
interpreter.go
File metadata and controls
68 lines (56 loc) · 1.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package dynamic
import (
"fmt"
"sync"
"github.com/GoCodeAlone/yaegi/interp"
"github.com/GoCodeAlone/yaegi/stdlib"
)
// Option configures an InterpreterPool.
type Option func(*InterpreterPool)
// WithAllowedPackages overrides the default allowed packages list.
func WithAllowedPackages(pkgs map[string]bool) Option {
return func(p *InterpreterPool) {
p.allowedPackages = pkgs
}
}
// WithGoPath sets the GOPATH for interpreters.
func WithGoPath(path string) Option {
return func(p *InterpreterPool) {
p.goPath = path
}
}
// InterpreterPool manages a pool of Yaegi interpreters.
type InterpreterPool struct {
mu sync.Mutex
allowedPackages map[string]bool
goPath string
}
// NewInterpreterPool creates a new pool with optional configuration.
func NewInterpreterPool(opts ...Option) *InterpreterPool {
p := &InterpreterPool{
allowedPackages: AllowedPackages,
}
for _, opt := range opts {
opt(p)
}
return p
}
// NewInterpreter creates a sandboxed Yaegi interpreter with only the allowed
// standard library symbols loaded.
func (p *InterpreterPool) NewInterpreter() (*interp.Interpreter, error) {
p.mu.Lock()
defer p.mu.Unlock()
opts := interp.Options{}
if p.goPath != "" {
opts.GoPath = p.goPath
}
i := interp.New(opts)
// Load the stdlib — Yaegi loads all of stdlib via Use, but the sandbox
// enforcement happens at source-validation time (ValidateSource), not
// at the interpreter level. We still load stdlib so that the allowed
// packages actually resolve.
if err := i.Use(stdlib.Symbols); err != nil {
return nil, fmt.Errorf("failed to load stdlib symbols: %w", err)
}
return i, nil
}